目录
4.2 自定义生成AESkey(Apache Shiro使用官方自带的生成AES密钥)
1 漏洞描述
Apache Shiro 是ASF旗下的一款开源软件,它提供了一个强大而灵活的安全框架,提供身份验证、授权、密码学和会话管理。在Apache Shiro部分旧版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中,攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。
2 漏洞特征
远程代码执行
3 修复建议
(1)、升级shiro至最新版本1.7.0并生成新的密钥替换。
(2)、使用官方秘钥生成方法:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()
备注:若在配置里配置了默认密钥,则立即修改,并妥善保管该密钥。
(3)升级shiro到1.2.5及以上,如果shiro的rememberMe功能的AES密钥一旦泄露,就会导致反序列化漏洞。
跟了shiro 1.3.2的代码,看到官方的操作如下:
- 删除代码里的默认密钥
- 默认配置里注释了默认密钥
- 如果不配置密钥,每次会重新随机一个密钥
可以看到并没有对反序列化做安全限制,只是在逻辑上对该漏洞进行了处理。
如果在配置里自己单独配置AES的密钥,并且密钥一旦泄露,那么漏洞依然存在。
4 解决办法
4.1 升级shiro到最新版本
4.2 自定义生成AESkey(Apache Shiro使用官方自带的生成AES密钥)
package com.tengfan.modules.security;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import org.apache.shiro.codec.Base64;
/**
*
* @Title ShiroCustomAESKeyUtil.java
* @Description 自定义生成shiro AESkey(解决:Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437))
* 采用Apache Shiro官方自带的生成AES密钥
* @Author wy
* @Date 2020年11月17日 上午10:06:45
*/
public class ShiroCustomAESKeyUtil {
/**
* 生成密钥
*
* @return
* @throws Exception
*/
public static String getKey() throws Exception {
KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecretKey deskey = keygen.generateKey();
String key = Base64.encodeToString(deskey.getEncoded());
return key;
}
public static void main(String[] args) throws Exception {
System.out.println(getKey());
}
}
1).shiro采用xml方式配置(spring+springMVC+xx)
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 指定Shiro验证用户登录的类为自定义的Realm(若有多个Realm,可用[realms]属性代替) -->
<property name="realm" ref="systemAuthorizingRealm" />
<property name="sessionManager" ref="sessionManager" />
<property name="cacheManager" ref="shiroCacheManager" />
<!--注入rememberMe cookie管理器-->
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!--注入自定义cookie(主要是设置寿命, 默认的一年太长) -->
<property name="cookie" ref="rememberMeCookie" />
<!-- 避免Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437) -->
<!-- 密钥 WVYw571OG4BehqT7I6J3mA== 调用ShiroCustomAESKeyUtil.getKey()生成 -->
<property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('WVYw571OG4BehqT7I6J3mA==')}"/>
</bean>
<!--手动指定cookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<constructor-arg value="rememberMe" />
<property name="httpOnly" value="true" />
<property name="maxAge" value="604800" /><!-- 7天 -->
</bean>
2).springBoot项目
在shiro配置类中添加以下代码
/**
* 安全管理器
*/
@Bean
public SecurityManager securityManager(UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(userRealm);
// 记住我
securityManager.setRememberMeManager(rememberMeManager());
// 注入缓存管理器;
securityManager.setCacheManager(getEhCacheManager());
// session管理器
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* 记住我
*/
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
cookieRememberMeManager.setCipherKey(Base64.decode(cipherKey));
return cookieRememberMeManager;
}
/**
* cookie 属性设置
*/
public SimpleCookie rememberMeCookie() {
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setDomain(domain);
cookie.setPath(path);
cookie.setHttpOnly(httpOnly);
cookie.setMaxAge(maxAge * 24 * 60 * 60);
return cookie;
}
5 参考网址
https://www.jianshu.com/p/5b99c0ef6fb7
https://www.cnblogs.com/fengwenzhee/p/7121175.html