1.原理
文件包含漏洞的产生原因是在通过 PHP 的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
2.php 中引发文件包含漏洞的通常是以下四个函数
1、include() 当使用该函数包含文件时,只有代码执行到 include() 函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。
2、include_once() 功能和 include() 相同,区别在于当重复调用同一文件时,程序只调用一次。
3、require() 只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行
4、require_once() 它的功能与 require() 相同,区别在于当重复调用同一文件时,程序只调用一次。
当使用这四个函数包含一个新文件时,该文件将作为 PHP 代码执行,php 内核并不在意该被包含的文件是什么类型。所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。这一特性,在实施攻击时非常有用。
3.分类
文件包含漏洞可以分为 RFI (远程文件包含)和 LFI(本地文件包含漏洞)两种。而区分他们最简单的方法就是 php.ini 中是否开启了allow_url_include。如果开启 了我们就有可能包含远程文件。
1、本地文件包含 LFI(Local File Include)
2、远程文件包含 RFI(Remote File Include)(需要 php.ini 中 allow_url_include=on、allow_url_fopen = On)
在 php.ini 中,allow_url_fopen 默认一直是 On,而 allow_url_include 从 php5.2 之后就默认为 Off。
4.利用条件
(1) include 等函数通过动态执行变量的方式引入需要包含的文件;
(2)用户能控制该动态变量。
5.利用方式
1、包含一些敏感的配置文件,获取目标敏感信息
2、配合图片马getshell
3、包含临时文件getshell
4、包含session文件getshell
5、包含日志文件getshell(Apach、SSH等等)
6、利用php伪协议进行攻击
6.防御方式
1.设置白名单
代码在进行文件包含时,如果文件名可以确定,可以设置白名单对传入的参数进行比较。
2.过滤危险字符
由于Include/Require可以对PHP Wrapper形式的地址进行包含执行(需要配置php.ini),在Linux环境中可以通过”…/…/”的形式进行目录绕过,所以需要判断文件名称是否为合法的PHP文件。
3.设置文件目录
PHP配置文件中有open_basedir选项可以设置用户需要执行的文件目录,如果设置目录的话,PHP仅仅在该目录内搜索文件。
4.关闭危险配置
PHP配置中的allow_url_include选项如果打开,PHP会通过Include/Require进行远程文件包含,由于远程文件的不可信任性及不确定性,在开发中禁止打开此选项,PHP默认是关闭的。
7.绕过方式
1、%00 截断
?file=…/…/…/…/…/…/…/…/…/etc/passwd%00
PHP 内核是由 C 语言实现的,因此使用了 C 语言中的一些字符串处理函数。在连接字符串时,0 字节 (\x00) 将作为字符串的结束符。所以在这个地方,攻击者只要在最后加入一个 0 字节,就能截断 file 变量之后的字符串。
2、%00 截断目录遍历
?file=…/…/…/…/…/…/…/…/…/var/www/%00
需要 magic_quotes_gpc=off,unix 文件系统,比如 FreeBSD,OpenBSD,NetBSD,Solaris
3、路径长度截断
?file=…/…/…/…/…/…/…/…/…/etc/passwd/././././././.[…]/./././././.
php 版本小于 5.2.8 可以成功,linux 需要文件名长于 4096,windows 需要长于 256
利用操作系统对目录最大长度的限制,可以不需要 0 字节而达到截断的目的。
我们知道目录字符串,在 window 下 256 字节、linux 下 4096 字节时会达到最大值,最大值长度之后的字符将被丢弃。
而利用 “./” 的方式即可构造出超长目录字符串:
4、点号截断
?file=…/…/…/…/…/…/…/…/…/boot.ini/………[…]…………
php 版本小于 5.2.8 可以成功,只适用 windows,点号需要长于 256
5、编码绕过
利用 url 编码
…/ -》 %2e%2e%2f -》 …%2f -》 %2e%2e/
…\ -》 %2e%2e%5c -》 …%5c -》 %2e%2e
二次编码:
…/ -》 %252e%252e%252f
…\ -》 %252e%252e%255c
文件后加入特殊字符绕过
利用工具,将访问路径后加入%00,可以绕过后缀检查。
或者后面加一些特殊字符例如 斜杠 点之类。
6.nginx目录解析漏洞
当判断到中间件是nginx时,我们可以利用nginx目录解析,当我们只能上传.jpg文件时,我们无法利用,只能原文读取出来,但是发现在shell.jpg后加/xxx.php,他就能以php方式读取文件,这就是目录解析漏洞。
7.包含日志文件
当我们访问不存在目录时,例如:http://lfi.cn/LFI-1/<?php phpinfo();?>
它会将错误路径保存在日志中。不同的中间件有不同的路径。
日志文件名字为access_log,access.log,error.log,Logfiles等
8.伪协议包含
当不能直接访问目录下文件时,可以选择利用伪协议来访问文件,伪协议有以下几种:(allow_url_fopen和allow_url_include)都为On
(1)page=file://[绝对路径]
当页面有file1,file2……后台会判断是否已file开头,我们可以使用此协议。
(2)php:// 访问各个输入/输出流(I/O streams)
php://filter用于读取源码
php://input用于执行php代码,或者直接将代码写入执行。
(3)zip://[绝对路径], bzip2://[绝对路径], zlib://[绝对路径]协议,都属于压缩楼,访问压缩文件中的子文件,不需要指定后缀
phar:// 可以查找指定压缩包内的文件,相对路径与绝对路径都可以写
(4)data: text/plain,<?php 执行内容 ?>与input类似,当我们想查看源代码时,可以将其先转换为base64文件在传到页面上就不会执行PHP了
(5)http协议
也可以传入外部链接,自己服务器的钓鱼网站。