SQL injection 2.0: Regular Expression injection

Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.

SQL injections are well-known and could easily be used against against most PHP scripts, but there is a much easier injection leak in many Perl scripts: Regular Expression injection.It's not PHP itself, but it's the way many, many PHP pseudo-developers write source trying to avoid thinking about what they're doing.

SQL injection is simple:

SELECT * FROM users WHERE username="$username"
" OR 1 OR "x" = "x
as username into the login form will turn the query into:
SELECT * FROM users WHERE username="" OR "x" = "x"
Simple way of logging into a foreign server without any valid credentials. Yes, typically password checks also occur, but passing another SQL injection string as password is easy.

I think hope that Perl users know of SQL placeholders or unpack:

$dbh->selectrow_hashref('SELECT * FROM users WHERE username=0x'.unpack('H*',$username));
- or -$sth = $dbh->prepare('SELECT * FROM users WHERE username=?');$sth->execute($username);
Simple, isn't it?

But Perl has a big injection hole itself:

for my $key (keys %in) {   $html =~ s/\$$key/$in{$key}/g;}
Looks common to you? But what happens if someone passes
(?{system "rm -rf /";})
as a GET argument variable name? (?{ code }) is experimental RegEx stuff, but it's valid and will execute everything between { } as Perl source.The solution is much easier than the SQL fix:
for my $key (keys %in) {   $html =~ s/\$\Q$key\E/$in{$key}/g;}
...or use quotemeta() to escape everything in $key. \Q and \E will ignore any control char in $key. Yes, it's that simple!

Here is a oneliner to try it out:

perl -le '/(?{ print keys %ENV; })/;'

4 Kommentare. Schreib was dazu

  1. Clinton


    The docs in{-code-}%29 say:

    For reasons of security, this construct is forbidden if the regular expression involves run-time interpolation of variables, unless the perilous use re 'eval' pragma has been used

    which seems to guard against the problem illustrated in your example. Or am I missing something?

  2. Sebastian

    You're right, my sample won't work in real work, but our request processor is also Perl and does many nasty things with the data before it reaches the final script. I won't rely on it to be that safe that Perl could always identify the source of a variable contents.
    I tried to make people think about what they write. Some days ago I got a ticket because a script crashed when being called with the (wrong) input variable "user[=12345". It might be bad teaching but telling people "Hey, anybody could execute any Perl source" gets more attention than "hey, someone could crash your script", especially where some developers don't read emails like this at all. :-)

  3. Anonymous

    Clinton: it works just fine without use re qw(eval). Proof: perl -Mstrict -Mwarnings -E'my $html = 1; $html =~ s[(?{system "touch /tmp/did_it_work"})][];'

  4. Sebastian

    Clinton pointed out that Perl doesn't allow external data to be used:
    $ perl -le '/$ARGV[0]/;' '(?{system "whoami"})'
    Eval-group not allowed at runtime, use re 'eval' in regex m/(?{system "whoami"})/ at -e line 1.

Schreib was dazu

Die folgenden HTML-Tags sind erlaubt:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>