JAVA安全—JWT攻防&Swagger自动化&Druid泄露

前言

依旧是Java安全的内容,今天主要是讲JWT这个东西,JWT之前讲过了,是Java中特有的身份校验机制,原理我就不再多说了,主要是看看它的安全问题,至于Swagger和Druid顺便讲一下。

Druid泄露

Druid是阿里巴巴数据库事业部出品,为监控而生的数据库连接池。Druid提供的监控功能,监控SQL的执行时间、监控Web URI的请求、Session监控。当开发者配置不当时就可能造成未授权访问漏洞。

可以看到里面有sql监控,就是执行了哪些sql语句。

还有session监控,就是会显示已经登录的用户的session,因为我这里只是简单演示一下,就啥也没有。

那么它主要的危害就是信息泄露,直接拼接URL路径,尝试能否直接未授权访问系统功能点。

结合泄露URL路径和Session信息,利用BurpSuite进行尝试登录。也就是说有了登录地址,也有用户的session,那么我就可以以这个用户的身份去登录。

Swagger自动化

这个之前也是讲过的,就是Swagger给开发者提供了一个接口测试的页面,将项目中所有(想要暴露的)接口展现在WEB页面上,并可以进行接口调用和调式的服务(一般都是用SpringBoot框架搭建该服务)

我们来批量的去测试一下,因为太多的话手动测不过来,postman导入Swagger地址。

成功导入,然后批量去测试即可。

接着讲一下postman和BP的联动,其实就是设置一个代理就行,postman代理设置和BP一样即可。

再次运行可以看到BP这边有大量的数据包,这时就可以利用BP上的插件去进行漏洞探测,还可以联动一些漏扫,如Xray,这个后续再说了。

JWT攻防

首先来了解一下JWT的组成。

1、标头(Header)

Header是JWT的第一个部分,是一个JSON对象,主要声明了JWT的签名算法,如"HS256"、"RS256"等,以及其他可选参数,如"kid"、"jku"、"x5u"等

alg字段通常用于表示加密采用的算法。如"HS256"、"RS256"等(HS对称加密、RS非对称加密)

typ字段通常用于表示类型

还有一些其他可选参数,如"kid"、"jku"、"x5u"等

2、有效载荷(Payload)

Payload是JWT的第二个部分,这是一个JSON对象,主要承载了各种声明并传递明文数据,用于存储用户的信息,如id、用户名、角色、令牌生成时间和其他自定义声明。

iss:该字段表示jwt的签发者。

sub:该jwt面向的用户。

aud:jwt的接收方。

exp:jwt的过期时间,通常来说是一个时间戳。

iat:jwt的签发时间,常来说是一个时间戳。

jti:此jwt的唯一标识。通常用于解决请求中的重放攻击。该字段在大多数地方没有被提及或使用。因为使用此字段就意味着必须要在服务器维护一张jti表, 当客户端携带jwt访问的时候需要在jti表中查找这个唯一标识是否被使用过。使用这种方式防止重放攻击似乎让jwt有点怪怪的感觉, 毕竟jwt所宣称的优点就是无状态访问

3、签名(Signature)

Signature是对Header和Payload进行签名,具体是用什么加密方式写在Header的alg 中。同时拥有该部分的JWT被称为JWS,也就是签了名的JWT。

第一部分:对 JSON 的头部做 base64 编码处理得到

第二部分:对 JSON 类型的 payload 做 base64 编码处理得到

第三部分:分别对头部和载荷做base64编码,并使用.拼接起来

使用头部声明的加密方式,对base64编码前两部分合并的结果加盐加密处理,作为JWT

JWT识别

识别我们可以人工识别,就是直接看cookie的格式就行,也不算难,就是要一个一个数据包来看有点麻烦罢了。

还可以用BP中的插件来自动化识别,这个比较简单快速,自带的插件有JSON Web Tokens,就在

BP商店里面。但是我这里下载不了,说我BP版本不够高,好吧,那就不演示这个插件了。

还有一个插件就是Hae,但是需要自己去下载导入BP,BP商店没有自带。但是我这里啥也没识别出来,不知道为啥,访问的网站明明是有JWT,妈的。

接着来讲一下JWT常见的安全问题,分别是空加密算法、未校验签名、暴力破解密钥、源码泄漏密匙。

空加密算法

签名算法可被修改为none,JWT支持将算法设定为"None"。如果"alg"字段设为"None",那么签名会被置空,这样任何token都是有效的,这里直接用CTFshow里面的题目来讲解,先来看web345。

查看源码得知叫我们访问admin。

抓包发现有JWT。

拿去解密一下,发现我们sub的值是user,sub上面我们说过是该JWT面向的用户,那么这题估计是要admin身份才能拿到flag。

注意到这里的alg为None,也就是说没用到加密算法,我们可以直接修改。这里有个坑,直接在这个网站修改的话是空白的,并不会给你生成修改后的JWT。

