Ctfshow web入门 JWT篇 web345-web350 详细题解 全

CTFshow JWT web345

先看题目,提示admin。

image-20230403151543453

抓个包看看看。

image-20230403152135129

好吧我不装了,其实我知道是JWT。直接开做。

在jwt.io转换后,发现不存在第三部分的签证,也就不需要知道密钥。

全称是JSON Web Token。
通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。

JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串
JWTString = Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret)

这里只需要注意访问的是/admin/而不是/admin因为访问/admin表示访问admin.php而访问/admin/表示访问的是admin目录下默认的index.php

base64解码之后user改成admin再编码。
eyJhbGciOiJOb25lIiwidHlwIjoiand0In0.W3siaXNzIjoiYWRtaW4iLCJpYXQiOjE2ODA1MDY0NzYsImV4cCI6MTY4MDUxMzY3NiwibmJmIjoxNjgwNTA2NDc2LCJzdWIiOiJhZG1pbiIsImp0aSI6ImQxNjI3NDRhZDZiMTk0ZDk4MmEzNjcwMTkzMmFlZTFiIn1d
//不知道为什么出不来

CTFshow JWT web346

这次有算法了。

image-20230403173156058

法一:alg字段改为none,sub改为admin脚本加密。(后面一定要加点)

image-20230403203925153

法二:爆破密钥。是123456

CTFshow JWT web347

题目提示弱口令。

方法一:脚本爆破。

方法二: jwt-cracker工具爆破。

用法:
kali文件夹开终端
sudo su换成root
docker run -it --rm  jwtcrack JWT字符串

获取密码为123456,在官网上面输入密码,改成admin,自动会给我们想要的jwt字符串。 //六位有点慢,快一个小时了,不爆了。

payload:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY4MDUzODIxMSwiZXhwIjoxNjgwNTQ1NDExLCJuYmYiOjE2ODA1MzgyMTEsInN1YiI6ImFkbWluIiwianRpIjoiOTY2YTNhMmQyMDc2YzY5M2NmMmNjMDMyZTI2Mzc2YWQifQ.DhAEchqVrSifkRd7vHUhXG2fezIUGZq4LDyvUdhdEc0

CTFshow JWT web348

jwt-cracker工具爆破,密钥是aaab,秒出。

image-20230404013051054

CTFshow JWT web349

考点:公私钥泄密之【私钥】泄密。

还是JWT,不过这次变成了安全度更高的公私钥加密。


题目自带一个附件app.js,估计是源码。

image-20230802141634922

/* GET home page. */
router.get('/', function(req, res, next) {res.type('html');var privateKey = fs.readFileSync(process.cwd()+'//public//private.key');var token = jwt.sign({ user: 'user' }, privateKey, { algorithm: 'RS256' });res.cookie('auth',token);res.end('where is flag?');});router.post('/',function(req,res,next){var flag="flag_here";res.type('html');var auth = req.cookies.auth;var cert = fs.readFileSync(process.cwd()+'//public/public.key');  // get public keyjwt.verify(auth, cert, function(err, decoded) {if(decoded.user==='admin'){res.end(flag);}else{res.end('you are not admin');}});
});

可以看到,题目把私钥和公钥放在了web目录,我们访问就可以直接下载,造成了私钥公钥的泄露。

image-20230802125547575

image-20230802125614460

有了公私钥,我们就能生成JWT签名了,这里我们选择使用NodeJs脚本来生成签名。

const jwt = require('jsonwebtoken');
const fs = require('fs');var privateKey = fs.readFileSync(process.cwd()+'\\private.key');
// console.log(privateKey);var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'RS256' });
console.log(token)

环境准备:

1、安装node,安装完之后cmd输入node查看是否安装成功。

image-20230801151039971

2、从脚本代码const jwt = require('jsonwebtoken');中看出,我们需要安装jsonwebtoken(jwt)模块。安装指令如下:(指令在cmd输入)

npm install jsonwebtoken --save

