1. Attempting PHP Include File Injection Interactively
1.1. Problem
When PHP Hypertext Processor is used as a server-side scripting
engine, an attacker can carry out several types of attacks if the
application developer is not careful. One particularly dangerous attack
is PHP Include file injection where
the attacker can cause the web server to download and run arbitrary
code. This test will try to determine whether your application written
in PHP will download arbitrary code specified by the attacker and
execute it.
1.2. Solution
First, determine whether PHP is being used by the application. One
indicator is URLs that reference resources with the extensions php, php3,
and php4, for example: http://www.example.com/home.php?display=5. If
it is not clear whether PHP is being used by the application, you will
need to ask the development team.
Example 1. Test input for finding PHP include file injection
vulnerability
http://host:port/xyzzy_php_test
|
Of course, host is the
hostname or IP address of the web server you set up and port is the port number on which the web
server is listening. Then, search the access logs and error logs at
host for the string xyzzy_php_test. If the string is in the logs,
then the page being tested is trying to retrieve the file from your web
server and is vulnerable to PHP injection.
1.3. Discussion
This attack works because the PHP include() and require()
functions can read files from the local filesystem as well
as from a remote location. If some PHP code in the application takes a
variable input by the user and then passes it to include() or require() functions as in the following code,
then the user can manipulate the variable in ways that the developer did
not intend. Example 2 shows a line of PHP that would be
vulnerable to this attack if the $userInput variable
is not carefully sanitized before the require()
function is called.
Example 2. Sample line of code vulnerable to PHP include file
injection
require($userInput . '.php')
|
The developer may have tried to restrict $userInput by using radio buttons in an HTTP
page, for example, but you can of course bypass client-side controls and
provide any value you like. Thus, if the attacker provides the string in
Section 12.9.2 as the variable $userInput, then the code will attempt to
fetch the file http://host:port
/xyzzy_php_test.php and
will execute the PHP code in the retrieved file.
Note that PHP code may retrieve values of GET or POST variables or
even HTTP cookie values and use them in the manner discussed earlier.
Modifying GET values can be accomplished simply by modifying the URL.
There are many other types of PHP injection attacks, but they are
less common, and are not discussed here. A Google search for “PHP
injection” will reveal the other types of PHP injection attacks.
2. Creating Decompression Bombs
2.1. Problem
A decompression bomb is a compressed file that is very small but expands to a
disproportionately large amount of data. This recipe will
discuss how such decompression bombs can be created. If your application
processes compressed files (.zip,
.jar, .tar.gz, .tar.bz2, etc.), you can use this recipe to
generate pathological compressed files that can be used to ensure that
your application handles such malicious input gracefully.
2.2. Solution
The program in Example 3
will generate a zip of death . You can substitute other
compression utilities instead of zip
to create other types of decompression bombs (e.g., bzip2).
Example 3. Perl script to create decompression bomb
#!/usr/bin/perl
use File::Copy;
$width = 17; $depth = 6; $tempdir = '/tmp/dec_bomb'; $filename = '0.txt'; $zipfile = 'bomb.zip'; chdir($tempdir) or die "unable to change directory to $tempdir $!";; createInitialFile(); createDecompressionBomb();
sub createInitialFile { my $file = $filename; my $i = 0; open FILE, ">$file" or die "unable to open $file $!"; # The largest file that current versions of 'zip' will compress is 4GB (minus 1 byte) for ($i = 0; $i < (1024*4)-1; $i++) { print FILE '1'x1048576; } print FILE '1'x1048575; close FILE; `zip -rmj9 $depth-0.zip $filename` }
sub createDecompressionBomb { my $d = 0; my $w = 0; for ($d = $depth; $d > 0; $d--) { if ($d < $depth) { `zip -rmj9 $d-0.zip *.zip`; } for ($w = 1; $w < $width; $w++) { copy($d . '-0.zip', $d . '-' . $w . '.zip') or die "unable to copy file $!"; } } } `zip -rmj9 $zipfile *.zip`;
|
2.3. Discussion
You can easily create decompression bombs of arbitrary sizes even
if you do not have that amount of storage available yourself. This
script only requires sufficient storage for one file of size 4
gigabytes, as well as one file of size 4 megabytes while it runs,
whereas if one were to decompress the entire archive, it would
decompress to 96,550 terabytes. That ought to be sufficient to fill up
the disk space on any server.
You should be careful about where you create the decompression
bomb. Since it is meant to crash programs such as virus scanners, you
can easily crash such programs on your own system and maybe even make
your system unresponsive. You should obviously not try to decompress the
file yourself.
The script in Example 3 takes
a few minutes to run with the given $depth and $width. Be careful about increasing the
values; the size of the decompression bomb increases very quickly. Since
the default values will fill up the disk space on any server if the
archive is fully extracted, it should not be necessary to increase these
values. It would be more beneficial to reduce the values to say $depth=5 and $width=2 to create an archive that would
expand to 128 gigabytes. On a server with more than 128 gigabytes of
available disk space, that will ensure that if your application is
vulnerable to decompression bomb attacks, it will slow to a crawl, but
will not crash. Thus, the test will be less destructive.
If upon uploading a decompression bomb the application slows to
a crawl or becomes unresponsive, it fails the test and is vulnerable to
decompression bomb attacks.