Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks

I'm looking at the Locale::Maketext code and came across this in the _compile method (line 435 onwards in Maketext.pm):

if(length $c[-1]) { # Now actually processing the preceding literal $big_pile .= $c[-1]; if($USE_LITERALS and ( (ord('A') == 65) ? $c[-1] !~ m<[^\x20-\x7E]>s # ASCII very safe chars : $c[-1] !~ m/[^ !"\#\$%&'()*+,\-.\/0-9:;<=>?\@A-Z[\\\]^_`a-z{|} +~\x07]/s # EBCDIC very safe chars )) { # normal case -- all very safe chars $c[-1] =~ s/'/\\'/g; push @code, q{ '} . $c[-1] . "',\n"; $c[-1] = ''; # reuse this slot } else { push @code, ' $c[' . $#c . "],\n"; push @c, ''; # new chunk }
I'm wondering why potentially unsafe characters are handled differently in the above code?

Since this is extracting string literals from an external source for a later eval, would the following generalized code be safe:

my $literal = <DATA>; $literal =~ s/\\*'/\\'/g; # later on... # There may be a number of literals in reality - # each would be single quoted to prevent interpolation my $string = eval "'$literal'"; __DATA__ this could be \'; system("ls -la");\'
IE, the above code could look something like this instead:
if(length $c[-1]) { # Now actually processing the preceding literal $big_pile .= $c[-1]; $c[-1] =~ s/\\*'/\\'/g; push @code, " '$c[-1]',\n"; $c[-1] = ''; # reuse this slot }
This isn't a criticism of L::Maketext, rather I'm just curious to know if there are situations where evaling a single quoted literal with all single quotes escaped might still cause accidental interpolation.

Can anyone suggest security problems with this - if you can give a simple example to illustrate, even better. BTW, I appreciate that the noddy example code I've provided doesn't need eval - its just there as a simple example.

Thanks

Replies are listed 'Best First'.
Re: Safe eval of string literals?
by rinceWind (Monsignor) on Aug 19, 2003 at 16:32 UTC
    When I see code that passes externally supplied strings through eval, it fills me with trepidation.

    When it comes to 'safe' strings, a lot depends on how much you can trust the source of the strings. If your code is only ever being used inside a corporate development environment, you probably don't need to worry.

    The extreme case is if you are receiving strings for eval as parameters in a CGI script, and some cracker gets in there and trashes your system. (For example 'system("rm -rf /");' This is what taint mode was invented for.

    I thoroughly recommend Ovid's CGI course, which contains a full discussion of the security aspects involved in validating external strings.

Re: Safe eval of string literals?
by simonm (Vicar) on Aug 19, 2003 at 17:34 UTC
    I'm just curious to know if there are situations where evaling a single quoted literal with all single quotes escaped might still cause accidental interpolation.

    After further thought, yes -- they could use backslash escapes to encode a single quote; for example, $literal could contain \x27; print system('ls -la'); \x27.

    Update: Or not, as pointed out below -- I had rigged my test case a bit differently than the OP and went off on a tangent somewhere...

      Thanks for the replies, but have you actually tried it?
      my $literal = <DATA>; $literal =~ s/\\*'/\\'/g; # later on... # There may be a number of literals in reality - # each would be single quoted to prevent interpolation my $string = eval "'$literal'"; print $string, "\n"; __DATA__ this could be \x27; print system('ls -la'); \x27
      On my machine:
      >perl testcode.pl this could be \x27; print system('ls -la'); \x27
      Since the string is evaled within single quotes: "'$literal'", \x{} notated characters shouldn't get interpreted. Of course it's essential to escape single quotes, or nasty things can easily get through, and it's especially important to handle escaped single quotes or stuff like "\'; print system("ls -la"); \'" would slip through.

      From comments a few others have made on other mailing lists, Safe.pm seems to be a great idea, but in reality it has limitations and isn't as secure as it should be - it also adds an overhead that I could do without.

      With regards to rinceWind's reply - we're talking about l10n data loaded from 'internal' sources (eg. program resources installed locally or on the local network), so CGI and data tainting isn't a particularly useful model. I didn't make that clear enough, so sorry about that. Of course, if a sysadmin installs a rogue app without thinking (never!), it's still nice to limit/prevent damage caused by hacked .PO or .MO files, which is why I'm asking about it here :)

      Thanks for the replies so far, and keep 'em coming!

Re: Safe eval of string literals?
by simonm (Vicar) on Aug 19, 2003 at 17:11 UTC
    If you're not 100% sure that your string to eval is safe, just use a Safe partition.
    require Safe; my $string = Safe->new->reval("'$literal'");

    Safe disables many of the potentially dangerous Perl op codes, so that even if someone manages to sneak a curiously-formatted piece of code past your parser/escaper, it's unable to do anything particularly malicious. (For example, it might be able to suck up an inordinate amount of CPU time, but it won't be able to reformat your hard drive.)

    This is a very powerful capability, and I don't know why Perl developers don't take advantage of it more often...