我们可以直接在BP上面进行base64解码,可以看到是能解出来数据的,因为第一和第二部分是用base64进行加密的。

我们修改user为admin之后再进行base64加密,就得到新的JWT了,然后替换掉原来的JWT即可得到flag。

未校验签名

某些服务端并未校验JWT签名,可以尝试修改payload后然后直接请求token或者直接删除signature再次请求查看其是否还有效。

来看CTFshow的Web346。

抓包解密JWT,我们发现这里的alg设置为HS256了,不再是空加密。那么此时我们直接把user改为admin肯定是不行的,因为你没有秘钥是无法解密的。

这时候就有两个思路,要么就爆破HS256的秘钥,要么就把alg改为空再去除签名,因为它如果不去校验第三部分的签名的话,那么有没有这一部分其实没影响的,这里我们要用到一个工具去修改。

https://github.com/ticarpi/jwt_tool

先输入命令让它先去解析你的JWT,我这里有点小乱码,但是问题不大,可以看到能成功解析出数据。

复制代码
项目命令帮助
#解析JWT
python3 jwt_tool.py your_JWT

# 使用None算法
python3 jwt_tool.py your_JWT -X a

# 自定义修改生成
python3 jwt_tool.py your_JWT -T

# 使用字典破解
python3 jwt_tool.py your_JWT -C -d dictionary.txt

# 指定密码测试
python3 jwt_tool.py your_JWT -C -p password_here

接着自定义修改,我们选择1,对alg进行修改。

提示叫我们输入新的值,输入None,把alg算法修改为空。

改完之后输入0,结束对头部的修改,进入下一步去修改payload。

我们选择5,修改user为admin,修改完之后输入0结束修改,就会生成一个新的JWT。

然后我们用新生成的JWT去替换原来的JWT去发包,结果还是不行。

这是为啥呢,上面说过如果"alg"字段设为"None",那么签名会被置空,这样任何token都是有效的,也就是说不会校验你的签名,所以直接把签名删除再发包即可。

秘钥爆破

这种情况就是虽然它用了加密,但是秘钥过于简单,爆破一下就出来,这里用Web347进行演示。

解密JWT可以看到用了HS256进行加密。

我们利用工具进行秘钥的爆破,爆破出秘钥为123456。

剩下的直接来到网站改就行,秘钥天123456,user改为admin即可。

信息泄露

有时候秘钥的泄露或者加密源码的泄露,也会造成安全问题,利用web349进行演示。

扫下目录发现有个私钥泄露。

直接下载来看一下。

然后又从题目中下载了源码,通过分析源码我们可以知道是通过私钥加密,公钥解密。

现在我们已经知道私钥了,那么我们直接进行修改加密即可,记得安装PyJWT库才行。

复制代码
import jwt
public = open('private.key', 'r').read() //读取当前目录下的私钥
payload={"user":"admin"}  //user的值设置为admin
print(jwt.encode(payload, key=public, algorithm='RS256'))

用生成的JWT替换掉原本的JWT即可,记得改为POST提交方式,因为源码中的解密是要POST去提交。

web350也是信息泄露,不过这题有点意思。

直接把源码包下载下来看看,可以看到也是私钥加密,公钥解密的。

但是问题是它源码中只给出了公钥,没有给出私钥啊,如果我们用公钥加密的肯定是解密不出来的。怎么办呢,我们都知道RSA是两个密钥一个加密一个解密,而上面说到的HS256加解密都是同一个密钥,现在我们只知道一个密钥,那我们是不是可以修改alg的值为HS250,那么这时我们公钥加密再公钥解密完全是没问题的。

复制代码
var jwt = require('jsonwebtoken');
var fs = require('fs');
var privateKey = fs.readFileSync('./public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)

利用JS代码生成新的JWT。

利用新生成的JWT替换掉原本的即可,记得改为POST请求。

总结

主要讲了JWT的安全问题,总的来说就那么几种方式利用,空算法、密钥爆破、签名未校验。关于Druid和Swagger以后讲到接口安全再细讲了。

最后,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。

相关推荐
考虑考虑15 小时前
Jpa使用union all
java·spring boot·后端
用户37215742613515 小时前
Java 实现 Excel 与 TXT 文本高效互转
java
浮游本尊16 小时前
Java学习第22天 - 云原生与容器化
java
渣哥18 小时前
原来 Java 里线程安全集合有这么多种
java
间彧18 小时前
Spring Boot集成Spring Security完整指南
java
间彧19 小时前
Spring Secutiy基本原理及工作流程
java
Java水解20 小时前
JAVA经典面试题附答案(持续更新版)
java·后端·面试
洛小豆1 天前
在Java中,Integer.parseInt和Integer.valueOf有什么区别
java·后端·面试
前端小张同学1 天前
服务器上如何搭建jenkins 服务CI/CD😎😎
java·后端
ytadpole1 天前
Spring Cloud Gateway:一次不规范 URL 引发的路由转发404问题排查
java·后端