第69天:漏洞利用-Java安全&JWT攻防&Swagger自动化&算法&签名&密钥&Druid泄漏

image-20250825063825203

Java安全-Druid监控-未授权访问&信息泄漏

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

黑盒发现

参考:https://cloud.tencent.com/developer/article/1771986

攻击点:直接拼接URL路径,尝试能否直接未授权访问系统功能点。结合泄露URL路径和Session信息,利用BurpSuite进行尝试登录。利用Cookie编辑器替换Session,再次访问后台路径尝试进入后台

image-20250825080147539

白盒发现

在项目源码配置文件中搜索druid关键字

image-20250825080207981

image-20250825080218825

Java安全-Swagger接口-导入&联动批量测试

Swagger是一个用于生成、描述和调用RESTful接口的Web服务。就是将项目中所有(想要暴露的)接口展现在页面上,并可以进行接口调用和测试的服务。所以可以对这个接口进行漏洞测试,看是否存在未授权访问、sql注入、文件上传等漏洞。由于接口太多,一个个接口测试的话太费时间,所以一般会采用自动化接口漏洞安全测试。

自动化发包测试,Postman

自动化漏洞测试,联动BurpSuite Xray等

黑盒发现

image-20250825080416823

image-20250825080258245

白盒发现

image-20250825080321996

postman && burp && xray 联动

postman设置代理为burp,burp设置上游代理为xray

image-20250825080843781

如果postman提示没有环境:

image-20250825093930619

image-20250825080922479

image-20250825080936249

image-20250825093842440

这里要有漏洞才会有这个提示信息。

JWT

image-20250825094004443

解析JWT数据

JWT在线解析:https://jwt.io/

burp插件

image-20250825093435053

我这个burp装不上,就不折腾了

JWT 安全

空加密算法(攻击头部不使用加密)

  • 签名算法可被修改为 none,JWT 支持将算法设定为 “None”。如果 “alg” 字段设为 “None”,那么签名会被置空,这样任何 token 都是有效的。

未校验签名(攻击签名不使用签名认证)

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

暴力破解密钥(攻击签名知道密钥实现重组)

  • 针对是对称加密算法(非对称没有用)
  • 非对称要使用方法:获取源码或者公钥私钥文件
  • 某些签名算法,例如 HS256(HMAC+SHA-256),会像密码一样使用一个任意的、独立的字符串作为秘密密钥。这个秘钥如被轻易猜到或暴力破解,则攻击者能以任意的头部和载荷值来创建 JWT,然后用密钥重新给令牌签名。

其他安全参考:(源码泄漏密匙,Kid 注入等)

https://blog.csdn.net/weixin_44288604/article/details/128562796

JWT 利用

利用项目 github 地址:https://github.com/ticarpi/jwt_tool

使用方式:

  • 使用 None 算法

    1
    python3 jwt_tool.py JWT_HERE -X a
  • 自定义修改生成

    1
    python3 jwt_tool.py JWT_HERE -T
  • 使用字典破解

    1
    python3 jwt_tool.py JWT_HERE -C -d dictionary.txt
  • 指定密码测试

    1
    python3 jwt_tool.py JWT_HERE -C -p password_here

webshow靶场演示

