Preface
A file inclusion vulnerability is a type of vulnerability that is most commonly found to affect web applications that rely on a scripting run time. This issue is caused when an application builds a path to executable code using an attacker-controlled variable in a way that allows the attacker to control which file is executed at run time. If a file contains this loophole ot often was implemented in the development stage for convenience. Because it is often used in development and later forgotten, it has become the target of multiple attacks and has resulted in a variety of file-based attacks.
Local file inclusion
First of all, when the value can directly be be controlled we have a very similar code snippet as below present:
<? php
$ file = $ _GET ['file'];
include ($ file);
If we can find the above code, there is a directly included $file
, which we have control over.
Note: The file can be anything. It is included no matter if it’s an exptected file type, a picture, or anything arbitrary.
First of all in the current folder create an arbitrary file with any suffix, such as: file.txt
(even if it is a picture format like file.jpg then the following effect takes place).
Set the contents of the file as:
<? php
phpinfo ();
File Inclusion Vulnerabilities also contain other files within the current server while supporting directories that contain web
applications, as follows:
Try to include some of the contents of your HDD for example: C:\WINDOWS\system.ini
If we do this, we can see that the contents of any file will be outputted to the browser.
This only works if we have total control and the file type is not further specified.
So what can we do if the code snippet changes to this:
<?php
$file = $_GET['file'] . '.php';
echo $file;
include($file);
In this case, we can try to follow the method above:
This will result in an output like this:
We can see that if the suffix is fixed, then just like in the figure above, we will not find the file we included earlier.
The searched for filename is: ./Include.txt.php
.
So here’s another way to do that: %00
truncates a string upon reaching.
This trick is widly spread and used in different areas as well.
I won’t go into any more detail here .
I recommend checking out online ressources like this!
Using %00
in PHP:
- PHP version <5.3 (excluding 5.3);
PHPmagic_quotes_gpc = off
;
PHP does not use the addslashes function for the received parameters, such as `$ _GET [‘file’] in the above code
In PHP version 5.3 or later this issue has been fixed.
The sequence will be correctly escaped if gpc
is turned on or the addslashes
function is used.
First of all, we can try what happens if the gpc
is turned on (the effect is the same as using the function)
We can directly see how this case is handled if we enable the gpc
flag.
Next we take a look at the situation in 5.3:
There is no noticeable effect here either.
So we can see that as long as the above three conditions are satisfied, %00
can be used.
First we change the PHP version to 5.2 and restart Apache
after php.ini
changes magic_quotes_gpc = on
to magic_quotes_gpc = off
.
This enables us to use truncation when attempted.
We can see that we have successfully made use of truncated inclusion.
So does the file only contain the included functions?
That is certainly not the case, since we have control of what can be included let’s do this .
Let’s create a file: shell.txt
to further exploit this vulnerability.
We can see, including shell
is not a problem either.
So what is the difference between the two? In fact, there is no difference, the principle is the same, but the first is introduced with the suffix, the second is fixed in the program dead suffix. But % 00
can be used because it terminates directly when the program stream encounters% 00
terminator.
remote file inclusion
The local file contains the same principle as the remote file, except that the former can only contain the files that exist on the server, and the latter can contain the files on the remote server.
For remote files we need to consider the following:
- Need
allow_url_include = on
andallow_url_fopen = on
inphp.ini
- The required remote file suffix cannot be the same as the target server’s language, such as (the target server parses PHP code, then the remote file suffix can not be
.php
)
Let me explain the second point.
If your remote file has .php
suffix and your remote file content is something like:
<? php
phpinfo ();
Then the contents of the target server are obtained after your remote server executes phpinfo()
It will not run the code, so the information contained is not the target server but your remote server.
This is illustrated below:
This is my remote machines information for PHP5.6 version, the target machine is version 5.2.
Next we include the file!
We can see that after the file is included, our remote machine changed! why??
Because the target server does not contain the this code:
<? php phpinfo ();?>
Instead, the remote server executes the source code of this code, as shown below:
So to make this attack work we need to make a few modifications:
1.Modify the configuration
2.Modify the file suffix
Let’s try the include attack vector again:
We can see the desired information got returned after this inclusion and our target machine information did not change anymore.
Next up we want to do the shell example again for the remote file inclusion
Remote file contains the use of the premise is in line with the local file contains the premise and meet the remote file contains the premise of its availability.
File contains on of many pseudo-protocols
There can be quite a few different pseudo-protocols contained in a file.
I’ll demonstrate a few of them below.
data:text/plain
or data: text/plain; base64
php://input
php://filter
file://
zip://
Other protocols can looked up in the official documentation
data:text/plain
Output is directly in the corresponding URL showing the parameters: data:text/plain
.
Then we need to execute the php code as shown below:
data: text/plain; base64
For data: text/plain; base64` there is another way to use it.
We need to execute PHP code using base64 encoding: the base64php code is as shown below:
php://input
php://input
accesses the read-only stream of the requested raw data, executing the data in the post request as PHP code.
You can see that the program has automatically an added .php
suffix.
Hence using include php://input
will automatically add .php
so it is certainly not working properly.
We can come back to the nifty little %00
trick to truncate the file path!
You can see the terminator is very powerful.
php://filter
php://filter
can read the php file code base64 encoded output and return it to us.
For example, we want to read a php file but do not want it to be normal php.
Usage: php://filter/read=convert.base64-encode/resource=
../ressource=
needs to read the contents of the file code
After decoding the base64 we can get the contents as usual:
file://
file://
is used to access the local file system and is not affected by allow_url_fopen
or allow_url_include
.
Usage: file://absolute/path/to/file
zip://
zip://
can access the files in a zip file. But it needs an absolute path.
Usage: zip://[archive absolute path] # [compressed file name]
Create a file locally and compress it into a zip archive.
You can see that I have already filled in the absolute path and the name of the file.
Why we cannot include it successfully shows the error:
Warning: include (
zip://C:/phpStudy/WWW/include/phpinfo.zip.php
)
We do not want to include this file, instead we want to include the file inside the zip!
Why is the value after #
gone?
Because #
will ignore the parameters behind it, so we need to use the %23
in the form.
Another point is that the included file ends in a .php
, but we compressed the file for the php suffix.
So we do not need to have this suffix, as shown below:
PS:My English is not good, please understand!