文件包含(File Inclusion):是指页面利用url去动态包含文件(include或require等),当文件名参数可控但又过滤不严的时候,就容易被利用。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。
DVWA实战:
1. 打开phpStudy或xampp,运行Apach和mysql,这里要特别打开php的allow_url_include选项:点击面板“其他选项菜单”->PHP拓展及设置->参数开关设置->勾选“allow_url_include”;
2. 浏览器进入DVWA主界面,在左侧栏选择DVWA Security安全等级为Low,然后进入File Inclusion;
我们看到页面上有三个文件选项,当我们点击其中一个时,页面会显示该文件的内容,同时我们看到url变成了:
http://localhost/DVWA-1.9/vulnerabilities/fi/?page=file1.php
3. 那么如果我们改变page的参数,是不是就能获得其它文件?我们试着将参数改为page=../../phpinfo.php,结果我们顺利的得到了该页面的信息:
这样,我们就利用了文件包含的漏洞,获取了本不应该呈现给我们的页面。如果我们查看后台源码的话,我们会发现其中就一句话:
$file = $_GET[ ‘page‘ ];
没有任何的过滤,参数名又可控,就形成了文件包含漏洞。
4. 我们把安全等级调为medium,采用同样的方法,发现失效了。如果我们看后台源码,发现多了两行过滤控制:
// Input validation $file = str_replace( array( "http://", "https://" ), "", $file ); $file = str_replace( array( "../", "..\"" ), "", $file );
即将”http:// ”、”https://”、 ” ../”、”..\”过滤掉,替换成为空字符。这让我们想起了在命令注入那节中,也采用了对关键命令过滤的方式,因此这启发了我们可以构造....//的方式,过滤掉其中一个,剩下的刚好能用,例如修改page=....//....//phpinfo.php,同样获得了之前的结果。
5. 接下去我们试试high等级的文件包含,发现采用上述的方法,报错:ERROR: File not found!,查看后台源码,发现使用了fnmatch函数检查page参数,要求page参数的开头必须是file。
if( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn‘t the page we want! echo "ERROR: File not found!";
既然如此,那我们只要让参数开头是file就行啦,构造如下url参数:
page=file:///E:/Development/KPlayer/Web/PHP/phpStudy/WWW/DVWA-1.9/phpinfo.php
就能同样得到之前的页面。
6. 最后我们来看看impossible安全等级,发现之前的方法都不管用,查看后台源码,发现原来使用了白名单机制,page参数必须为“include.php”、“file1.php”、“file2.php”、“file3.php”之一,杜绝了文件包含漏洞。
// Only allow include.php or file{1..3}.php if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) { // This isn‘t the page we want! echo "ERROR: File not found!";
实战心得:
当服务器开启allow_url_include选项时,会通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。因此有效的方法就是采用白名单的方式,防止这种漏洞。