Re: Passing a regex from a CGI HTML form
by hippo (Archbishop) on Aug 31, 2016 at 17:13 UTC
|
Yes, there is. But doing so would be a massive security hole (because it's effectively arbitrary code execution) which is why nobody does it like that.
Perhaps this is an XY problem? Why do you want to have a user provide a function to your code - can you elaborate?
| [reply] |
|
|
Thank you for the reply. It's a private page used by me and a co-worker at work to run a football competition every week for work mates. The data is scraped (manual copy 'n' paste) from a newspaper site and as the data now is produced on the fly, it is in a real mess - my code 'as is' now parses this and puts it in the format we require Now, the issue is, every week or so, they change something, and my parser breaks (which can be fixed easily when I am at home!), but I am at work, so need a way to add new subsitutions on the fly otherwise all hell breaks lose at work when the results are late! Basically, it's just a fail safe 'in case' and NO security issues at all raise their heads as it is only me doing the input :) Thanks, Nick
| [reply] |
|
|
| [reply] [d/l] |
|
|
|
|
|
|
|
Hi Linicks,
Doing an eval or s///ee with a value supplied by a user on an HTML form is the equivalent of giving that user shell access to the machine. You keep saying that only you know the address of the machine, but if security by obscurity is your only security, then one day, for example if your page is discovered by a crawler, that'll mean game over for your server. That's why everyone has been saying to be very careful with eval and security by obscurity, and they are right!
To make one more recommendation because I don't think it's been made yet: At least throw some HTTP digest authentication on there along with the SSL.
Hope this helps, -- Hauke D
| [reply] [d/l] |
|
|
|
|
|
|
|
Re: Passing a regex from a CGI HTML form
by trippledubs (Deacon) on Aug 31, 2016 at 18:03 UTC
|
my $string = "A";
my $command = '$string =~ s/A/B/';
eval $command;
print $string; #B
| [reply] [d/l] |
|
|
use String::Interpolate::RE qw( strinterp );
print Substitution(
"input string",
"pattern",
"replacement",
"flags" );
sub Substitution {
my( $in, $re, $rep, $flags ) = @_;
my $global = $flags =~ m{g}i;
my $qrFlags = join '', $flags =~ m{[msixpodualn]}i;
$qrFlags = "(?$qrFlags)";
$re = qr{$qrFlags$re};
if( $global ){
$in =~ s{$re}{
Replace($rep, \%+,{1=>$1,2=>$2,3=>$3});
}gex;
} else {
$in =~ s{$re}{
my $vars = {
%+, 1=>$1, 2=>$2, 3=>$3,
};
strinterp( $rep, $vars );
}ex;
}
}
sub Replace {
my( $rep, $named, $numed ) = @_;
my $vars = { %$named, %$numed, 'bananas','bananas' );
return strinterp( $rep, $vars );
}
| [reply] [d/l] |
|
|
Seems like these types of modules try to make an explicitly unsafe course of action less unsafe.
From String::Interpolate::RE Docs -
This module interpolates variables into strings using regular expression matching rather than Perl's built-in interpolation mechanism and thus hopefully does not suffer from the security problems inherent in using eval to interpolate into strings of suspect ancestry.
From String::Interpolate Docs -
Because the Perl string interpolation engine can call arbitrary Perl code you do not want to want to use it on strings from untrusted sources without some precautions. For this reason String::Interpolate objects can be made to use Safe compartments. This is, of course, only as safe as Safe and you are advised to read "WARNING" section of the Safe documentation.
Your code did not compile for me, but I guess the point is to try and override the substitution operator with some subset of safer features. I acknowledge that could be successful, but also the op could just use eval in any context where all user input is trusted and be fine. The OP is troubleshooting his gambling code on the clock here so every second counts.
| [reply] |
|
|
|
|
|
|
|
Also good idea to add no re 'eval'; in that sub
| [reply] [d/l] |
|
|
Thanks, but that doesn't quite work I need both what to replace and what with, i.e. I could have to input to a $var 's/ ... ,g/ g/g;' etc. Nick
| [reply] |
|
|
OK, seeing as I am 57 in a few months, looks like a lot of people are protecting me ;) Here follows 2 examples of the junk I need to format:
SWA vs CHE GK
WBA @ BOU GK
That is easy to parse and render clean, as all I need is to extract is "SWA,GK" or "WBA,GK" in that example: $line =~ s/ vs ... /,/;
$line =~ s/ \@ ... /,/;
Now, the 'vs' and '@' are (seem) randomly dispersed ~ whether that is a product of the newspapers website database or crappy programming, I don't know. But this week, this appeared in about 50 places over 4000 lines:
EVE GK
OK, my code failed on this. I could see what has happened, but couldn't fix it at work. If I did have a debug option to pass over a new regex, I could send a '$line =~ s/ GK/,GK/;' which would have fixed it up until I got home (as it was, I frigged around in a spreadsheet to correct it to keep the wolves at bay). Nick | [reply] [d/l] [select] |
|
|
|
|
Re: Passing a regex from a CGI HTML form UPDATE
by Linicks (Scribe) on Sep 04, 2016 at 09:54 UTC
|
if (length ($request{'find'}) > 0 ) {
$find=$request{'find'};
$replace=$request{'replace'};
while ($line =~ m{(.*)$find(.*)}){
$line = $1 . $replace . $2;
}
}
Nick | [reply] [d/l] |
|
|
Yes, that looks a good deal better - assuming you are running in taint mode.
Now try and break it. :-)
| [reply] |
|
|
Yes, running with -T option. All looks good, haven't broken anything yet ;) It is perfect for what I need, as it will only be simple substitutions required anyway (when they happen) just to keep the parser working when at work. Thanks everybody for their help and input on this subject, I learnt a lot Nick
| [reply] |
Re: Passing a regex from a CGI HTML form [SOLVED]
by Linicks (Scribe) on Sep 01, 2016 at 18:01 UTC
|
OK, I changed tact and looked for a way to use $var's in the substition. I found a post on stackoverflow that works 'perfectly' for my precise requirements. On the HTML form, have two 'input type="text"' boxes. One is for the text to find, the second is for the text to replace. The perl code is as follows:
if ($request{'find'} && $request{'replace'}) {
$find=$request{'find'};
$reptemp=$request{'replace'};
$replace='$reptemp';
$line =~ s/$find/$replace/ee;
}
Bingo, all works great, and no "Danger, Will Robinson" type stuff :) Nick | [reply] [d/l] |
|
|
| [reply] |
|
|
Yes, but the code is simple. Secondly, all you need is a bit of 'magic' in the 'find' text box that the code looks for. If it exists then strip the 'magic' and proceed - if not, exit; Also, as I keep reiterating, this is a private page, on my own server, using my own code, with a hidden page that only I know ~ there really is no danger, Will Robinson'. I am not stupid. Nick
| [reply] |
|
|
|
|
|