原型链污染攻击

原型链污染攻击

prototype 和 _proto_是什么

JavaScript中的类的简历

        在JavaScript中,我们如果要定义一个类,需要以定义“构造函数”的方式来定义:

function Foo() {this.bar = 1
}new Foo()

解析:

        Foo函数的内容,就是Foo类的构造函数,而this.bar就表示Foo类中的一个属性

        为了简化编写JavaScript代码,ECMAScript 6后增加了class语法,但class其实只是一个语法糖

JavaScript中的类中方法的建立

        一个类必然有一些方法,类似属性this.bar,我们也可以将方法定义在构造函数内部

function Foo() {this.bar = 1this.show = function() {console.log(this.bar)}
}(new Foo()).show()

解析:

        这样写有一个问题,就是每当我们新建一个Foo对象时,this.show = function()... 就会执行一次,这个show方法实际上是绑定在对象上的,而不是绑定在“类”中

 JavaScript中原型prototype的引用

希望在创建类时只创建一次show方法,需要使用原型(prototype)

function Foo() {this.bar = 1
}Foo.prototype.show = function show() {console.log(this.bar)
}let foo = new Foo()
foo.show()

解析:

        我们可以认为原型prototype是类Foo的一个属性,而所有用Foo类实例化的对象,都将有这个属性中的所有内容,包括变量和方法。foo对象,天生具有foo.show()方法

        此时Foo.prototype来访问Foo类的原型,但是Foo实例化出来的对象,是不能够通过prototype访问原型

 JavaScript中__proto__的引用

        一个Foo类实例化出来的foo对象,可以通过foo.__proto__属性访问Foo中类的原型

foo.__proto__ == Foo.prototype

 prototype 和 _proto_的定义

        prototype --- 是一个类的属性所有类对象在实例化的时候将会拥有prototype中的属性和方法

        一个对象的__proto__属性,指向这个对象所在类的prototype属性

