网络安全--原型链污染

1.什么是原型链污染

原型链污染(Prototype Pollution)是一种web应用程序中常见的安全漏洞,主要影响使用JavaScript的应用程序。它是一种攻击技术,通过修改JavaScript对象的原型链,来实现对应用程序的非法操作和控制。

JavaScript中的对象是通过原型链进行继承的。每个对象都有一个指向其原型的链接,它允许对象从其原型中继承属性和方法。当JavaScript代码在处理输入时,如果不适当地允许用户控制原型链上的属性,攻击者就可以操纵原型链,并在目标对象上添加、修改或删除属性。

攻击者利用原型链污染可以实现多种攻击,包括但不限于:

  1. 修改对象的原型,从而覆盖或扩展原有属性和方法,导致应用程序的意外行为或漏洞。
  2. 污染全局对象的原型,导致全局范围内的异常行为,可能导致系统崩溃或敏感信息泄露。
  3. 在原型链上添加恶意方法或属性,用于劫持或篡改应用程序的逻辑。
  4. 绕过应用程序的安全控制,获取未授权的访问权限。

原型链污染漏洞通常是由于开发者未正确验证和过滤用户提供的输入数据所导致的。为了防止原型链污染,开发者应该始终对用户输入进行严格的验证和过滤,并避免直接使用用户提供的数据来操作原型链上的属性。另外,更新JavaScript运行时环境和库到最新版本也可以帮助防范已知的原型链污染漏洞。

在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。

2.原型链三属性

1)prototype

prototype 是函数对象特有的属性。在 JavaScript 中,每个函数都有一个 prototype 属性,它是一个指向对象的引用。这个对象被称为该函数的原型对象,它包含了可以由该函数的所有实例共享的属性和方法。当通过构造函数创建对象实例时,实例的 __proto__ 属性会指向构造函数的 prototype 对象。

2)constructor

constructor 属性是原型对象的一个属性,它指向构造函数本身。当你创建一个函数并给它设置 prototype 属性后,prototype 对象会自动获得一个名为 constructor 的属性,该属性指向该函数本身。这样,通过实例对象的 constructor 属性,你可以访问到创建该实例的构造函数。

3)proto

__proto__ 是每个对象都有的属性,它指向对象的原型。在 JavaScript 中,对象通过 __proto__ 属性链接到它们的原型对象,从而形成了原型链。当你访问一个对象的属性时,如果该对象本身没有该属性,JavaScript 就会沿着原型链往上查找,直到找到该属性或者到达原型链的顶端(通常是 Object.prototype)。

4)原型链三属性之间关系

javascript 复制代码
// 创建一个构造函数
function Person(name) {
  this.name = name;
}

// 给构造函数的 prototype 添加一个方法
Person.prototype.sayHello = function() {
  console.log('Hello, I am ' + this.name);
};

// 创建一个实例
const john = new Person('John');

// 使用 __proto__ 访问原型对象
console.log(john.__proto__ === Person.prototype); // true

// 使用 constructor 访问构造函数
console.log(john.constructor === Person); // true

// 使用 Object.getPrototypeOf() 访问原型对象
console.log(Object.getPrototypeOf(john) === Person.prototype); // true

// 使用原型链调用方法
john.sayHello(); // 输出: "Hello, I am John"

3.JavaScript原型链继承

javascript 复制代码
function Father() {
    this.first_name = 'Donald'
    this.last_name = 'Trump'
}

function Son() {
    this.first_name = 'Melania'
}

Son.prototype = new Father()

let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)

1)分析

Son类继承了Father类的last_name属性,最后输出的是Name: Melania Trump

2)总结

  1. 在对象son中寻找last_name

  2. 如果找不到,则在son.__proto__中寻找last_name

  3. 如果仍然找不到,则继续在son.__proto__.__proto__中寻找last_name

  4. 依次寻找,直到找到null结束。比如,Object.prototype__proto__就是null

3)运行结果

4.原型链污染简单实验

1)实验一

javascript 复制代码
let foo = {bar :1}
console.info(foo.bar)
//foo是一个object foo.__proto__ === object.prototype
foo.__proto__.bar = 2
console.info(foo.bar)
let zoo = {}
console.info(zoo.bar)

污染过程

因为前面我们修改了foo的原型foo.__proto__.bar = 2,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。

后来,我们又用Object类创建了一个zoo对象let zoo = {},zoo对象自然也有一个bar属性

2)实验2

javascript 复制代码
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]
        }
    }
}

var x = {
    age:11
}

var y = {
    age: 12,
    num: 100
}
merge(x,y)
console.info(x)
console.info(y)

运行结果:

为什么会被污染?

merge函数的目的是将source对象中的属性合并到target对象中。如果source对象和target对象具有相同的键(属性名),那么merge函数将递归地将嵌套对象的属性合并。否则,如果source对象具有target对象中不存在的键,merge函数将直接将该键值对添加到target对象中,接下来,执行 merge(x, y) 语句将会将 y 对象的属性合并到 x 对象中

相关推荐
用户962377954481 天前
VulnHub DC-3 靶机渗透测试笔记
安全
叶落阁主2 天前
Tailscale 完全指南:从入门到私有 DERP 部署
运维·安全·远程工作
用户962377954484 天前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机4 天前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机4 天前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954484 天前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star4 天前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954485 天前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
cipher6 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
一次旅行9 天前
网络安全总结
安全·web安全