RACTF-web C0llide?(js弱类型)

源码:

const bodyParser = require("body-parser")
const express = require("express")
const fs = require("fs")
const customhash = require("./customhash")

const app = express()
app.use(bodyParser.json())

const port = 3000
const flag = "flag"
const secret_key = "Y0ure_g01nG_t0_h4v3_t0_go_1nto_h4rdc0r3_h4ck1ng_m0d3"

app.get('/', (req, res) => {
    console.log("[-] Source view")
    res.type("text")
    return fs.readFile("index.js", (err,data) => res.send(data.toString().replace(flag, "flag")))
})

app.post('/getflag', (req, res) => {
    console.log("[-] Getflag post")
    if (!req.body) {return res.send("400")}
    let one = req.body.one
    let two = req.body.two
    console.log(req.body)
    if (!one || !two) {
        return res.send("400")
    }
    if ((one.length !== two.length) || (one === two)) {
        return res.send("Strings are either too different or not different enough")
    }
    one = customhash.hash(secret_key + one)
    two = customhash.hash(secret_key + two)
    if (one == two) {
        console.log("[*] Flag get!")
        return res.send(flag)
    } else {
        return res.send(`${one} did not match ${two}!`)
    }
})

app.listen(port, () => console.log(`Listening on port ${port}`))

因为本人对nodejs一无所知。所以很多语法都是临时查的。整个源码浏览一遍之后,我们把重点放在以下几处代码上

app.post('/getflag', (req, res) => {
    console.log("[-] Getflag post")
    if (!req.body) {return res.send("400")}
    let one = req.body.one
    let two = req.body.two

大致的意思是用post方式向/getfkag传两个参数,参数名为one和two,如果没有接收到参数则返回400。

const bodyParser = require("body-parser")
body-parser是Express的中间件。模块会处理application/x-www-form-urlencoded、application/json两种格式的请求体。
经过这个中间件后,就能在所有路由处理器的req.body中访问请求参数。
body-parser默认接受方式是application/x-www-form-urlencoded。
app.use(bodyParser.json())

app.use()用于定义路由规则。详情可移步https://blog.csdn.net/u014473112/article/details/51992771

很明显用的是json格式,这就是问题所在。

hackbar的传参是x-www-form-urlencoded格式。所以怎么传都是返回400。返回的400是第一个if的结果。因为没有收到正确的参数格式所以req.body为空

 

 因此需要用bp改一下包,把Content-Type改为application/json,然后再以json格式传参

 

 

 那么目前传参格式问题就解决了。接着就要分析参数内容了。


    if ((one.length !== two.length) || (one === two)) {
        return res.send("Strings are either too different or not different enough")
    }
    one = customhash.hash(secret_key + one)
    two = customhash.hash(secret_key + two)
    if (one == two) {
        console.log("[*] Flag get!")
        return res.send(flag)
    } else {
        return res.send(`${one} did not match ${two}!`)
    }
})

app.listen(port, () => console.log(`Listening on port ${port}`))

第一个if判断两个参数长度,要求长度相同且内容且值不同

之后分别在secret_key后加上两个参数,再进行hash加密,要求hash值相同

 

构造payload:{"one":[{"2":"32"}],"two":[{"1":"c"}]}(数组为空也行)

和php的弱类型差不多。one和two值都为数组类型。因为payload数组元素相等,相当于one[1]和two[1],所以长度相等。js在拼接的时候会转换参数类型,数组转换后解析为NaN,

因此hash值相等,提交后成功获得flag

 

 






posted @ 2020-06-07 19:14  remon535  阅读(299)  评论(0编辑  收藏  举报