image-20230802130930016

也可以直接在编译器里面安装。

image-20230802133149032

3、准备就绪,运行脚本却发现报错secretOrPrivateKey has a minimum key size of 2048 bits for RS256。意思是私钥最短长度要2048,这题的私钥太短了。

image-20230802131010274

产生报错的原因是,JWT版本15以后不支持小密钥,要求密钥最短长度是2048。

大师傅的馊主意(能解决问题但是不提倡):修改JWT的源码

找到\node_modules\jsonwebtoken目录,选择sign.js文件。

image-20230802133715702

注释130243行。防止他报错。

image-20230802133928980

image-20230802133937005

然后就可以成功生成了。

image-20230802134114737

根据源码,咱们修改完JWT直接根目录POST就能拿到flag。

image-20230802141946852

做后发现,JWT网站也支持使用公私钥伪造,要是下次私钥长度大于2048就直接用网站吧。

image-20230802134450775

CTFshow JWT web350

考点:公私钥泄密之【公钥】泄密。

可以根据公钥,修改算法从 非对称算法(比如RS256) 到 对称密钥算法(HS256)
双方都使用公钥验签,顺利篡改数据
当公钥可以拿到时,如果使用对称密码,则对面使用相同的公钥进行解密
实现验签通过


开题之后界面还是一样。

image-20230802140602138

拿JWT先去网站分析一下,修改点还是user,我们的目标是user=admin

image-20230802140624531

还是一样,有公钥泄露。但是没有私钥泄露。

image-20230802140448872

脚本如下:

const jwt = require('jsonwebtoken');
const fs = require('fs');var privateKey = fs.readFileSync(process.cwd()+'\\public.key');
// console.log(privateKey);var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)

image-20230802140734714

得到flag。

image-20230802142152162

题目有提供源码,简单看看。

image-20230802142253519

其他不看了,就看app.js。其他如node_modules文件夹其实是Node环境,没啥好看的。

app.js

var createError = require('http-errors');  // 导入 'http-errors' 模块,用于创建 HTTP 错误
var express = require('express');  // 导入 'express' 模块,用于创建 Web 应用
var ejs = require('ejs');  // 导入 'ejs' 模块,用于渲染 HTML 模板
var path = require('path');  // 导入 'path' 模块,用于处理文件路径
var cookieParser = require('cookie-parser');  // 导入 'cookie-parser' 模块,用于解析 Cookie
var logger = require('morgan');  // 导入 'morgan' 模块,用于日志记录
var session = require('express-session');  // 导入 'express-session' 模块,用于会话管理
var FileStore = require('session-file-store')(session);  // 导入 'session-file-store' 模块,用于将会话信息存储到文件中var indexRouter = require('./routes/index');  // 导入 './routes/index' 模块,用于处理根路由请求var app = express();  // 创建 Express 应用的实例// 设置会话配置
var identityKey = 'auth';  // 定义用于标识会话的键名app.use(session({name: identityKey,  // 设置会话的名称secret: 'ctfshow_session_secret',  // 设置用于加密会话数据的密钥store: new FileStore(),  // 设置会话数据存储方式为 'session-file-store',即将会话信息存储到文件中saveUninitialized: false,  // 设置不保存未初始化的会话resave: false,  // 设置不重新保存会话cookie: {maxAge: 60 * 60 * 1000 // 设置会话的有效期为 1 小时(单位是毫秒)}
}));// 设置视图引擎
app.set('views', path.join(__dirname, 'views'));  // 设置视图文件的路径为当前目录下的 'views' 目录
app.engine('html', require('ejs').__express);  // 使用 'ejs' 引擎渲染 HTML 模板
app.set('view engine', 'html');  // 设置视图引擎为 'html'app.use(logger('dev'));  // 使用 'dev' 格式的日志记录
app.use(express.json());  // 解析 JSON 请求体
app.use(express.urlencoded({ extended: false }));  // 解析 URL 编码请求体
app.use(cookieParser());  // 解析 Cookie
app.use(express.static(path.join(__dirname, 'public')));  // 设置静态文件目录为当前目录下的 'public' 目录app.use('/', indexRouter);  // 使用导入的路由模块来处理根路由请求// 捕获 404 错误并转发到错误处理中间件
app.use(function(req, res, next) {next(createError(404));  // 创建 404 错误,并转发给下一个中间件或错误处理中间件
});// 错误处理中间件
app.use(function(err, req, res, next) {// 设置本地变量,仅在开发环境中提供错误信息res.locals.message = err.message;  // 错误消息res.locals.error = req.app.get('env') === 'development' ? err : {};  // 判断是否为开发环境,若是则提供错误对象// 渲染错误页面,返回错误状态码或默认 500 状态码res.status(err.status || 500);  // 设置响应状态码为错误状态码或默认 500 状态码res.render('error', {msg:err.message});  // 渲染名为 'error' 的模板,传入错误消息作为参数
});module.exports = app;  // 导出创建的 Express 应用实例

