原型链污染

文章目录

  • 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 now

var 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】用户和权限

文章目录 前言什么是 root 用户su 命令和 exit 命令sudo 命令为普通用户配置 sudo 认证 用户、用户组管理什么是Linux 用户和用户组用户组管理用户管理创建用户删除用户查看用户所属组将指定用户添加到指定用户组中 查看当前系统的用户和用户组 权限控制权限信息 修改权限控制修…

【IDEA问题】下载不了源代码

引出问题 最近不知道怎么打开 IDEA&#xff0c;本想查看源代码&#xff0c;然后点击下载源码&#xff0c;总是报找不到此对象的源代码。百度找了半天&#xff0c;GPT问了半天还是解决不了&#xff0c;直到遇到了这篇&#xff1a;idea中无法下载源码问题解决&#xff0c;终于得…

74、75、76——tomcat项目实战

tomcat项目实战 tomcat 依赖 java运行环境,必须要有jre , 选择 jdk1.8 JvmPertest 千万不能用 kyj易捷支付 项目机器 选择 一台机器 ,安装jdk1.8的机器下载tomcat的包 上传到机器,解压tomcattomcat文件 bin文件夹: 启动文件 堆栈配置文件 catalina.sh JAVA_OPTS="-Xm…

Nginx反向代理配置+负载均衡集群部署

文章目录 负载均衡反向代理基础环境部署&#xff1a;什么是代理实验环境图流量过程 环境部署准备两台Web服务器安装Nginx准备页面内容添加主机名 代理服务器配置 修改windos hosts文件测试&#xff1a;终端浏览器 负载均衡反向代理基础环境部署&#xff1a; 什么是代理 正向代…

腾讯云轻量应用服务器CPU型号?处理器主频多少?

腾讯云轻量应用服务器CPU型号是什么&#xff1f;处理器主频多少&#xff1f;轻量应用服务器不支持指定CPU处理器型号&#xff0c;目前腾讯云服务器网账号下的轻量应用服务器&#xff0c;CPU采用2.5GHz主频的Intel(R) Xeon(R) Gold 6133 处理器&#xff0c;睿频 3.0GHz&#xff…

160. 相交链表 题解

题目描述&#xff1a;160. 相交链表 - 力扣&#xff08;LeetCode&#xff09; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 注&#xff1a;本题中链表相交是“Y”型的&am…

ClickHouse(十三):Clickhouse MergeTree系列表引擎 - ReplicingMergeTree

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

unity海康威视原生SDK拉取网络摄像头画面,并展示在一个Material上

原理是使用sdk获取视频流&#xff0c;格式为YUV&#xff0c;然后分离YUV通道到三张不同的Texture2D上&#xff0c;通过shader将三个通道重新输出为原始图像。 我将所用的各个部分已经整理成一个压缩包&#xff0c;免积分下载 压缩包结构如下 使用步骤 1 DLL:放在Plugins文件…

wordpress数据表中标签和分类如何区分?

wordpress中标签和分类是什么关系怎么区分&#xff1f;最后有一个群的网友告诉了我文章ID和标签ID的关系是放在了wp_term_relationships表中&#xff0c;然后我百度了下这个表的结构和相关介绍&#xff0c;发现果然如此&#xff0c;先把文章保存起来&#xff1a; wp_term_rela…

那些年的golang开发经验记录

goland 问题CreateProcess error216, 该版本的 %1 与你运行的 Windows 版本不兼容。请查看计算机的系统信息&#xff0c;然后联系软件发布者 Cannot run program "......" (in directory "D:\project\go\awesomeProject\src\test"): CreateProcess error2…

nginx基于主机和用户访问控制以及缓存简单例子

一.基于主机访问控制 1.修改nginx.conf文件 2.到其他主机上测试 &#xff08;1&#xff09;191主机 &#xff08;2&#xff09;180主机 二.基于用户访问控制 1.修改nginx.conf文件 2.使用hpasswd为用户创建密码文件&#xff0c;并指定到刚才指定的密码文件webck 3.测试…

Cocos Creator 3.8 后期效果 Shader 编写(2/2) 进阶篇

前言 在上一篇文章中&#xff0c;麒麟子给大家分享了如何在 Cocos Creator 3.8 中的自定义管线中&#xff0c;添加属于自己的后期效果 Shader。 但基于 BlitScreen 的方案&#xff0c;我们只能编写最简单后效 Shader&#xff0c;如果我们想要支持更多复杂的 Shader&#xff0c…

nginx动态同步配置模块nginx-upsync-module

使用场景简介 nginx一般直接在配置文件里配置upstream即可实现负载均衡&#xff0c;但有些特定的环境下此种方式就显得有些局限性。比如后台动态调整节点的时候&#xff1b;调整节点后不想修改配置文件重启nginx。 可以将配置文件从nginx本地迁移到其他第三方服务上如etcd、c…

Claude 2、ChatGPT、Google Bard优劣势比较

​Claude 2&#xff1a; 优势&#xff1a;Claude 2能够一次性处理多达10万个tokens&#xff08;约7.5万个单词&#xff09;。 tokens数量反映了模型可以处理的文本长度和上下文数量。tokens越多&#xff0c;模型理解语义的能力就越强&#xff09;。它在法律、数学和编码等多个…

LinearAlgebraMIT_8_TheRankOfMatrix

这节课中主要讲解根据秩来判断方程组/矩阵的(solvability)解情况&#xff0c;即通过秩来判断(aumented matrix)增广矩阵的解。我们需要直接求解方程组的解就是求解矩阵的解。 x.1 判断(非齐次线性方程组)Axb是否有解 我们以下面这个方程组为例&#xff0c;它具有3个约束条件和…

虹科方案 | 汽车总线协议转换解决方案(二)

上期说到&#xff0c;虹科的PCAN-LIN网关在CAN、LIN总线转换方面有显著的作用&#xff0c;尤其是为BMS电池通信的测试提供了优秀的解决方案。假如您感兴趣&#xff0c;可以点击文末相关链接进行回顾&#xff01; 而今天&#xff0c;虹科将继续给大家带来Router系列在各个领域的…

AI 绘画Stable Diffusion 研究(六)sd提示词插件

大家好&#xff0c;我是风雨无阻。 今天为大家推荐一款可以有效提升我们使用 Stable Diffusion WebUI 效率的插件&#xff0c; 它就是 prompt-all-in-one&#xff0c; 它不但能直接将 WebUI 中的中文提示词转换为英文&#xff0c;还能一键为关键词加权重&#xff0c;更能建立常…

Redis的AOF持久化

除了RDB持久化功能之外&#xff0c;Redis还提供了AOF持久化功能。与RDB 持久化通过保存数据库中的键值对来记录数据库状态不同&#xff0c;AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的&#xff0c;如下图所示。 举个例子&#xff0c;如果我们对空白的数据…

vim学习笔记(致敬vim作者)

vim cheat sheet 30. vim 删除大法 vim 删除某个字符之后改行的其他的字符&#xff1f;删除某行之后的其他行&#xff1f;删除某个字符之后的其他字符&#xff1f;【1】删除单个字符&#xff1f; 跳到要删除的字符位置 按下d键然后按下shift 4键 【2】删除某行之后的其他行…

vite+vue3项目环境搭建

1.安装 npm init vite 2.输入项目名称 vue3-project 3.选择框架 说明&#xff1a;vue 4.选择类别 说明&#xff1a;JavaScript 5.进入文件夹 cd vue3-project yarn npm run dev 6.打开local