网安学习第26天 Java安全 swagger&jwt&ctfshow345-350
使用私钥进行签名,公钥进行验证,所以,如果我们需要修改sub的值,修改后,让服务器还能识别,就需要得到私钥。typ字段通常用于表示类型还有一些其他可选参数,如"kid"、"jku"、"x5u"等。Payload是JWT的第二个部分,这是一个JSON对象,主要承载了各种声明并传递明文数据,用于存储用户的信息,如id、用户名、角色、令牌生成时间和其他自定义声明。Header是JWT的第一个部分,是一个
一、Druid监控
Druid是阿里巴巴数据库事业部出品,为监控而生的数据库连接池。Druid提供的监控功能,监控SQL的执行时间、监控Web URI的请求、Session监控。当开发者配置不当时就可能造成未授权访问漏洞。
可能存在的攻击点
1、直接拼接URL路径,尝试能否直接未授权访问系统功能点。
如图就是一个Druid监控的访问路径。

这是设置了账户密码,如果没有设置。就可以直接进入
2、结合泄露URL路径和Session信息,利用BurpSuite进行尝试登录。
这就是Druid监控的界面,可以看到他是存在一些铭感信息的
3、利用Cookie编辑器替换Session,再次访问后台路径尝试进入后台。
二、Swagger接口
1、Swagger是什么
Swagger 是一种用于 生成、展示和测试 API 接口文档 的工具。在 Java / Spring Boot 项目里,Swagger 最常见的作用就是:
后端写完接口后,Swagger 自动生成一个网页,前端或测试人员可以在网页上查看接口、参数、返回值,并直接测试接口。
比如是这个样子

所以可以对这个接口进行漏洞测试,看是否存在未授权访问、sql注入、文件上传等漏洞。由于接口太多,一个个接口测试的话太费时间,所以一般会采用自动化接口漏洞安全测试。
2、接口测试
这里我们可以手动的自己一个一个测试也可以使用自动化工具来测试。
Postman:https://github.com/hlmd/Postman-cn
首先需要在postman中导入这个接口地址,这里的接口地址就是页面中的:
http://127.0.0.1:8088/v2/api-docs
然后在postman中导入,导入成功后会看到这样一个文档:

然后需要配置一下这个变量

配置完成后就可以点击RUN进行测试了:


然后他就在自动的帮我们进行测试。
除了使用postman测试外,还可以联动BurpSuit来进行测试。
首先需要在postman中设置代理;

然后同样在BP中设置好后,就可以进行测试,这时候我们看BP:

就可以看到postman传过来的数据包。同时也可以将BP与X-ray进行联动进行漏洞扫描。
三、JWT
1、JWT是什么?
JWT 在 Java 里不是 Java 独有的东西,而是一种登录认证/身份传递的令牌格式。
JWT 全称是 JSON Web Token,常用于:
用户登录成功后,后端生成一个 token,返回给前端;之后前端每次请求接口时都带上这个 token,后端通过验证 token 判断“你是谁、有没有权限”。
它遵循JSON格式,将用户信息加密到token里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。基于token的身份验证可以替代传统的cookie+session身份验证方法。这使得JWT成为高度分布式网站的热门选择,在这些网站中,用户需要与多个后端服务器无缝交互。
2、JWT识别
在实战中,我们应该怎么识别并发现JWT呢?
JWT由三个部分组成,且前两个部分的开头固定为"eyJ"
标头(Header)。
Header是JWT的第一个部分,是一个JSON对象,主要声明了JWT的签名算法,如"HS256”、"RS256"等,以及其他可选参数,如"kid"、"jku"、"x5u"等。alg字段通常用于表示加密采用的算法。如"HS256"、"RS256"等。typ字段通常用于表示类型还有一些其他可选参数,如"kid"、"jku"、"x5u"等。

有效载荷(Payload)。
Payload是JWT的第二个部分,这是一个JSON对象,主要承载了各种声明并传递明文数据,用于存储用户的信息,如id、用户名、角色、令牌生成时间和其他自定义声明。
iss:该字段表示jwt的签发者。
sub:该jwt面向的用户。
aud:jwt的接收方。
exp:jwt的过期时间,通常来说是一个时间戳。
iat:jwt的签发时间,常来说是一个时间戳。
jti:此jwt的唯一标识。通常用于解决请求中的重放攻击。该字段在大多数地方没有被提及或使用。因为使用此字段就意味着必须要在服务器维护一张jti表, 当客户端携带jwt访问的时候需要在jti表中查找这个唯一标识是否被使用过。使用这种方式防止重放攻击似乎让jwt有点怪怪的感觉, 毕竟jwt所宣称的优点就是无状态访问

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

