概述
在 Web 后台开发中,程序员往往为了提高效率以及让代码看起来更加简洁,会使用 “包含” 函数功能。比如把一系列功能函数都写进 function.php 中,之后当某个文件需要调用的时候直接在文件头中写上一句 <?php include function.php?>就可以调用函数代码。
但有些时候,因为网站功能需求,会让前端用户选择需要包含的文件(或者在前端的功能中使用了“包含”功能),又由于开发人员没有对要包含的这个文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意文件(代码)。这种情况称为“文件包含漏洞”。
文件包含漏洞有“本地文件包含漏洞”和“远程文件包含漏洞”两种。
low级别
源代码:
<?php // The page we wish to display $file = $_GET[ 'page' ]; ?>
可以看出,low级别什么安全措施都没有做,可以进行任意代码执行!
本地文件包含
我们可以通过在URL中运行"../"根目录跳转方式,获取服务器上的信息,填写多个"../"可以直接跳转到根目录(注:服务器系统不同,payload也会不同,但都可以通过根目录跳转方式获取信息)
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=../../../../../../../../etc/passwd
运行URL后浏览器界面会显示服务器的信息
远程文件包含
当服务器的php配置中,选项allow_url_fopen与allow_url_include为开启状态时,服务器会允许包含远程服务器上的文件,如果对文件来源没有检查的话,就容易导致任意远程代码执行。
上传一个文件到服务器上,这个文件可以获取服务器的IP地址和PHP的信息
然后构造一个URL
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=http://127.0.0.1/phpinfo.txt
执行这个URL后,可以获取到想要的信息
Medium级别
源代码:
<?php // The page we wish to display $file = $_GET[ 'page' ]; // Input validation $file = str_replace( array( "http://", "https://" ), "", $file ); $file = str_replace( array( "../", "..\"" ), "", $file ); ?>
从源代码中,可以看出,它把“http://”、“https://”、“../”、“..\”这些替换为了空白符,也就是删除,不可用了。
本地文件包含
使用low级别的跳转方式是不行的,因为他已经限制了使用“../”,我们可以利用源代码中限制路径符号使用的漏洞来获取我们想要的信息。
因为它会把“../”删除掉,而“..././”这个符号会因为其中的“../”被删除,就会变成"../",我们可以通过这种方式来构造payload实现绕过
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=..././..././..././..././..././..././etc/passwd
因为它只限定URL相对路径,所以它的绝对路径是不受影响的,比如Windows系统的绝对路径C:/xampp/htdocs/dvwa/php.ini,Linux系统的/var/www/html/dvwa/php.ini,这些绝对路径都是可以使用的!
远程文件包含
使用low级别的方法也是不行的,我们可以像本地文件包含的方法一样,利用它替换的漏洞来构造payload实现绕过,“hthttp://tp://”被删除后就会变成“http://”
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=hthttp://tp://127.0.0.1/phpinfo.txt
文件执行成功
High级别
源代码:
<?php // The page we wish to display $file = $_GET[ 'page' ]; // Input validation if( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit; } ?>
从源代码可以看出,它使用了fnmatch函数,规定page参数的值开头必须是file,才会允许去包含相应的文件。
这样设定,看似安全,其实我们是可以利用file协议来绕过它的防护策略
file协议就是在URL中输入file:///+文件的绝对路径,浏览器就会打开本地文件
我们可以保存一个文件在本地,然后通过浏览器打开这个文件
接下来可以通过这个文件的URL来构造一个payload
127.0.0.1/dvwa/vulnerabilities/fi/?page=file:///var/www/html/phpinfo.txt
payload执行成功
Impossible级别
源代码:
<?php // The page we wish to display $file = $_GET[ 'page' ]; // 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!"; exit; } ?>
从源代码中,可以看出,它使用了白名单防护的机制,page的值必须为“include.php、file1.php、file2.php、file3.php”这几个文件,彻底杜绝了文件包含漏洞!