原型链污染

文章目录

  • 1. javascript 原型链
  • 2. 原型链变量的搜索
  • 3. prototype 原型链污染
  • 4. 原型链污染例题
    • 4.1 题1:
    • 4.2.题2:

1. javascript 原型链

js在ECS6之前没有类的概念,之前的类都是用funtion来声明的。如下

img

可以看到b在实例化为test对象以后,就可以输出test类中的属性a了。这是为什么呢?

原因在于js中的一个重要的概念:继承。

而继承的整个过程就称为该类的原型链。

在javascript中,每个对象的都有一个指向他的原型(prototype)的内部链接,这个原型对象又有它自己的原型,直到null为止
function i(){this.a = "test1";this.b = "test2";}

img

可以看到其父类为object,且里面还有许多函数,这就解释了为什么许多变量可以调用某些方法。

在javascript中一切皆对象,因为所有的变量,函数,数组,对象 都始于object的原型即object.prototype。同时,在js中只有类才有prototype属性,而对象却没有,对象有的是__proto__和类的prototype对应。且二者是等价的

img

当我们创建一个类时

img

原型链为

b -> a.prototype -> object.prototype->null

创建一个数组时

img

原型链为

c -> array.prototype -> object.prototype->null

创建一个函数时

img

原型链为

d -> function.prototype -> object.prototype->null

创建一个日期

img

原型链为

f -> Data.prototype -> object.prototype->null

所以,测试之后会发现:javascript 一切皆对象,一切皆始于 object.prototype

2. 原型链变量的搜索

下面先看一个例子:

img

我们实例要先于在i中添加属性,但是在j中也有了c属性。这是为什么呢

答:

当要使用或输出一个变量时:首先会在本层中搜索相应的变量,如果不存在的话,就会向上搜索,即在自己的父类中搜索,当父类中也没有时,就会向祖父类搜索,直到指向null,如果此时还没有搜索到,就会返回 undefined

所以上面的过程就很好解释了,原型链为

j -> i.prototype -> object.prototype -> null

所以对象j调用c属性时,本层并没有,所以向上搜索,在上一层找到了我们添加的test3,所以可以输出。

3. prototype 原型链污染

先看一个小例子:

mess.js----(function()
{var secret = ["aaa","bbb"];secret.forEach();
})();

attach.html

img

结果:

img

在mess.js中我们声明了一个数组 secret,然后该数组调用了属于 Array.protottypeforeach方法,如下

img

但是,在调用js文件之前,js代码中将Array.prototype.foreach方法进行了重写,而prototype链为secret -> Array.prototype ->object.prototype,secret中无 foreach 方法,所以就会向上检索,就找到了Array.prototype 而其foreach方法已经被重写过了,所以会执行输出。

这就是原型链污染。很明显,原型链污染就是:在我们想要利用的代码之前的赋值语句如果可控的话,我们进行 ——__proto__ 赋值,之后就可以利用代码了

4. 原型链污染例题

在javascript中可以通过 test.a or test['a'] 对数组的元素进行访问,如下:

img

同时对对象来说说也是一样的

img

所以我们上述说的prototype也是一样的

img

那就很明显了,原型链污染一般会出现在对象、或数组的键名或属性名可控,而且是赋值语句的情况下。

4.1 题1:

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();
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传入的值,都是可控的。所以可以构造原型链污染,下面我们先本地测试一下。

img

下面我们给出payload和结果

img

注:要使用json传值,不然会出现错误

4.2.题2:

'use strict';const express = require('express');
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser');
const path = require('path');const isObject = obj => obj && obj.constructor && obj.constructor === Object;function merge(a, b) {for (var attr in b) {if (isObject(a[attr]) && isObject(b[attr])) {merge(a[attr], b[attr]);} else {a[attr] = b[attr];}}return a
}function clone(a) {return merge({}, a);
}// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
const admin = {};// App
const app = express();
app.use(bodyParser.json())
app.use(cookieParser());app.use('/', express.static(path.join(__dirname, 'views')));
app.post('/signup', (req, res) => {var body = JSON.parse(JSON.stringify(req.body));  {"__proto__": {"admin":1}}var copybody = clone(body)if (copybody.name) {res.cookie('name', copybody.name).json({"done": "cookie set"});} else {res.json({"error": "cookie not set"})}
});
app.get('/getFlag', (req, res) => {var аdmin = JSON.parse(JSON.stringify(req.cookies))if (admin.аdmin == 1) {res.send("hackim19{}");} else {res.send("You are not authorized");}
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

先分析一下题目,获取flag的条件是admin.аdmin == 1而admin 本身是一个object,其admin 属性本身并不存在,而且还有一个敏感函数 merg

function merge(a, b) {for (var attr in b) {if (isObject(a[attr]) && isObject(b[attr])) {merge(a[attr], b[attr]);} else {a[attr] = b[attr];}}return a
}

merge 函数作用是进行对象的合并,其中涉及到了对象的赋值,且键值可控,这样就可以触发原形链污染了

下面我们本地测试一下

img

是undefined,为什么呢?下面我们看下

img

原来我们在创建字典的时候,__proto__,不是作为一个键名,而是已经作为__proto__给其父类进行赋值了,所以在test.__proto__中才有admin属性,但是我们是想让__proto__作为一个键名的.

那应该怎么办呢?可以使用 JSON.parse

img

JSON.parse 会把一个json字符串 转化为 javascript的object

这样就不会在创建类的时候直接给父类赋值了

而题目中也出现了JSON.parse

var body = JSON.parse(JSON.stringify(req.body));

这样我们就可以愉快地进行原型链污染了

payload:

img

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

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

相关文章

ElasticSearch:全文检索及倒排索引原理

1.从全文检索说起 首先介绍一下结构化与非结构化数据&#xff1a; 结构化数据将数据具有的特征事先以结构化的形式定义好&#xff0c;数据有固定的格式或有限的长度。典型的结构化数据就是传统关系型数据库的表结构&#xff0c;数据特征直接体现在表结构的字段上&#xff0c;…

电商数据获取:网络爬虫还是付费数据接口?

随着电商行业的迅速发展&#xff0c;对电商数据的需求也越来越大。在获取电商数据时&#xff0c;常常面临一个选择&#xff1a;是自己编写网络爬虫进行数据爬取&#xff0c;还是使用现有的付费数据接口呢&#xff1f;本文将从成本、可靠性、数据质量等多个角度进行分析&#xf…

深入学习 Redis - 事务、实现原理、指令使用及场景

目录 一、Redis 事务 vs MySQL事务 二、Redis 事务的执行原理 2.1、执行原理 2.2、Redis 事务设计这么简单&#xff0c;为什么不涉及成 MySQL 那样强大呢&#xff1f; 三、Redis 事务的使用 3.1、使用场景 3.2、具体演示 开启/执行/放弃事务 watch 监控 watch 实现原理…

Dockerfile部署golang

使用go镜像打包&#xff0c;运行在容器内 redis和mysql用外部的 项目目录结构 w1go项目&#xff1a; Dockerfile # 这种方式是docker项目加上 本地的mysql和redis环境 # go打包的容器 FROM golang:alpine AS builder# 为我们镜像设置一些必要的环境变量 ENV GO111MODULEon …

Nginx可视化NginxWebUI

Nginx可视化Web Github:https://github.com/cym1102/nginxWebUI 支持window、linux 安装方式支持docker、window直接运行 jar包cmd运行&#xff1a;port可自行替换 java -jar -Dfile.encodingUTF-8 D:/软件/Nginx-Ui/nginxWebUI-3.6.3.jar --server.port8380 --project.hom…

centos7 yum源安装出错及更新问题

如下 首先&#xff0c;在搜索jdk时报错如下&#xff1a; 解决办法 1、进入 yum的repo目录 cd /etc/yum.repos.d/2、修改所有的CentOS文件内容 sed -i s/mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-*sed -i s|#baseurlhttp://mirror.centos.org|baseurlhttp://vau…

HDFS集群滚动升级以及回滚相关

HDFS集群滚动升级以及回滚相关 介绍不停机滚动升级非联邦HA集群联邦HA集群 停机升级--非HA集群HDFS集群降级和回滚异同点共同点不同点 HA集群降级&#xff08;downgrade&#xff09;注意事项 集群回滚操作 介绍 在hadoop v2中&#xff0c;HDFS支持namenode高可用&#xff08;H…

Benchmarking Augmentation Methods for Learning Robust Navigation Agents 论文阅读

论文信息 题目&#xff1a;Benchmarking Augmentation Methods for Learning Robust Navigation Agents: the Winning Entry of the 2021 iGibson Challenge 作者&#xff1a;Naoki Yokoyama, Qian Luo 来源&#xff1a;arXiv 时间&#xff1a;2022 Abstract 深度强化学习和…

java.util.NoSuchElementException: No value present-报错(已解决)

阿丹&#xff1a; 今天在spring-boot整合MongoDB的过程中出现了下面的错误&#xff0c;是因为追求新技术、更优雅产生的。 记录一下。 错误截图如下&#xff1a; 错误位置代码如下&#xff1a; 主要问题&#xff08;问题原因&#xff09;&#xff1a; 因为之前升级了我的jdk的…

Red Hat 安装MySQL 8.0与 Navicat

目录 Red Hat 安装 MySQL 8.0 1、更新软件包列表 2、安装MySQL服务器和客户端 3、启动MySQL服务 4、确保MySQL服务器正在运行 5、root 用户的密码 6、登录MySQL&#xff0c;输入mysql密码 7、MySQL默认位置 Red Hat 安装 Navicat 1、下载 Navicat 2、执行命令 Red H…

布基纳法索ECTN(BESC)申请流程

根据BURKINA FASO布基纳法索签发于 11/07/2006法令编号 00557的规定: 自2006年11月07 日起所有出口至布基纳法索&#xff08;Burkina Faso&#xff09;的货物&#xff0c;必须申请ECTN/BESC。ECTN是ELECTRONIC CARGO TRACKING NOTE的英文缩写&#xff0c;BESC是BORDEREAU DE SU…

Maven分模块-继承-聚合-私服的高级用法

Maven分模块-继承-聚合-私服的高级用法 JavaWeb知识&#xff0c;介绍Maven的高级用法&#xff01;&#xff01;&#xff01; 文章目录 Maven分模块-继承-聚合-私服的高级用法1. 分模块设计与开发1.1 介绍1.2 实践1.2.1 分析1.2.2 实现 1.3 总结 2. 继承与聚合2.1 继承2.1.1 继承…

vue2中使用mock数据发送请求

1.安装 npm i mockjs1.1 2.准备json数据 说明&#xff1a;mock数据需要的图片放置到public文件夹中&#xff08;原封不动的打包到dist文件夹&#xff09; [{"id": "1","imgUrl": "/images/banner1.jpg"},{"id": "2&qu…

python excel 操作

excel文件内容如下&#xff1a; 一、xlrd 读Excel 操作 1、打开Excel文件读取数据 filexlrd.open_workbook(filename)#文件名以及路径&#xff0c;如果路径或者文件名有中文给前面加一个 r 2、常用函数 &#xff08;1&#xff09;获取一个sheet工作表 table file.sheets(…

C++11 新特性 ---- 原始字面量

一、原始字面量 R “xxx(原始字符串)xxx”&#xff0c;其中&#xff08;&#xff09;两边的字符串可以省略。 #include <iostream> #include <string> using namespace std; int main() {string str1 R"(D:\hello\heheda\test.txt)";string str2 R&q…

day1-牛客67道剑指offer-JZ4 JZ6 JZ7 JZ9 JZ11 JZ69 JZ70 替换空格 斐波那契数列及其变形 左移/右移运算符

文章目录 1. JZ4 二维数组中的查找暴力法右上角往左下角逼近二分查找-左闭右开区间 2. 替换空格3. JZ6 从尾到头打印链表4. JZ7 重建二叉树思路1哈希加速 5. JZ9 用两个栈实现队列6. JZ11 旋转数组的最小数字常规遍历二分法 7. 斐波那契数列动态规划递归 8. JZ69 跳台阶动态规划…

Swintransformer模型的优化

SwinTransformer模型优化 文章目录 SwinTransformer模型优化1.SwinTransformer概述2.性能瓶颈分析3.模型优化3.1.transpose消除3.2.更好的layergroup3.1.1.SliceOp3.1.2.SqueezeOp3.1.3.weight切分 4.优化效果 1.SwinTransformer概述 自从Transformer在NLP任务上取得突破性的进…

UE5 半透明覆层材质

文章目录 前言介绍示例1示例2示例3 前言 本文采用虚幻5.2.1版本演示&#xff0c;介绍半透明覆层材质&#xff08;覆层材质&#xff09;。 介绍 半透明覆层材质是 UE5.1 版本 更新的功能&#xff0c;使用半透明覆层材质&#xff0c;可以轻松的给物体表面附着一层材质。 在UE5…

[IDEA]使用idea比较两个jar包的差异

除了一些小工具外&#xff0c;idea自带了jar包比较的功能。 把需要比对的jar包放到任意目录下&#xff0c;然后选中两个需要比较的jar包&#xff0c;右键&#xff0c;选择Compare Archives&#xff0c;然后就可以比较了。 这次疏忽了&#xff0c;每次打包前需要commit界面看一下…

Unity 编辑器选择器工具类Selection 常用函数和用法

Unity 编辑器选择器工具类Selection 常用函数和用法 点击封面跳转下载页面 简介 在Unity中&#xff0c;Selection类是一个非常有用的工具类&#xff0c;它提供了许多函数和属性&#xff0c;用于操作和管理编辑器中的选择对象。本文将介绍Selection类的常用函数和用法&#xff…