@

目录
  • 一、XSS之盲打
    • 🎯 漏洞原理
  • 二、XSS 之过滤
    • (一)攻击者视角:常见的过滤绕过技巧
      • 1. 标签与事件绕过
      • 2. 关键字绕过
      • 3. DOM 型过滤绕过
    • (二)防御者视角:如何构建可靠的防御体系
      • 1. 输入验证(白名单优先)
      • 2. 输出编码(最核心的防线)
      • 3. 使用安全的库(避免重复造轮子)
      • 4. 内容安全策略

前言:本文仅用于合法授权的渗透测试场景,旨在帮助开发者识别XSS漏洞、提升Web应用安全性,严禁用于未授权攻击!网络安全无小事,违规操作将承担相应法律责任。

一、XSS之盲打

XSS盲打(Blind XSS)是存储型XSS的一种特殊变体,其核心挑战在于攻击者无法直接看到攻击结果。这通常发生在用户输入被存储在服务器(如数据库、日志文件)中,但不会在当前页面立即显示,而是由其他用户(如管理员)在后台或其他页面查看时才会触发。

🎯 漏洞原理

  1. 注入点与触发点分离:攻击者提交恶意脚本后,只能看到类似“提交成功”或“感谢反馈”的通用提示,无法确认脚本是否真的被存储或何时被执行。
  2. 延迟性与隐蔽性:恶意脚本被持久化存储后,需要等待特定用户(如管理员登录后台查看留言、日志)访问包含该脚本的页面时,攻击才会真正触发。
  3. 攻击目标:由于普通用户可能不会访问所有包含XSS点的页面,盲打的主要目标通常是权限较高的管理员,以实现会话劫持或权限提升。

image-20260302202901157

在留言这里输入 ,并提交,当管理员再次登录的时候,就会触发 playload。

image-20260302203137760

当然,实战中,可以通过该漏洞获取到管理源的 cookie、session等信息。

二、XSS 之过滤

XSS 过滤是防御跨站脚本攻击的核心手段,但也是攻防对抗最激烈的领域。很多开发者以为“把 <script> 标签删掉就安全了”,但攻击者总有各种办法绕过这些简单的检查。

这里结合 pikachu 靶场梳理了常见的绕过技巧真正的防御方案

image-20260302212646886

(一)攻击者视角:常见的过滤绕过技巧

在渗透测试或 CTF 中,如果你发现输入被过滤了,可以尝试以下思路:

1. 标签与事件绕过

很多过滤器只拦截 <script>,却忽略了其他标签。

  • 利用其他标签:
    • <img src=x onerror=alert(1)> (利用图片加载失败事件)
    • <svg onload=alert(1)> (利用 SVG 矢量图标签)
    • <iframe src=javascript:alert(1)> (利用内联框架)
    • <body onload=alert(1)> (利用页面加载事件)
  • 利用伪协议:
    • <a href="javascript:alert(1)">点击</a>
    • <img src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' onload='alert(1)'/>"> (利用 Data URI)

2. 关键字绕过

如果 onerroralert 被过滤,可以尝试:

  • 大小写混淆<ImG sRc=x oNeRrOr=alert(1)>
  • 双写/多写过滤<img srconerror=alert(1)> (如果过滤器只删除一次,剩下 onerror
  • 利用注释<scr<!-- -->ipt>alert(1)</script><img src=x onerror=alert/*x*/(1)>
  • 编码绕过:
    • 十六进制:<img src=x onerror=alert(1)>
    • 十进制:<img src=x onerror=alert(1)>
    • javascript: 伪协议的编码:<a href="javascript:alert(1)">

3. DOM 型过滤绕过

针对你之前遇到的 DOM XSS,如果前端 JavaScript 过滤了 # 后面的内容,可以尝试:

  • 利用 ? 代替 #:如果代码只处理 hash,可以尝试在查询参数中注入。
  • 利用 location.search:如果过滤了 location.hash,但使用了 location.search,攻击方式同上。

(二)防御者视角:如何构建可靠的防御体系

作为开发者,永远不要依赖“黑名单”(即只过滤已知的危险词)。因为攻击向量无穷无尽,你永远无法列全。正确的做法是白名单策略和上下文相关的输出编码

1. 输入验证(白名单优先)

不要试图清理所有恶意代码,而是只允许合法的输入通过。

  • 严格校验格式:例如用户名只允许字母、数字和下划线,长度限制在 3-16 位。
    • 正则示例/^[a-zA-Z0-9_]{3,16}$/
  • 拒绝非法输入:对于不符合白名单格式的数据,直接拒绝处理(返回 400 错误),不要尝试“清理”它。

2. 输出编码(最核心的防线)

这是防御 XSS 最有效、最通用的方法。根据数据插入的位置(上下文)进行不同的编码

输出场景 编码规则 示例
HTML 文本内容 将特殊字符转为 HTML 实体 < 转为 <> 转为 >
HTML 属性值内 除了实体编码,还要编码引号 " 转为 "' 转为 '
JavaScript 代码内 使用 Unicode 或十六进制编码 </script> 转为 \x3c\x2fscript\x3e
URL 参数内 使用百分号编码 (Percent-encoding) < 转为 %3C" 转为 %22

3. 使用安全的库(避免重复造轮子)

手动编写过滤逻辑极易出错,应使用经过社区广泛验证的库。

  • 前端 (JavaScript/Node.js):
    • DOMPurify:专门用于净化 HTML,允许你定义白名单标签(如 <b>, <i>, <a>),同时移除所有危险的事件属性(如 onerror)和脚本。
  • 后端:
    • Java:使用 OWASP Java HTML SanitizerJsoup。它们基于白名单策略,可以安全地处理富文本。
    • Python:使用 Bleach(基于白名单的 HTML 清理器)。
    • PHP:使用 htmlspecialchars() 函数进行转义。

4. 内容安全策略

这是浏览器的“最后一道防线”。即使你的代码有漏洞,CSP 也能阻止恶意脚本的执行。

  • 核心思想:告诉浏览器,页面只能加载指定来源的脚本。
  • 配置示例:
    • Content-Security-Policy: default-src 'self';
    • 这表示只允许加载同源(和当前网站同一个域名)的脚本,内联脚本(<script>...</script>)和 eval() 默认会被禁止。
  • 配合 Nonce:对于必须执行的内联脚本,可以使用 nonce 机制,为脚本生成一个随机令牌,只有带上正确令牌的脚本才能执行。