资讯动态

Reflected Cross Site Scripting(XSS)反射型跨站脚本漏洞:用户输入回显缺陷与 DVWA 分级绕过实战

发布时间:2026/8/14 13:13:17 来源:尧图企业网站定制
Reflected Cross Site ScriptingXSS反射型跨站脚本漏洞用户输入回显缺陷与 DVWA 分级绕过实战前言1. Reflected XSS 核心理论基础1.1 什么是反射型 XSS1.2 反射型 XSS 的本质1.3 反射型 XSS 成立的必要条件1.4 Reflected XSS、Stored XSS 与 DOM XSS 的区别1.5 XSS 可能造成什么危害2. DVWA Reflected XSSLow2.1 页面黑盒探测2.2 漏洞利用原理2.3 源码审计无过滤直接回显3. DVWA Reflected XSSMedium3.1 页面黑盒探测3.2 黑名单绕过思路3.3 源码审计简单字符串替换的缺陷4. DVWA Reflected XSSHigh4.1 页面黑盒探测4.2 黑名单与正则过滤为什么仍然不可靠4.3 黑盒绕过测试与Payload4.4 源码审计正则过滤不等于安全编码5. DVWA Reflected XSSImpossible5.1 源码审计5.2 为什么输出编码才是正确修复方式5.3 Impossible 级别安全总结6. XSS 防护的正确姿势6.1 第一原则根据输出上下文进行编码6.2 不要使用黑名单修复 XSS6.3 必须支持富文本时使用白名单净化方案6.4 CSP 可以降低风险但不能代替修复漏洞7. DVWA Reflected XSS 四个等级对比8. 总结免责声明前言今天继续 DVWA Web 漏洞靶场系列来学习另一个 Web 安全中出现频率极高、影响范围极广的经典漏洞——Reflected Cross Site Scripting反射型跨站脚本简称 Reflected XSS。如果说 SQL 注入是让攻击者影响数据库查询逻辑命令注入是让攻击者影响服务器操作系统那么 XSS 的目标则是——让攻击者控制其他用户浏览器中的页面行为。一旦 XSS 利用成功攻击者注入的 JavaScript 代码会在受害者浏览器中以目标网站的身份和权限运行。轻则弹窗、篡改页面内容重则可能造成钓鱼、会话劫持、敏感信息读取、账户操作诱导等问题。XSS 的核心原理同样很简单Web 应用将用户可控输入直接输出到 HTML 页面中却没有进行正确的上下文编码导致浏览器把输入内容当成 HTML 标签或 JavaScript 代码解析执行。DVWA 的 Reflected XSS 靶场正好通过 Low、Medium、High、Impossible 四个安全等级完整展示了“无过滤 → 黑名单过滤 → 正则过滤 → 输出编码”的防护演进过程。1. Reflected XSS 核心理论基础1.1 什么是反射型 XSS反射型跨站脚本漏洞Reflected Cross Site Scripting对应常见漏洞编号CWE-79Improper Neutralization of Input During Web Page GenerationWeb 页面生成过程中对输入未进行正确处理反射型 XSS 的典型特征是攻击者构造恶意参数参数通过 URL 查询字符串、表单提交等方式发送给服务器服务器将该参数“反射”回响应页面浏览器解析页面时执行攻击者注入的脚本恶意内容通常不会被永久保存到数据库中。例如某页面存在一个姓名参数http://dvwa.local/vulnerabilities/xss_r/?nameAlice后端将参数直接拼接进页面echoHello .$_GET[name];正常访问时页面显示Hello Alice但如果用户输入中包含可被浏览器解析的标签或事件处理代码并且后端没有进行安全编码浏览器就可能把它当作页面的一部分执行。1.2 反射型 XSS 的本质反射型 XSS 的漏洞链路可以概括为攻击者可控输入 ↓ URL 参数 / 表单参数 / 请求头等 ↓ 后端未正确过滤或未进行输出编码 ↓ 输入被拼接到 HTML 响应页面 ↓ 浏览器将输入当作 HTML / JavaScript 解析 ↓ 恶意脚本在目标站点上下文中执行最关键的问题不在于“用户输入了script”而在于服务器没有区分“普通文本”和“浏览器可执行的 HTML 内容”。开发者原本希望页面显示的是一段文字但浏览器最终接收到的却是一个真正的标签、属性或脚本片段。1.3 反射型 XSS 成立的必要条件并不是所有能回显输入的页面都会产生 XSS。通常需要同时满足以下几个条件。条件一攻击者能够控制某个输入点常见输入来源包括URL 查询参数例如?namexxxGET、POST 表单参数搜索框内容错误提示中的参数跳转地址、回调参数HTTP 请求头中的 Referer、User-Agent 等条件二输入会被输出到页面中例如echo$_GET[name];或者echodiv搜索结果.$_GET[keyword]./div;只要用户输入最终出现在 HTML 响应内容中就需要进一步判断输出位置和编码方式。条件三输出时没有进行正确的上下文编码错误示例echopreHello{$name}/pre;安全的文本输出应当进行 HTML 编码echopreHello .htmlspecialchars($name,ENT_QUOTES|ENT_SUBSTITUTE,UTF-8)./pre;经过htmlspecialchars()处理后、、、等特殊字符会被转换为 HTML 实体浏览器只会把它们显示成普通文字而不会当作标签或脚本解析。1.4 Reflected XSS、Stored XSS 与 DOM XSS 的区别XSS 并不只有一种类型最常见的是以下三类类型恶意内容是否持久化触发方式典型场景Reflected XSS反射型不持久化用户访问恶意链接或提交恶意请求搜索页面、报错页面、参数回显页面Stored XSS存储型持久化到数据库或文件其他用户访问已被污染的页面评论区、昵称、留言板、个人资料DOM XSS不一定经过后端前端 JavaScript 直接操作 DOMlocation.hash、前端模板拼接、innerHTML其中反射型 XSS 常常需要攻击者诱导受害者点击一个精心构造的 URL因此它也经常出现在钓鱼链接、伪造通知、社工攻击等场景中。1.5 XSS 可能造成什么危害XSS 并不只是一个“弹窗漏洞”。弹窗只是验证脚本是否执行成功的最直观方式真实风险取决于页面权限、浏览器安全策略、Cookie 属性、站点功能以及受害者身份。常见影响包括篡改页面内容伪造登录框、支付提示或客服窗口诱导用户输入账号、密码、验证码等敏感信息读取页面中本来只有当前用户可见的数据以受害者身份发起页面内可执行的操作窃取未配置HttpOnly的会话 Cookie利用管理员访问的后台页面扩大影响范围配合 CSRF、点击劫持、钓鱼等攻击形成组合攻击链。需要注意的是HttpOnlyCookie 可以降低 Cookie 被 JavaScript 直接读取的风险但它不能修复 XSS 漏洞本身。攻击者依然可能通过页面篡改、操作诱导、读取 DOM 数据等方式造成影响。2. DVWA Reflected XSSLow2.1 页面黑盒探测首先在输入框中提交正常文本Alice观察页面是否将输入内容原样显示。页面显示Hello Alice说明当前输入会被后端接收并回显到 HTML 响应中。下一步需要判断应用是将用户输入作为普通文本显示还是直接交给浏览器解析。在本地 DVWA 授权靶场中可使用一个无害的验证 Payloadscriptalert(document.domain)/script如果浏览器弹出当前站点域名说明输入中的script标签没有被编码浏览器已经把用户输入当成脚本执行。2.2 漏洞利用原理Low 级别的核心问题是用户输入没有经过任何过滤、转义或编码直接被拼接到 HTML 页面中。攻击者提交的内容scriptalert(document.domain)/script后端返回页面时可能形成类似结构preHelloscriptalert(document.domain)/script/pre浏览器在解析 HTML 时不会把script当成普通文本而是会把它识别为真正的脚本标签因此 JavaScript 得以执行。需要特别注意pre标签只能保留文本格式和空白字符并不能阻止内部 HTML 标签被解析。很多开发者误以为把用户输入放进pre、div、p等普通标签中就安全了但只要没有进行输出编码浏览器仍会解析用户输入里的标签。2.3 源码审计无过滤直接回显DVWA Low 级别的核心逻辑通常类似于?phpheader(X-XSS-Protection: 0);// Is there any input?if(array_key_exists(name,$_GET)$_GET[name]!NULL){// Feedback for end userechopreHello .$_GET[name]./pre;}?逐行解读header (X-XSS-Protection: 0);主动关闭浏览器自带的XSS防护避免浏览器拦截测试Payload方便漏洞复现。判断逻辑仅校验GET请求里name参数是否存在、内容不为空不存在任何过滤、字符替换、HTML转义操作用户传入的内容会原样获取。漏洞关键语句echo preHello . $_GET[ name ] . /pre;程序直接将用户可控的name参数拼接进HTML代码中输出。即便内容被包裹在pre标签内部pre仅用于保留文本空格与换行不会阻止浏览器解析script这类HTML标签。最终页面源码会拼接为preHello scriptalert(document.domain)/script/pre浏览器解析页面时识别script标签并执行JS代码反射型XSS成功触发。漏洞根源概括用户可控输入未经HTML实体编码、无任何过滤直接嵌入HTML页面返回客户端浏览器将恶意内容当作脚本解析运行。标准修复方式使用htmlspecialchars()对输出内容转义把 等特殊字符转为HTML实体浏览器只会视作纯文本展示$name htmlspecialchars($_GET[name], ENT_QUOTES); echo preHello . $name . /pre;3. DVWA Reflected XSSMedium3.1 页面黑盒探测Medium 级别通常会尝试过滤最常见的script标签。当直接提交scriptalert(document.domain)/script会发现页面不再弹窗这说明应用程序已经加入了一层过滤逻辑。但这里必须明确“过滤了某一种 Payload”不等于“修复了 XSS 漏洞”。如果防护逻辑只是删除固定字符串例如删除小写的script和/script那么攻击者仍然可以通过大小写变化、其他 HTML 标签、事件属性等方式绕过。3.2 黑名单绕过思路假设后端只过滤了script/script那么大小写混合的标签就可能绕过检查ScRiPtalert(document.domain)/ScRiPt这里我们可以看到原因在于 HTML 标签名通常不区分大小写但 PHP 的普通字符串替换函数默认是区分大小写的。也就是说script和ScRiPt对于浏览器来说都可能是脚本标签但对于简单字符串黑名单来说它们并不一定相同。除了script标签外浏览器中还存在大量可触发脚本执行的上下文例如带有事件属性的元素imgsrcxonerroralert(document.domain)当图片加载失败时浏览器可能触发onerror中的 JavaScript。这也说明了黑名单方案的根本问题需要拦截的不是一个单词而是浏览器中大量可能进入脚本执行上下文的语法组合。黑名单很难覆盖完整漏掉一个入口就可能被绕过。3.3 源码审计简单字符串替换的缺陷Medium 级别后端PHP源码?php header (X-XSS-Protection: 0); // Is there any input? if( array_key_exists( name, $_GET ) $_GET[ name ] ! NULL ) { // Get input $name str_replace( script, , $_GET[ name ] ); // Feedback for end user echo preHello {$name}/pre; } ?代码逻辑拆解页面依旧接收GET方式传入的name参数相比Low级别新增了一处防护使用str_replace(script, , 变量)把内容里完整的小写script字符串直接清空删除本意是屏蔽脚本标签阻止scriptalert()/script这类基础Payload执行。其余逻辑没有改动依旧关闭浏览器XSS防护、无HTML转义处理替换完成后的内容直接拼接进HTML页面回显。防护存在的致命缺陷str_replace属于纯文本字面替换函数只会机械检索固定字符串进行删除不会解析HTML语法、不区分标签大小写、不识别浏览器的HTML容错解析规则属于简陋的黑名单防御漏洞依旧可以绕过。常见绕过Payload原理大小写混合绕过str_replace仅匹配小写script大小写混杂后不会被识别替换PayloadScRiPtalert(document.domain)/ScRiPt字符串检索不到script替换失效浏览器不区分HTML标签大小写脚本正常执行。嵌套标签绕过Payloadscrscriptiptalert(1)/scr/scriptipt运行过程函数先剔除中间的script文本变为scriptalert(1)/script完整脚本标签重现成功触发XSS。舍弃script标签使用事件属性标签防御仅拦截了script标签没有管控img、svg等携带事件触发的HTML标签img src1 onerroralert(document.domain)svg onloadalert(1)这类载荷不含script不会被替换删除依靠加载事件执行JS轻松绕过限制。漏洞本质依靠黑名单关键字删除的方式无法穷尽所有可执行JS的HTML写法只要不对输出内容做HTML实体编码特殊符号依旧会被浏览器解析为HTML语法XSS漏洞无法彻底根除。正确修复方案摒弃黑名单替换统一使用htmlspecialchars()进行输出转义将 等HTML特殊字符转为实体字符无论何种标签、大小写、事件属性都会被渲染成纯文本彻底杜绝反射型XSS$name htmlspecialchars($_GET[name], ENT_QUOTES); echo preHello {$name}/pre;4. DVWA Reflected XSSHigh4.1 页面黑盒探测High 级别一般会使用正则表达式检测script的变形防护比 Medium 更严格。例如大小写混合的ScRiPt已经无法绕过。此时说明防护逻辑不再是简单匹配固定字符串而是开始尝试识别脚本标签的不同写法。但 High 级别依旧存在一个核心问题它的防护目标仍然是“识别并删除危险标签”而不是“让用户输入以普通文本方式安全显示”。如果开发者只是把检测范围从字符串替换升级成正则表达式依然无法真正覆盖全部 HTML 解析场景。4.2 黑名单与正则过滤为什么仍然不可靠假设后端通过正则表达式尝试删除所有疑似script标签preg_replace(/.*s.*c.*r.*i.*p.*t.*/i,,$name);这种写法看起来比简单的str_replace()更严格但仍然存在明显问题。第一它只关注script标签。而 XSS 并不只依赖script标签许多 HTML 标签及事件属性同样可能触发脚本执行。第二正则表达式并不适合完整解析 HTML。HTML 的标签、属性、实体编码、浏览器容错机制、不同上下文嵌套关系都非常复杂。试图用一条正则表达式覆盖所有危险输入最终通常会出现该拦截的没拦住正常内容被误杀后续维护困难新的浏览器解析差异无法及时覆盖。第三黑名单思路本身就是被动防御。开发者需要先知道所有危险写法再逐一拦截攻击者只需要找到一个没有被考虑到的语法入口即可。所以 High 级别的核心教训是黑名单从“字符串过滤”升级到“正则过滤”并没有改变防护方向错误的问题。4.3 黑盒绕过测试与Payload绕过核心彻底舍弃script标签使用HTML事件属性触发JavaScript载荷不含script字段避开正则匹配规则。首选Payloadimg标签加载错误事件img srcx onerroralert(document.domain)原理src赋值无效地址图片加载失败触发onerror事件执行弹窗代码无script内容正则不会过滤页面加载后成功执行XSS。svg加载事件Payloadsvg onloadalert(document.cookie)页面渲染完成后自动执行JS脚本可用于窃取Cookie。input自动聚焦触发input onfocusalert(1) autofocus4.4 源码审计正则过滤不等于安全编码High级别后端完整PHP源码?phpheader(X-XSS-Protection: 0);// Is there any input?if(array_key_exists(name,$_GET)$_GET[name]!NULL){// Get input$namepreg_replace(/(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i,,$_GET[name]);// Feedback for end userechopreHello{$name}/pre;}?代码解析header (X-XSS-Protection: 0);关闭浏览器自带XSS防护方便漏洞测试获取GET参数name仅校验参数是否存在、非空正则忽略大小写模糊匹配script字符串所有包含script的标签都会被清空处理完毕的变量直接拼接进HTML页面输出全程未进行HTML实体转义。漏洞根源Low、Medium、High三级均使用黑名单防御机制区别仅在于过滤严苛程度。只拦截危险标签不在输出时调用htmlspecialchars()转义特殊字符用户可控内容始终会被浏览器解析为HTML无法彻底抵御XSS攻击。修复方案?phpif(array_key_exists(name,$_GET)$_GET[name]!NULL){$namehtmlspecialchars($_GET[name],ENT_QUOTES);echopreHello{$name}/pre;}?对输出内容进行HTML编码 全部转为实体字符所有HTML标签都会以文本形式展示XSS漏洞彻底修复。5. DVWA Reflected XSSImpossible5.1 源码审计Impossible 等级摒弃黑名单过滤思路采用HTML实体编码输出 CSRF令牌校验双重安全机制从根源防御反射型XSS后端完整源码如下?php// 判断GET请求是否携带name参数且参数不为空if(array_key_exists(name,$_GET)$_GET[name]!NULL){// 校验CSRF防护令牌checkToken($_REQUEST[user_token],$_SESSION[session_token],index.php);// 获取用户输入并进行HTML实体编码$namehtmlspecialchars($_GET[name]);// 将处理后的内容回显至页面echopreHello{$name}/pre;}// 生成全新的会话CSRF令牌generateSessionToken();?代码分段解析Anti-CSRF 令牌校验checkToken()会核对请求携带的令牌与服务端会话存储令牌是否一致每次请求结束调用generateSessionToken()刷新令牌令牌单次有效。攻击者无法伪造合法token构造恶意链接大幅削减反射型XSS的利用条件。核心防护函数htmlspecialchars()该函数会剥夺特殊字符的HTML语法功能将其转换为纯文本实体原始字符转换后HTML实体lt;gt;quot;amp;注默认不会转义单引号传入参数ENT_QUOTES才可将单引号转为#039;编码效果演示用户提交恶意载荷scriptalert(document.domain)/script经过函数转义后页面最终源码lt;scriptgt;alert(document.domain)lt;/scriptgt;浏览器渲染效果纯文本展示scriptalert(document.domain)/script不会识别为脚本标签JS代码无法执行XSS攻击失效。5.2 为什么输出编码才是正确修复方式旧方案Low/Medium/High黑名单拦截逻辑流程预判所有危险字符/标签 → 字符串替换/正则匹配 → 发现后删除过滤弊端HTML可执行JS的方式不计其数无法穷举全部攻击载荷规则永远滞后于攻击手法漏洞始终存在绕过空间。正确方案Impossible输出HTML编码逻辑流程不区分输入好坏所有用户可控内容统一转义 → 全部以普通文本形式输出核心原理 等字符失去HTML标签、事件属性的语法意义浏览器只会将内容当作文字解析无需持续增补过滤规则从底层阻断XSS触发条件。5.3 Impossible 级别安全总结彻底舍弃黑名单防御体系不再依靠正则、字符串替换拦截恶意标签与事件载荷规避黑名单覆盖不全的固有缺陷输出点统一执行HTML实体编码利用htmlspecialchars()消解特殊字符的HTML语义杜绝浏览器解析恶意脚本新增CSRF一次性令牌防护限制恶意链接批量传播利用收缩反射型XSS攻击场景可拓展优化添加ENT_QUOTES参数可同时转义单、双引号适配标签属性内回显场景防护更加完备。6. XSS 防护的正确姿势6.1 第一原则根据输出上下文进行编码不同输出位置需要不同的编码策略。输出位置推荐防护方式HTML 文本节点HTML 实体编码如htmlspecialchars()HTML 属性值属性编码并始终使用引号包裹属性值JavaScript 字符串JavaScript 上下文编码避免直接字符串拼接URL 参数URL 编码如urlencode()CSS 上下文CSS 编码尽量避免拼接用户输入必须牢记输入过滤不能替代输出编码。用户输入可能经过多个业务流程最终出现在不同页面、不同上下文中。真正靠近风险点的位置是“输出到浏览器之前”。6.2 不要使用黑名单修复 XSS以下写法都不推荐作为 XSS 的修复手段str_replace(script,,$input);preg_replace(/script/i,,$input);str_replace(onerror,,$input);原因是黑名单无法穷尽浏览器可以解析的所有危险语法。开发者越试图维护“危险关键字列表”越容易陷入规则膨胀、漏拦截和误拦截的问题。6.3 必须支持富文本时使用白名单净化方案有些业务确实需要用户提交富文本例如文章发布、评论编辑器、知识库系统。此时不能简单使用htmlspecialchars()把所有标签都转义否则格式会全部丢失。正确思路是明确允许哪些标签、哪些属性、哪些协议 ↓ 删除其他所有内容 ↓ 使用经过安全验证的 HTML 净化库处理例如只允许p、br、strong、em、ul、ol、li、a并且限制链接协议只能是http、https不要自己用正则表达式“过滤 HTML”应使用成熟且经过长期验证的 HTML Sanitizer / Purifier 类库。6.4 CSP 可以降低风险但不能代替修复漏洞内容安全策略Content Security PolicyCSP可以帮助浏览器限制脚本加载和执行来源。例如可以限制页面只允许加载本站脚本禁止内联脚本等。但必须注意CSP 是纵深防御措施不是 XSS 漏洞的替代修复方案。正确顺序应该是优先修复输出编码问题 ↓ 再通过 CSP 降低残余风险 ↓ 配合 HttpOnly、Secure、SameSite Cookie 等安全配置7. DVWA Reflected XSS 四个等级对比安全等级核心防护逻辑防护效果主要问题Low不做过滤直接回显完全可利用用户输入直接进入 HTMLMedium过滤固定script字符串容易绕过大小写、事件属性、其他标签未覆盖High正则匹配脚本标签有一定拦截效果本质仍是黑名单无法完整解析 HTMLImpossiblehtmlspecialchars()输出编码可有效阻断当前反射型 XSS正确的上下文编码思路从 DVWA 的四个等级可以非常直观地看出防护演进无防护 ↓ 简单黑名单 ↓ 复杂黑名单 ↓ 输出编码真正可靠的安全方案不是把黑名单写得越来越长而是不要让不可信输入以浏览器可执行语法的形式进入页面。8. 总结反射型 XSS 的漏洞原理并不复杂用户输入被服务端反射到页面中且没有经过正确的输出编码浏览器就可能把输入当成 HTML 或 JavaScript 执行。DVWA 的不同安全等级分别展示了Low直接回显完全无防护Medium简单字符串黑名单容易绕过High正则黑名单仍然无法覆盖全部 XSS 场景Impossible使用htmlspecialchars()进行 HTML 输出编码从根源阻断标签解析。最后记住 XSS 防御最重要的一句话不要试图猜测攻击者会输入什么要确保无论用户输入什么都只能以普通文本的形式被浏览器展示。免责声明本文所有内容仅用于网络安全技术研究与教学演示所有测试均在本地授权搭建的 DVWA 靶场环境中进行旨在帮助读者理解反射型 XSS 漏洞原理与防御机制。请勿将本文涉及的技术与方法用于任何未经授权的真实系统测试。任何利用本文内容进行的非法攻击行为均与作者无关由使用者自行承担相应法律责任。网络安全学习与测试应严格遵守相关法律法规仅在获得明确授权的前提下开展安全测试。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价