第一部分:对 JSON 的头部做 base64 编码处理得到
第二部分:对 JSON 类型的 payload 做 base64 编码处理得到
第三部分:分别对头部和载荷做base64编码,并使用.拼接起来
使用头部声明的加密方式,对base64编码前两部分合并的结果加盐加密处理,作为JWT
在线解析:https://jwt.io/。可以在官网进行解析
BURP插件:Hae 或 JSON Web Tokens。也可以用BP的插件来查看

3、JWT绕过
1>空加密算法(攻击头部不使用加密)
签名算法可被修改为none,JWT支持将算法设定为"None"。如果"alg"字段设为"None",那么签名会被置空,这样任何token都是有效的。
2>未校验签名(攻击签名不使用签名认证)
某些服务端并未校验JWT签名,可以尝试修改payload后然后直接请求token或者直接删除signature再次请求查看其是否还有效。
3>暴力破解密钥(攻击签名知道密钥实现重组)
针对是对称加密算法(非对称没有用)
非对称要使用方法:获取源码或者公钥私钥文件
某些签名算法,例如HS256(HMAC+SHA-256),会像密码一样使用一个任意的、独立的字符串作为秘密密钥。这个秘钥如被轻易猜到或暴力破解,则攻击者能以任意的头部和载荷值来创建JWT,然后用密钥重新给令牌签名。
4>其他安全参考:(源码泄漏密匙,Kid注入等)
https://blog.csdn.net/weixin_44288604/article/details/128562796
4、JWT利用工具
利用项目:https://github.com/ticarpi/jwt_tool
四、CtfShow345-350
1、Web345
第一关我们可以抓个包看一下,
可以看到这里是使用了jwt验证,并且告诉我们flag在admin目录下。然后我们把jwt的信息解码看一下

可以看到他只有两个部分,没有签名,且加密算法是none。然后我们可以把jwt发送到BP中的Decoder中。然后对他进行解码后,修改sub的值为admin,且将修改后的再进行编码

然后使用新生成的jwt,重新发包。

得到flag
2、Web346
同样我们先抓包,并且解码看一下

可以看到这里是使用了加密算法的,加密算法是HS256,这是一个对称密钥加密。可以尝试使用
这里可以使用工具jwt_tools来修改加密算法以及sub的值。启动jwt_tools

修改加密算法为none

修改sub的值为admin,然后会生成jwt
利用新的JWT发包。出现flag

注意需要删除第三部分签名
3、Web347
这一关给了提示是使用弱口令,先抓个包看一下他的jwt

可以看到他还是使用了HS256的加密算法,这一关可以使用弱口令爆破密钥,同样使用jwt_tools这个工具。

爆破出来了密钥是123456。然后对数据修改后加密,得到新的jwt

发包得到flag

4、Web348
这一关和上一关一样是弱口令爆破
5、Web349
这一关是给了我们源码,通过抓包可以看到,他的加密算法是"RS256",这是一个非对称加密的算法。使用私钥进行签名,公钥进行验证,所以,如果我们需要修改sub的值,修改后,让服务器还能识别,就需要得到私钥。
其中给了我们私钥地址

下载下来。可以编写一个简单的python脚本来进行修改与加密
import jwt
private=open('private.key','r').read();
payload={"user":"admin"};
print(jwt.encode(payload,key=private,algorithm='RS256'))
然后就可以得到jwt,然后修改数据包,并且改为post请求,因为他源码的验证是要求post

得到flag
6、Web350
这一关给了源码,我们可以先看一下源码,发现他是给了公钥的文件但是没有给私钥的文件。
并且它的验证逻辑是:
if(decoded.user==='admin'){
res.end(flag);
}else{
res.end('you are not admin'+err);
}
所以也需要用户等于admin。这一关仍然使用的是"RS256"加密,但是这一关没有告诉我们私钥。
这一关我们可以把它的加密算法改为"HS256"堆成密钥加密,因为他给了公钥。所以可以写一个简单的加密脚本
var jwt= require('jsonwebtoken');
var fs = require('fs');
var privateKey = fs.readFileSync('./public/public.key');
var token = jwt.sign({ user: 'admin' }, privateKey, { algorithm: 'HS256' });
console.log(token)
得到jwt,改为POST请求,发包

得到flag
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)