XSS攻击中JavaScript字符串的非法拼接与执行机制解析

5次阅读

XSS 攻击中 JavaScript 字符串的非法拼接与执行机制解析

本文详解 XSS 利用中一种典型但易被误解的 JavaScript 表达式注入手法——通过减法运算符强制触发 alert()等函数执行,揭示 ’test’-alert(2)-‘hello’ 为何能成功弹窗而 ’test’alert(2)’hello’ 却语法报错的根本原因。

本文详解 xss 利用中一种典型但易被误解的 javascript 表达式注入手法——通过减法运算符强制触发 `alert()` 等函数执行,揭示 `’test’-alert(2)-‘hello’` 为何能成功弹窗而 `’test’alert(2)’hello’` 却语法报错的根本原因。

在 Web 安全实战(如 Zseano HackerOne CTF)中,常出现一类看似“不合语法”却可成功触发 XSS 的载荷:

<script>var commentContent='test'-alert(2)-'hello';</script>

表面看,’test’ 和 ’hello’ 是字符串,中间却夹着 alert(2)——既无括号包裹、也无分号分隔,更未用加号连接。但它确实会弹出 2。这并非浏览器宽容,而是 JavaScript 引擎严格遵循 表达式求值规则 的结果。

? 核心原理:减法运算符触发隐式类型转换与函数调用

JavaScript 中,减法操作符 - 要求操作数可转换为数字。当对非数字类型执行 - 时,引擎会尝试调用 ToNumber()抽象操作:

  • 字符串 ’test’ → NaN
  • 字符串 ’hello’ → NaN
  • 而 alert(2)本身 无返回值 (即返回 undefined),ToNumber(undefined) 结果也是 NaN

关键在于:为获取操作数的数值,引擎必须先执行 alert(2) —— 这是求值过程的必然步骤。因此,alert(2)在 ’test’-alert(2)-‘hello’ 中被主动调用,弹窗发生;之后整个表达式计算为 NaN – NaN – NaN,结果仍为 NaN,但副作用(弹窗)已达成。

立即学习Java 免费学习笔记(深入)”;

验证该行为,可在控制台运行:

console.log('test' - alert(2) - 'hello'); // 先弹窗,再输出 NaN

✅ 注意:alert()在此处不是“被拼接进字符串”,而是作为 减法表达式的操作数被求值——这是 XSS 利用的关键语义陷阱。

❌ 为什么 ‘test’alert(2)’hello’ 无效?

该写法违反 JavaScript 语法规范:

  • ‘test’ 是字符串字面量(token)
  • alert(2) 是函数调用表达式(token)
  • 相邻两个独立 token 之间 缺少运算符或分隔符(如;、+、,),直接拼接构成语法错误(SyntaxError: Unexpected identifier)

浏览器解析器在词法分析阶段即报错,脚本中断,alert(2)根本不会被执行。

✅ 正确构造 XSS 载荷的关键原则

  1. 确保注入内容处于合法表达式上下文中
    如 <script>var x=…;, <img onerror="…" alt="XSS 攻击中 JavaScript 字符串的非法拼接与执行机制解析 " > 等,且周围已有引号 / 括号包裹,使你的输入成为 JS 表达式的一部分。</script>

  2. 利用强制求值的操作符
    除 - 外,以下操作符同样有效(均会触发操作数求值):

    'a'+alert(1)+'b'    // + 可用于字符串,但 alert(1) 返回 undefined → 'aundefinedb' !alert(1)           // 逻辑非:先执行 alert,再取反 ~alert(1)           // 按位非:同理 void alert(1)       // 显式丢弃返回值,最清晰安全
  3. 规避语法错误的黄金法则
    ✅ 允许:’x’-alert(1)-‘y’、void(alert(1))、[alert(1)]
    ❌ 禁止:’x’alert(1)’y’、alert(1) ‘x’、alert(1), ‘x’(逗号表达式需完整结构)

?️ 防御建议(开发者视角)

  • 永远不要将用户输入直接拼入 <script> 标签内 </script>,尤其避免使用 innerHTML 或 eval()类危险 API。
  • 使用现代框架(React/Vue)的默认转义机制,或手动调用 DOMPurify.sanitize()处理富文本。
  • 对服务端返回的 JS 上下文数据,采用 JSON 序列化并用 JSON.parse()安全解析,而非 eval 或模板字符串拼接。

理解 ’a’-alert(1)-‘b’ 背后的求值链,本质是掌握 JavaScript 执行模型与 XSS 利用面的交汇点——它提醒我们:安全漏洞常藏于语言特性最“合理”的角落。

text=ZqhQzanResources