原型链污染初探

7erry

2019年初,Snyk的安全研究人员披露了流行的JavaScript库Lodash中一个严重漏洞的详细信息,该漏洞使黑客能够攻击多个Web应用程序,这个安全漏洞就是一个原型污染漏洞(JavaScript Prototype Pollution),攻击者可以利用该漏洞利用JavaScript编程语言的规则并以各种方式破坏应用程序。
与该攻击思想类似的,包括但不限于Python的元对象可同样可能以这样的攻击方式实现攻击

前置知识

原型链

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。每个对象都有一个名为__proto__的内置属性,它指向该对象的原型。同时,每个函数也都有一个名为 prototype 的属性,它是一个对象,包含构造函数的原型对象应该具有的属性和方法。简单来说,__proto__属性是指向该对象的原型,而 prototype属性是用于创建该对象的构造函数的原型原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain)

JavaScript的继承机制

当我们访问某一对象Object的一个的key属性时,JavaScript会进行一次递归查询,例如:

  1. 在该对象Object中寻找key属性
  2. 在该对象中没有找到时,它会在在Object.__proto__中寻找key属性
  3. 如果仍未找到,此时会去Object.__proto__.__proto__中寻找key属性

漏洞成因

在JavaScript中,每个对象都有一个原型,它是一个指向另一个对象的引用。当我们访问一个对象的属性时,如果该对象没有这个属性,JavaScript引擎会在它的原型对象中查找这个属性。这个过程会一直持续,直到找到该属性或者到达原型链的末尾。
如果攻击者能够控制一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这意味着,攻击者可以利用这个特性,通过修改一个对象的原型链,来污染程序的行为。例如,攻击者可以在一个对象的原型链上设置一个恶意的属性或方法,当程序在后续的执行中访问该属性或方法时,就会执行攻击者的恶意代码。

示例

在实际攻击情境中,原型连污染漏洞的情景主要出现在以下两种情况中:

  1. 对象合并 Merge
  2. 对象克隆 Clone (本质上是将一个对象合并到空对象中)

以Merge为例,如果存在以下代码

function merge(target, source) {
    for (let key in source) {
        if (key in source && key in target) {
            merge(target[key], source[key])
        } else {
            target[key] = source[key]
        }
    }
}

在合并的过程中存在赋值的操作:target[key] = source[key],当key为__proto__时,即可进行原型链污染
由于攻击者需要能攻控制key值,因此原型链污染往往会与JSON解析,模版解析进行反序列化的业务相关联
还有一个经典的原型链污染漏洞可见于参考资料

Bypass

Reference

继承与原型链
关于Prototype Pollution Attack的二三事
高级漏洞篇之原型污染专题
深入理解 JavaScript Prototype 污染攻击
Fuzz中的javascript大小写特性
https://www.freebuf.com/articles/web/361333.html
CVE-2021-25928
JavaScript原型链污染原理及相关CVE漏洞剖析

  • Title: 原型链污染初探
  • Author: 7erry
  • Created at : 2023-10-31 00:00:00
  • Updated at : 2023-10-31 00:00:00
  • Link: http://7erry.com/2023/10/31/原型链污染初探/
  • License: This work is licensed under CC BY-NC 4.0.