没 ctfshow 账号,所以只能看看了

  • Web345 (None 无签名认证)

    • 在官网无法重组,但因为算法是 none,所以可以直接 base64 解密之后把用户改为提示的 admin 并且访问 /admin/ 即可获取 flag
    • 或者若 bp 中的 JWT 插件可用,直接在插件中修改即可
  • Web346 (None 算法绕过签名)

    • 官网不支持修改,一改就啥也没了
    • bp 插件可以解析,使用 bp 插件或者 jwt_tool 工具进行修改
      • 将 alg 字段算法置空,即设置为 None,然后将 sub 字段设置为 admin
      • 将 JWT 第三部分签名删掉,即第二个。后的内容
    • 修改完成后访问路径 /admin/ 即可获取 flag
  • Web347 (弱口令密钥获取)

    • 使用上一关的方法无法绕过
    • 使用 jwt_tool 工具爆破密钥,爆破成功后修改密钥为正常值,并修改 sub 为 admin 后访问 /admin/ 路径获取 flag
  • Web348 (爆破密钥上题一样)

  • Web349(公钥私钥泄露)

    • 公钥私钥泄露,分析源码发现公钥私钥文件路径,访问 /private.key/public.key 得到公钥密钥

      服务器私钥生成 jwt,利用公钥解密 jwt,所以使用私钥重新生成一个 user 为 admin 的 JWT 即可

      1
      2
      3
      4
      import jwt
      public = open('private.key', 'r').read()
      payload={"user":"admin"}
      print(jwt.encode(payload, key=public, algorithm='RS256'))
    • python 使用 import jwt 需要安装两个库 jwt 和 PyJWT

    • 将生成的 jwt 使用 post 方式 (分析源码可知) 提交 / 路径获取 flag

  • Web350 (密钥混淆攻击 RS256=>HS256)

    • 将 RS256 算法改为 HS256(非对称密码算法 => 对称密码算法)
    • HS256 算法使用同一个密钥为所有消息进行签名和验证。而 RS256 算法则使用私钥对消息进行签名并使用公钥进行身份验证。
      • 所以这里使用 RS256 的公钥当作 HS256 的密钥进行加密,服务器解密时仍然使用 RS256 的公钥进行身份验证,所以可以通过验证
      • 但是我这里有个疑问,虽然公钥加解密确实是这个逻辑,但是一个解密算法是 HS256,一个解密算法是 RS256,解密结果一样吗?
        • 小迪后面说了,这个解密密钥规定算法,只是使用那个密钥去解密,所以可以换为 HS256
    • 将生成的 jwt 使用 post 方式 (分析源码可知) 提交 / 路径获取 flag

黑盒 JWT 测试

首先找到需要 JWT 鉴权后才能访问的页面,如个人资料页面,将该请求包重放测试:

  1. 未授权访问:删除 Token 后仍然可以正常响应对应页面
  2. 敏感信息泄露:通过 JWt.io 解密出 Payload 后查看其中是否包含敏感信息,如弱加密的密码等
  3. 破解密钥 + 越权访问:通过 JWT.io 解密出 Payload 部分内容,通过空加密算法或密钥爆破等方式实现重新签发 Token 并修改 Payload 部分内容,重放请求包,观察响应包是否能够越权查看其他用户资料
  4. 检查 Token 时效性:解密查看 payload 中是否有 exp 字段键值对(Token 过期时间),等待过期时间后再次使用该 Token 发送请求,若正常响应则存在 Token 不过期
  5. 通过页面回显进行探测:如修改 Payload 中键值对后页面报错信息是否存在注入,payload 中 kid 字段的目录遍历问题与 sql 注入问题

BURP官方靶场

未验证签名

image-20250830215928595

首先使用提示的账号密码进行登陆,登陆成功之后,有一个邮箱登陆的口子,更新邮箱,然后对其抓包:

image-20250830222914202

image-20250830222805063

image-20250830223910826

然后将其带到解码模块没有问题,就重新放到jwt中

image-20250830223929953

然后在直接替换session值,访问admin路径即可。

image-20250830223823398

image-20250830224021216

空加密算法

1
2
3
4
5
6
jwt结构:
xxx.xxx.xxx

如果是空加密算法:
xxx.xxx.
不用加上签名部分

image-20250830230254820

需要将认证部分手动改成none:

image-20250830230359534

image-20250830230333832

然后还是同样F12去替换session:

image-20250830230423752

爆破密钥

1
python jwt_tool.py eyJraWQiOiI1YjMxMzViNS0zMmJmLTQ1ZDAtYmZhZS0yMzZlNTdjZWU5OWUiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJwb3J0c3dpZ2dlciIsImV4cCI6MTc1NjU3MDIzMywic3ViIjoid2llbmVyIn0.gNwxXWc7jWM_jrU55MnvFo5r0eIpn0QnZ1PkbtWMzCU -C -d dict.txt

image-20250830231545579