0x1 Shiro介绍
Shiro是java中执行验证、授权和会话管理的一个安全框架,广泛用于Java网站的开发中。随着Shiro反序列漏洞(CVE-2016-4437)被披露,直到现在在一些hw、渗透测试中依然被用作打点和入口,接下来随着源码来分析漏洞形成原因。
0x2 漏洞分析
p神的漏洞环境:https://github.com/phith0n/JavaThings/blob/master/shirodemo
Shiro漏洞的形成在于Rememberme的选项,当用户勾选Rememberme选项后,Cookie就会增加一个Rememberme字段,开发者指定此字段的有效时间,在此时间段中便可以不用登录访问其资源。生成字段位置在于org.apache.shiro.mgt.DefaultSecurityManager#login
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info;
try {
info = this.authenticate(token);
} catch (AuthenticationException var7) {
AuthenticationException ae = var7;
try {
this.onFailedLogin(token, ae, subject);
} catch (Exception var6) {
if (log.isInfoEnabled()) {
log.info("onFailedLogin method threw an exception. Logging and propagating original AuthenticationException.", var6);
}
}
throw var7;
}
Subject loggedIn = this.createSubject(token, info, subject);
this.onSuccessfulLogin(token, info, loggedIn);
return loggedIn;
}
这里作用完成用户认证后继续向下
protected void onSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {
this.rememberMeSuccessfulLogin(token, info, subject);
}
跟进入rememberMeSuccessfulLogin
protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {
RememberMeManager rmm = this.getRememberMeManager();
if (rmm != null) {
try {
rmm.onSuccessfulLogin(subject, token, info);
} catch (Exception var7) {
if (log.isWarnEnabled()) {
String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() + "] threw an exception during onSuccessfulLogin. RememberMe services will not be " + "performed for account [" + info + "].";
log.warn(msg, var7);
}
}
} else if (log.isTraceEnabled()) {
log.trace("This " + this.getClass().getName() + " instance does not have a " + "[" + RememberMeManager.class.getName() + "] instance configured. RememberMe services " + "will not be performed for account [" + info + "].");
}
}
这两步进行进行调用到org.apache.shiro.mgt.AbstractRememberMeManager#onSuccessfulLogin方法
public void onSuccessfulLogin(Subject subject, AuthenticationToken token, AuthenticationInfo info) {
this.forgetIdentity(subject);
if (this.isRememberMe(token)) {
this.rememberIdentity(subject, token, info);
} else if (log.isDebugEnabled()) {
log.debug("AuthenticationToken did not indicate RememberMe is requested. RememberMe functionality will not be executed for corresponding account.");
}
}
forgetIdentity的作用是清除上次的cookie里认证值 判断rememberme字段存在后进入rememberIdentity
public void rememberIdentity(Subject subject, AuthenticationToken token, AuthenticationInfo authcInfo) {
PrincipalCollection principals = this.getIdentityToRemember(subject, authcInfo);
this.rememberIdentity(subject, principals);
}
制造了一个PrincipalCollection,继续跟踪,这里将PrincipalCollection转换为了byte数组
protected void rememberIdentity(Subject subject, PrincipalCollection accountPrincipals) {
byte[] bytes = this.convertPrincipalsToBytes(accountPrincipals);
this.rememberSerializedIdentity(subject, bytes);
}
protected byte[] convertPrincipalsToBytes(PrincipalCollection principals) {
byte[] bytes = this.serialize(principals);
if (this.getCipherService() != null) {
bytes = this.encrypt(bytes);
}
这里我们关注encrypt干了什么
protected byte[] encrypt(byte[] serialized) {
byte[] value = serialized;
CipherService cipherService = this.getCipherService();
if (cipherService != null) {
ByteSource byteSource = cipherService.encrypt(serialized, this.getEncryptionCipherKey());
value = byteSource.getBytes();
}
return value;
}
算法为AES,模式为CBC,既然是AES就需要密钥了, getEncryptionCipherKey就得到了默认密钥
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
然后我们大概可以捋一下shiro解析cookie的过程:base64解码再AES解码,最后反序列化。知道这个过程我们就可以自己去构造,将我们的CC4链去进行AES编码再进行base64编码即可执行,实现反序列化攻击。至于为何不能直接使用CC6,p神的文章中指出:如果反序列化流中包含非Java自身的数组,则会出现无法加载类的错误。这就解释了为什么CommonsCollections6无法利用了,因为其中用到了Transformer数组,进而从TiedMapEntry改成了TemplatesImpl对象,绕过去执行命令。
0x3 简单总结
这是一个年代较为久远的漏洞,但仍影响至今,其利用和测试工具也有很多,大佬们对于规避检测和一些长度限制不断的在缩短payload,新的漏洞已经出现,又怎能停滞不前。
参考链接:
http://blog.topsec.com.cn/apache-shiro-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%8E%9F%E7%90%86%E8%AF%A6%E8%A7%A3/ https://xz.aliyun.com/t/8445
原文始发于微信公众号(RainSec):Shiro反序列化初探
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论