JavaScript中原型链继承

        所有类对象在实例化的时候将会拥有中的prototype属性和方法这个特性被用来实现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}`)

解析:

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

  JavaScript引擎会进行如下操作:

  1. 在对象son中寻找last_name

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

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

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

 JavaScript的这个查找的机制,被运用在面向对象的继承中,被称作prototype继承链

注意:

  1. 每个构造函数(constructor)都有一个原型对象(prototype)

  2. 对象的__proto__属性,指向类的原型对象prototype

  3. JavaScript使用prototype链实现继承机制

原型链污染是什么

引入

       在前面说过 foo.__proto__指向的是Foo类的prototype。那么,如果我们修改了foo.__proto__中的值是不是就可以修改Foo类呢?

// foo是一个简单的JavaScript对象
let foo = {bar: 1}// foo.bar 此时为1
console.log(foo.bar)// 修改foo的原型(即Object)
foo.__proto__.bar = 2// 由于查找顺序的原因,foo.bar仍然是1
console.log(foo.bar)// 此时再用Object创建一个空的zoo对象
let zoo = {}// 查看zoo.bar
console.log(zoo.bar)

 解析:

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

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

原型链污染定义

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

哪些情况原型链会被污染

        我们思考一下,哪些情况下我们可以设置__proto__的值呢?其实找找能够控制数组(对象)的“键名”的操作即可:

  1. 对象merge 结合 拼接

  2. 对象clone(其实内核就是将待操作的对象merge到一个空对象中) 复制

使用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__,是不是就可以原型链污染呢?

        使用如下代码进行测试

let o1 = {}
let o2 = {a: 1, "__proto__": {b: 2}}
merge(o1, o2)
console.log(o1.a, o1.b)o3 = {}console.log(o3.b)

        结果是,合并虽然成功了,但原型链没有被污染

解析:

        这是因为,我们用JavaScript创建o2的过程(let o2 = {a: 1, "__proto__": {b: 2}})中,__proto__已经代表o2的原型了,此时遍历o2的所有键名,你拿到的是[a, b]__proto__并不是一个key,自然也不会修改Object的原型

        修改代码

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

解析:

        这是因为,JSON解析的情况下__proto__会被认为是一个真正的“键名”,而不代表“原型”,所以在遍历o2的时候会存在这个键

案例

案例一

const express = require('express')
var hbs = require('hbs');
var bodyParser = require('body-parser');
const md5 = require('md5');
var morganBody = require('morgan-body');
const app = express();
//目前user并没有admintoken
var user = []; //empty for nowvar matrix = [];
for (var i = 0; i < 3; i++){matrix[i] = [null , null, null];
}function draw(mat) {var count = 0;for (var i = 0; i < 3; i++){for (var j = 0; j < 3; j++){if (matrix[i][j] !== null){count += 1;}}}return count === 9;
}app.use(express.static('public'));
app.use(bodyParser.json());
app.set('view engine', 'html');
morganBody(app);
app.engine('html', require('hbs').__express);app.get('/', (req, res) => {for (var i = 0; i < 3; i++){matrix[i] = [null , null, null];}res.render('index');
})app.get('/admin', (req, res) => { /*this is under development I guess ??*/console.log(user.admintoken);if(user.admintoken && req.query.querytoken && md5(user.admintoken) === req.query.querytoken){res.send('Hey admin your flag is <b>flag{prototype_pollution_is_very_dangerous}</b>');} else {res.status(403).send('Forbidden');}    
}
)app.post('/api', (req, res) => {var client = req.body;var winner = null;if (client.row > 3 || client.col > 3){client.row %= 3;client.col %= 3;}matrix[client.row][client.col] = client.data;for(var i = 0; i < 3; i++){if (matrix[i][0] === matrix[i][1] && matrix[i][1] === matrix[i][2] ){if (matrix[i][0] === 'X') {winner = 1;}else if(matrix[i][0] === 'O') {winner = 2;}}if (matrix[0][i] === matrix[1][i] && matrix[1][i] === matrix[2][i]){if (matrix[0][i] === 'X') {winner = 1;}else if(matrix[0][i] === 'O') {winner = 2;}}}if (matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2] && matrix[0][0] === 'X'){winner = 1;}if (matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2] && matrix[0][0] === 'O'){winner = 2;} if (matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0] && matrix[2][0] === 'X'){winner = 1;}if (matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0] && matrix[2][0] === 'O'){winner = 2;}if (draw(matrix) && winner === null){res.send(JSON.stringify({winner: 0}))}else if (winner !== null) {res.send(JSON.stringify({winner: winner}))}else {res.send(JSON.stringify({winner: -1}))}})
app.listen(3000, () => {console.log('app listening on port 3000!')
})

解析:

        获取flag的条件是 传入的querytoken要和user数组本身的admintoken的MD5值相等,且二者都要存在

       由代码可知,全文没有对user.admintokn 进行赋值,所以理论上这个值是不存在的,但因为存在一下赋值语句

    matrix[client.row][client.col] = client.data;

        其中data,row,col,都是我们post传入的值都是可控的。所以可以构造原型链污染

本地测试

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/22929.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高频高速板行业现状及市场前景

覆铜板全称为覆铜箔层压板&#xff0c;是由增强材料浸以树脂胶液 , 覆以铜箔 , 经热压而成的一种板状材料。覆铜板是制作印制电路板的核心材料&#xff0c;担负着印制电路板导电、绝缘、支撑三大功能。高频高速电路板有介电常数小且稳定、介质损耗小、传输损耗小等特点。 高频…

ip link add 命令

ip link add veth0 type veth peer name veth1 这条命令主要用于在 Linux 操作系统中创建一个新的 veth(虚拟以太网) 对&#xff0c;这是一种虚拟网络设备&#xff0c;用于在 Linux 命名空间&#xff08;namespaces&#xff09;之间创建网络连接。此命令将创建两个设备&#xf…

2023年华数杯数学建模A题思路代码分析 - 隔热材料的结构优化控制研究

# 1 赛题 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性&#xff0c;在航天、军工、石化、建筑、交通等 高科技领域中有着广泛的应用。 目前&#xff0c;由单根隔热材料 A 纤维编织成的织物&#xff0c;其热导率可以直接测出&#xff1b;但是 单根隔热…

vue name命名错误 Do not use built-in or reserved HTML elements as component

描述&#xff1a; Do not use built-in or reserved HTML elements as component id: header 这里指的是components的名称命名不正确。 在项目中我使用的是header 作为组件名称&#xff0c;但是在前端html中这个是内置组件来的&#xff0c;名称已被占用不能再使用这些名称了。…

山西电力市场日前价格预测【2023-08-06】

日前价格预测 预测明日&#xff08;2023-08-06&#xff09;山西电力市场全天平均日前电价为411.77元/MWh。其中&#xff0c;最高日前电价为457.52元/MWh&#xff0c;预计出现在19: 30。最低日前电价为370.37元/MWh&#xff0c;预计出现在13: 15。 价差方向预测 1&#xff1a; 实…

区块链-Web3.0-什么是Web3.0?

一、什么是Web 3.0 Web 3.0&#xff0c;也被称为“去中心化Web”或“智能Web”&#xff0c;是互联网的下一代&#xff0c;它使用了分布式系统技术、区块链技术和智能合约等新型技术&#xff0c;旨在构建一个更加去中心化、安全、透明和智能的互联网。Web 3.0 可以带来更广泛的…

机器学习---概述(一)

文章目录 1.人工智能、机器学习、深度学习2.机器学习的工作流程2.1 获取数据集2.2 数据基本处理2.3 特征工程2.3.1 特征提取2.3.2 特征预处理2.3.3 特征降维 2.4 机器学习2.5 模型评估 3.机器学习的算法分类3.1 监督学习3.1.1 回归问题3.1.2 分类问题 3.2 无监督学习3.3 半监督…

前端(十一)——Vue vs. React:两大前端框架的深度对比与分析

&#x1f60a;博主&#xff1a;小猫娃来啦 &#x1f60a;文章核心&#xff1a;Vue vs. React&#xff1a;两大前端框架的深度对比与分析 文章目录 前言概述原理与设计思想算法生态系统与社区支持API与语法性能与优化开发体验与工程化对比总结结语 前言 在当今快速发展的前端领…

软件设计原则

文章目录 一、软件设计原则1. 开闭原则2. 里氏代换原则3. 依赖倒转原则4. 接口隔离原则5. 迪米特法则6. 合成复用原则 一、软件设计原则 在软件开发中&#xff0c;为了提高软件系统的可维护性和可复用性&#xff0c;增加软件的可扩展性和灵活性&#xff0c;程序员要尽量根据软件…

django使用mysql数据库

Django开 发操作数据库比使用pymysql操作更简单&#xff0c;内部提供了ORM框架。 下面是pymysql 和orm操作数据库的示意图&#xff0c;pymysql就是mysql的驱动&#xff0c;代码直接操作pymysql ,需要自己写增删改查的语句 django 就是也可以使用pymysql、mysqlclient作为驱动&a…

迁移学习:使用Restnet预训练模型构建高效的水果识别模型

目录 引言 1 迁移学习 1.1 什么是迁移学习 1.2 迁移学习能解决什么问题 1.3 迁移学习面临的三个问题 1.3.1 何时迁移 1.3.2 何处迁移 1.3.3 如何迁移 1.4 迁移学习的分类 1.4.1 按照学习方式的划分 1.4.2 按照使用方法的划分 2 Restnet网络 2.1 Restnet介绍 2.2 Re…

LangChain:打造自己的LLM应用 | 京东云技术团队

1、LangChain是什么 LangChain是一个框架&#xff0c;用于开发由LLM驱动的应用程序。可以简单认为是LLM领域的Spring&#xff0c;以及开源版的ChatGPT插件系统。核心的2个功能为&#xff1a; 1&#xff09;可以将 LLM 模型与外部数据源进行连接。 2&#xff09;允许与 LLM 模…

element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)

功能如图 功能需求 表格树形表格勾选数据&#xff0c;右边显示对应勾选的数据内容&#xff0c;选中客户&#xff0c;自动勾选所有的店铺(子级)&#xff0c;选中其中一个店铺&#xff0c;自动勾选上客户(父级)&#xff0c;同时会存在只有客户&#xff08;下面没有子级的情况&am…

Apache Flink概述

Flink 是构建在数据流之上的一款有状态的流计算框架&#xff0c;通常被人们称为第三代大数据分析方案 第一代大数据处理方案&#xff1a;基于Hadoop的MapReduce 静态批处理 | Storm 实时流计算 &#xff0c;两套独立的计算引擎&#xff0c;难度大&#xff08;2014年9月&#x…

Java版工程行业管理系统源码-专业的工程管理软件-em提供一站式服务 em

​ Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目…

STM32存储左右互搏 I2C总线读写EEPROM ZD24C1MA

STM32存储左右互搏 I2C总线读写EEPROM ZD24C1MA 在较低容量存储领域&#xff0c;EEPROM是常用的存储介质&#xff0c;不同容量的EEPROM的地址对应位数不同&#xff0c;在发送字节的格式上有所区别。EEPROM是非快速访问存储&#xff0c;因为EEPROM按页进行组织&#xff0c;在连…

如何用 Java 获取 DOCX 文档的注释

现代文档协作工具有助于在比以往更紧迫的期限内从头到尾推动项目。前数字化项目协作依赖于手动标记和注释来在分发之前修改/改进关键报告和备忘录&#xff0c;而不同行业的当代团队可以使用可访问的简单修订工具来实现相同的基本目标&#xff0c;甚至更多。 DOCX 文件中的所有用…

拓扑排序--代码

模板 常用代码模板3——搜索与图论 - AcWing 拓扑排序 —— 模板题 AcWing 848. 有向图的拓扑序列 时间复杂度 O(nm), n 表示点数&#xff0c;m 表示边数 bool topsort() {int hh 0, tt -1;// d[i] 存储点i的入度for (int i 1; i < n; i )if (!d[i])q[ tt] i;while…

caj文件怎么转换成pdf?了解一下这种方法

caj文件怎么转换成pdf&#xff1f;如果你曾经遇到过需要将CAJ文件转换成PDF格式的情况&#xff0c;那么你一定知道这是一件麻烦的事情。幸运的是&#xff0c;现在有许多软件和工具可以帮助你完成这项任务。下面就给大家介绍一款使用工具。 【迅捷PDF转换器】是一款功能强大的工…

数据结构----c语言复习

数据结构----c语言复习 一.类型 1.类型的种类 char 1个字节 范围-128~127 short 2个字节 范围-32768~32767 int 4个字节 范围-2147483648~2147483647 long 4个字节 范围-2147483648~2147483647 float 4个字节 有效位为6~7位 float 8个字节 有效位为15~16为 unsigned c…