高级漏洞篇之原型污染专题
字数 1234 2025-08-10 16:34:39

JavaScript原型污染漏洞详解

1. 什么是原型污染?

原型污染是一种JavaScript漏洞,攻击者可以利用它向全局对象原型添加任意属性。这些属性可能会被用户定义的对象继承,从而控制原本无法访问的对象的属性。

关键特点:

  • 通常无法作为独立漏洞利用
  • 可与其他漏洞结合导致严重后果
  • 客户端可能导致DOM XSS
  • 服务器端可能导致远程代码执行

2. JavaScript原型与继承基础

2.1 JavaScript对象

JavaScript对象是一组键值对(属性)的集合:

const user = {
  username: "natsuk0",
  userId: 01234,
  isAdmin: false
}

2.2 原型概念

每个JavaScript对象都链接到另一个对象,称为它的原型:

let myObject = {};
Object.getPrototypeOf(myObject); // Object.prototype

let myString = "";
Object.getPrototypeOf(myString); // String.prototype

2.3 原型链

对象不仅从直接原型继承属性,还从原型链中所有上层对象继承属性:

username -> String.prototype -> Object.prototype -> null

2.4 访问原型的特殊属性

__proto__是大多数浏览器使用的非标准属性,用于访问对象原型:

username.__proto__ // String.prototype
username['__proto__'] // 同上

3. 原型污染漏洞的产生

3.1 漏洞产生条件

当JavaScript函数递归合并包含用户可控属性的对象时,未对键进行清理,可能允许注入__proto__等特殊键。

3.2 污染机制

攻击者可以注入类似以下的结构:

targetObject.__proto__.evilProperty = 'payload';

3.3 关键组成部分

  1. 污染源(Source):用户可控的输入
  2. 接收器(Sink):执行任意代码的JavaScript函数或DOM元素
  3. 利用链:未经适当过滤传递到接收器的属性

4. 原型污染源(Source)

4.1 通过URL

https://vulnerable-website.com/?__proto__[evilProperty]=payload

4.2 通过JSON输入

{"__proto__": {"evilProperty": "payload"}}

4.3 通过Web消息

5. 原型污染接收器(Sink)

常见的接收器包括:

  • 执行任意JavaScript的函数
  • DOM元素(如innerHTML)
  • 配置选项(如transport_url)

6. 利用链示例

6.1 典型利用场景

let transport_url = config.transport_url || defaults.transport_url;
let script = document.createElement('script');
script.src = `${transport_url}/example.js`;
document.body.appendChild(script);

6.2 攻击示例

https://vulnerable-website.com/?__proto__[transport_url]=data:,alert(1);//

7. 检测与利用方法

7.1 手动检测步骤

  1. 尝试注入任意属性:
    vulnerable-website.com/?__proto__[test]=test
    
  2. 检查是否成功污染:
    Object.prototype.test // 应为"test"
    
  3. 尝试不同表示法:
    vulnerable-website.com/?__proto__.test=test
    

7.2 使用DOM Invader(Burp Suite工具)

  1. 在Burp内置浏览器中启用DOM Invader
  2. 自动扫描原型污染源和利用链
  3. 自动生成DOM XSS POC

8. 防御方法

8.1 基本防御

  • 过滤用户输入中的__proto__

8.2 更安全的防御

  1. 使用无原型的对象:
    Object.create(null)
    
  2. 冻结原型:
    Object.freeze(Object.prototype)
    
  3. 使用Map代替普通对象

9. 高级技巧:替代污染向量

__proto__被过滤时,可以使用构造函数属性:

myObject.constructor.prototype // 等同于myObject.__proto__

污染示例:

https://vulnerable-website.com/?constructor[prototype][evilProperty]=payload

10. 实际案例分析

案例1:通过transport_url的DOM XSS

  1. 污染原型:
    /?__proto__[transport_url]=data:,alert(1);
    
  2. 触发动态脚本加载

案例2:通过sequence属性的DOM XSS

  1. 污染原型:
    /?__proto__.sequence=alert(1)-
    
  2. 触发恶意代码执行

11. 总结

原型污染是一种强大的JavaScript漏洞,虽然通常需要与其他漏洞结合利用,但可能导致严重后果。防御关键在于:

  • 正确处理用户输入
  • 限制原型修改
  • 使用更安全的数据结构
  • 定期安全审计和测试

理解原型继承机制和污染原理对于开发安全的JavaScript应用至关重要。

JavaScript原型污染漏洞详解 1. 什么是原型污染? 原型污染是一种JavaScript漏洞,攻击者可以利用它向全局对象原型添加任意属性。这些属性可能会被用户定义的对象继承,从而控制原本无法访问的对象的属性。 关键特点: 通常无法作为独立漏洞利用 可与其他漏洞结合导致严重后果 客户端可能导致DOM XSS 服务器端可能导致远程代码执行 2. JavaScript原型与继承基础 2.1 JavaScript对象 JavaScript对象是一组键值对(属性)的集合: 2.2 原型概念 每个JavaScript对象都链接到另一个对象,称为它的原型: 2.3 原型链 对象不仅从直接原型继承属性,还从原型链中所有上层对象继承属性: 2.4 访问原型的特殊属性 __proto__ 是大多数浏览器使用的非标准属性,用于访问对象原型: 3. 原型污染漏洞的产生 3.1 漏洞产生条件 当JavaScript函数递归合并包含用户可控属性的对象时,未对键进行清理,可能允许注入 __proto__ 等特殊键。 3.2 污染机制 攻击者可以注入类似以下的结构: 3.3 关键组成部分 污染源(Source) :用户可控的输入 接收器(Sink) :执行任意代码的JavaScript函数或DOM元素 利用链 :未经适当过滤传递到接收器的属性 4. 原型污染源(Source) 4.1 通过URL 4.2 通过JSON输入 4.3 通过Web消息 5. 原型污染接收器(Sink) 常见的接收器包括: 执行任意JavaScript的函数 DOM元素(如innerHTML) 配置选项(如transport_ url) 6. 利用链示例 6.1 典型利用场景 6.2 攻击示例 7. 检测与利用方法 7.1 手动检测步骤 尝试注入任意属性: 检查是否成功污染: 尝试不同表示法: 7.2 使用DOM Invader(Burp Suite工具) 在Burp内置浏览器中启用DOM Invader 自动扫描原型污染源和利用链 自动生成DOM XSS POC 8. 防御方法 8.1 基本防御 过滤用户输入中的 __proto__ 键 8.2 更安全的防御 使用无原型的对象: 冻结原型: 使用Map代替普通对象 9. 高级技巧:替代污染向量 当 __proto__ 被过滤时,可以使用构造函数属性: 污染示例: 10. 实际案例分析 案例1:通过transport_ url的DOM XSS 污染原型: 触发动态脚本加载 案例2:通过sequence属性的DOM XSS 污染原型: 触发恶意代码执行 11. 总结 原型污染是一种强大的JavaScript漏洞,虽然通常需要与其他漏洞结合利用,但可能导致严重后果。防御关键在于: 正确处理用户输入 限制原型修改 使用更安全的数据结构 定期安全审计和测试 理解原型继承机制和污染原理对于开发安全的JavaScript应用至关重要。