JavaScript原型链污染

一、什么是原型链污染(JS)

原型链污染(Prototype Pollution)是一种安全漏洞,在 JavaScript 中可能会导致意外和不安全的行为。它利用了 JavaScript 中的原型继承机制,通过修改对象的原型链来污染或篡改目标对象的属性。

二、前置知识

2.1 JS对象

属性声明及调用格式如下

key:value //声明

classname.key //调用

方法声明及调用格式如下

methodname:function(){
    ……
} //声明

classname.methodname()  //调用

2.11 通过类创建

类的声明与实例化和其他语言相似,如果不声明构造函数,则该函数仍存在但内容为NULL

class demo{
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
let person = new demo(ELITE,25);
// 访问对象的属性
console.log(person.name); // 输出:ELITE
console.log(person.age); // 输出: 25

2.12 字面量模式创建

JavaScript中对象的字面量模式定义类似于python中的字典,属性是键值对的组合,方法也以类似的形式定义示例如下

var person = {
    name:"ELITE",
    age:19,
    gender:'male',
    sayName:function(){
        console.log("hello world!");
    }
};

2.13构造函数模式创建

// 定义一个函数,将作为对象的构造方法
function Person(name, age) {
  this.name = name;
  this.age = age;
}
// 使用构造方法创建对象实例
var person1 = new Person('Alice', 25);  //给构造方法传值
// 访问对象的属性
console.log(person1.name); // 输出: Alice
console.log(person1.age); // 输出: 25

JavaScript里的构造方法和其他语言中的构造方法相同,都会在对象初始化时自动执行

2.2 默认属性

在JavaScript中一切皆对象(这里就和python类似了),函数也可以理解为一种特殊的变量

  • __proto__ 属性,它是对象独有的,指向对象(构造函数)的原型(可以说是父类)
  • constructor属性,它是对象独有的,指向对象的构造函数
  • prototype属性,它是函数独有的,指向函数的原型对象,也可以说是该函数作为构造函数创建的实例的原型对象

具体关系如图所示


并且存在这样一个等式

对象.__proto__ == 构造函数.prototype

一般创建的对象的原型默认都是object,例如:

let person = {
  name: 'John',
  age: 30,
  city: 'New York'
};
//未指明构造函数

三、污染利用

污染需要用到这样一个合并函数,和python里的merge函数差不多

function merge(target, source) {
    console.log('merge', target, source);
    // 遍历 source 中的 key。
    for (let key in source) {
        if (key in source && key in target) {
            merge(target[key], source[key])  //递归遍历
        } else {
            target[key] = source[key]  //合并赋值
        }
    }
}

重点在于这一条语句

merge(target[key], source[key])

假定对象如下

let a = {}
let b = {"id": 1, "__proto__": {"no": 2}}

//这俩都未指定原型,默认都为Object

我们要通过a与b的合并,去污染object对象,b为原对象

当for语句迭代到b对象的第二个属性时污染开始,我们的目的是得到 a[__proto__]属性,也就是Object对象,但是我们这种字面量定义方式是错的

let b = {"id": 1, "__proto__": {"no": 2}}

__proto__并不会被原封不动的解释为键值,而是会被当做默认属性解析为 b对象 的原型,这时b对象的原型发生改变,不再是默认的Object,而是后来定义的 {"no": 2},这样b对象的键值只有a和b,b是在原型(父类)中的,这样只是会正常的合并,而不会污染到上一层

示例如下

demo:

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]
        }
   }
}
let a = {}
let b = {"id": 1, "__proto__": {"no": 2}}
merge(a, b)
console.log(a.id,a.no)
console.log(a.__proto__)

结果


我们应该对payload进行JSON解析处理,这样__proto__就可以被当做键值,而不会被解析,示例如下

let b = JSON.parse('{"id": 1, "__proto__": {"no": 2}}')

运行结果


可以看到成功污染到了Object对象

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
©2023 By Elite

冀公网安备 13108202000889号

| 鲁ICP备2023011162号

声明:本站中用到的所有图片图标,均来源网络,如有侵权请及时联系删除
Theme Argon