?????我怎么感觉这是NodeJs原型链污染的源码包。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/22254.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web测试框架SeleniumBase

首先,SeleniumBase支持 pip安装: > pip install seleniumbase它依赖的库比较多,包括pytest、nose这些第三方单元测试框架,是为更方便的运行测试用例,因为这两个测试框架是支持unittest测试用例的执行的。 Seleniu…

浅析 C++ 的输入输出

输入输出 什么是输入输出输出(output)输入(input) 输入输出流的头文件iostream输出流类的抽象基类ostream输入流类的抽象基类istreamifstream 类ofstream 类fstream 类 什么是输入输出 输出(output) 于文…

深入理解负载均衡原理及算法

1. 前言 在互联网早期,网络还不是很发达,上网用户少,流量相对较小,系统架构以单体架构为主。但如今在互联网发达的今天,流量请求动辄百亿、甚至上千亿,单台服务器或者实例已完全不能满足需求,这就有了集群。不论是为了实现高可用还是高性能,都需要用到多台机器来扩展服…

实验5-3 使用函数求奇数和 (15 分)

实验5-3 使用函数求奇数和 (15 分) 本题要求实现一个函数,计算N个整数中所有奇数的和,同时实现一个判断奇偶性的函数。 函数接口定义: int even( int n ); int OddSum( int List[], int N ); 其中函数even将根据用户传…

《在细雨中呼喊》阅读笔记

《在细雨中呼喊》阅读笔记 2023年2月5号在家读完,本书就是以作者者回忆的形式来写,男一号叫孙光林,有一个哥哥孙光平,一个弟弟叫孙光明,父亲叫孙光才。书中写了四篇故事。 第一篇写的就是作者对于老家生活的回忆 小的时…

2023年第四届“华数杯”数学建模思路 - 案例:随机森林

## 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林? 随机森林属于 集成学习 中的 Bagging(Bootstrap AGgregation 的简称) 方法。如果用图来表示他们之…

Android 之 AudioManager ( 音频管理器 )

本节引言: 在多媒体的第一节,我们用SoundPool写了个Duang的示例,小猪点击一个按钮后,突然发出"Duang"的 一声,而且当时的声音很大,吓死宝宝了 ,好在不是上班时间,上班时间…

DBoW3库的编译与安装(亲测可用)

1. DBoW3库介绍 DBoW3是DBoW2的增强版,这是一个开源的C库,用于给图像特征排序,并将图像转化成视觉词袋表示。它采用层级树状结构将相近的图像特征在物理存储上聚集在一起,创建一个视觉词典。DBoW3还生成一个图像数据库&#xff0c…

【LeetCode】516. 最长回文子序列

文章目录 1. 思路讲解1.1 创建dp表1.2 状态转移方程1.3 不需考虑边界问题 2. 整体代码 1. 思路讲解 1.1 创建dp表 此题采用动态规划的方法,创建一个二维dp表,dp[i][j]表示s[i, j]中最大回文子序列的长度。且我们人为规定 i 是一定小于等于 j 的。 1.2…

【大数据】Flink 从入门到实践(一):初步介绍

Flink 从入门到实践(一):初步介绍 Apache Flink 是一个框架和分布式处理引擎,用于在 无边界 和 有边界 数据流上进行 有状态 的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。 1.架构 1…

C++、Java、JavaScript和Python数组对比

C、Java、JavaScript和Python数组对比 C、Java、JavaScript和Python都有数组的概念,但在不同的编程语言中,数组的实现方式和用法可能会有所不同。 1. C:使用C时,可以使用内置的数组来存储一组具有相同数据类型的元素。数组在…

Kubernetes——理论基础

Kubernetes——理论基础 一、Kubernetes 概述1.K8S 是什么?2.为什么要用 K8S?3.Kubernetes 主要功能 二、Kubernetes 集群架构与组件三、Master 组件1.Kube-apiserver2.Kube-controller-manager3.Kube-scheduler4.配置存储中心——etcd 四、Node 组件1.Kubelet2.Ku…

【Python】模块学习之locust性能测试

目录 背景 安装 测试代码 运行命令 资料获取方法 背景 locust是一个python的第三方库,用于做性能测试,可使用多台机器同时对一台服务器进行压测,使用其中一台机器作为主节点,进行分布式管理 博主测试接口的时候一直是使用p…

Zebec APP:构建全面、广泛的流支付应用体系

目前,流支付协议 Zebec Protocol 基本明确了生态的整体轮廓,它包括由其社区推动的模块化 Layer3 构架的公链 Nautilus Chain、流支付应用 Zebec APP 以及 流支付薪酬工具 Zebec payroll 。其中,Zebec APP 是原有 Zebec Protocol 的主要部分&a…

CentOS 虚拟机磁盘扩容(非常实用)

新手村的选手在刚开始安装使用 CentOS 虚拟机时,很多选项都会按照推荐操作来,比如:磁盘推荐大小为 20 GB;但随着后面的使用,总会因为“磁盘根目录不足”原因,而导致软件无法安装、虚拟机无法正常运行等&…

人工智能在计算机视觉中的应用与挑战

引言 计算机视觉是人工智能领域的一个重要分支,旨在让计算机能够像人一样理解和解释视觉信息,实现图像和视频的自动识别、理解和分析。计算机视觉技术已经在许多领域产生了深远的影响,如人脸识别、自动驾驶、医学影像分析等。本篇博客将深入…

vue3使用iframe引入其他网站,vue-router路由跳转后页面空白,刷新之后才展示页面内容乌龙事件

问题描述:vue3项目的页面A跳转到页面B时,页面B页面是空白的,需要手动刷新一下才能恢复正常,在页面A中用iframe引入了别的网站(后续事实证明,跟iframe没一毛钱的关系)。着急的童鞋可以直接拉到底…

Linux JDK 安装

文章目录 安装步骤1、卸载openJDK1.1 查看当前Linux系统是否安装java,卸载openjdk1.2 卸载系统中已经存在的openJDK 2、在/usr/local目录下创建java目录3、上传JDK到Linux系统4、解压jdk5、配置Jdk环境变量6、重新加载/etc/profile文件,让配置生效7、测试安装是否成…

【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解

PS:本要求基于华为的eNSP模拟软件进行 具体要求: 完成步骤: 1、根据要求,对网络进行IP设计,如下图 2、对已经设计好的IP思路,对每一个路由器进行IP配置 R1路由器上的IP配置: R6路由器上的IP…

Windows terminal 添加 git bash 解决git中文乱码显示问题

Windows terminal 添加 git bash 解决git中文乱码显示问题 在 windows terminal 中配置git 说明: 点击箭头选择设置 说明: 点击"添加新配置文件"配置名称命令行,可执行文件的具体语句 C:\Program Files\Git\bin\bash.exe启动目录…