Apache Shiro反序列化识别那些事

1.1 关于Apache Shiro
Apache shiro是一个Java安全框架,提供了认证、授权、加密和会话管理功能,为解决应⽤安全提供了相应的API:

认证-⽤用户身份识别,常被称为用户”登录”
授权-访问控制
密码加密-保护或隐藏数据防止被偷窥
会话管理-用户相关的时间敏感的状态

1.2 Shiro反序列化
1.2.1 反序列化漏洞

Shiro550:
shiro≤1.2.4版本,默认使⽤了CookieRememberMeManager,由于AES使用的key泄露,导致反序列化的cookie可控,从而引发反序列化攻击。(理论上只要AES加密钥泄露,都会导致反序列化漏洞)

1.2.2 Shiro识别

要想识别Apache Shiro反序列列化漏洞,首先应该判断相关的Web站点是否使⽤了shiro框架。主要有以下⽅式:

  • rememberMe

可以在 cookie 追加一个 rememberMe=xx 的字段,这个字段是rememberMeManager默认的,然后看响应头部可以看看是否有 Set-Cookie: rememberMe=deleteMe; 的字段则可判断使⽤了shiro框架:

Apache Shiro反序列化识别那些事_第1张图片

  • 自定义的 rememberMe字段

前⾯通过在Cookie追加rememberMe字段进⾏判断,实际上这个默认字段的命名是可以修改的,Shiro支持在rememberMe管理器中自定义名称,可以通过在配置⽂件进⾏配置,例如下⾯的例子,将rememberMe设置成了了rememberMeTK: 






同理,在springboot集成Shiro时也可以通过在shiro配置类中添加rememberMeManager的配置,修改默认命名为rememberMeTK:

public SimpleCookie rememberMeCookie(){
//cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMeTK");
//cookie生效时间30天,单位秒;
simpleCookie.setMaxAge(2592000);
return simpleCookie;
}

然后在securityManager中注册: 

securityManager.setRememberMeManager(rememberMeManager());

通过上述方式配置后,在cookie中添加rememberMe就不会有deleteMe返回了:

Apache Shiro反序列化识别那些事_第2张图片

当使⽤我们设置的rememberMeTK字段尝试探测时,响应中成功返回熟悉的deleteMe:

Apache Shiro反序列化识别那些事_第3张图片

这种方式从一定程度上增加了探测识别shiro框架的难度,但是如果可以正常登录的话,是可以得到相关的值的,
因为这个rememberMe本身是Shiro 提供了记住我(RememberMe)的功能,比如访问如淘宝等⼀一些⽹站时,关闭了浏览 器下次再打开时还是能记住你是谁,下次访问时⽆需再登录即可访问。
基本流程是先在登录页面选中 RememberMe 然后登录成功;如果是浏览器登录一般会把 相关 的Cookie字段,也就是我们探测的关键字段(例例如rememberMeTK)写到客户端并保存下来。那么此时只要去浏览器本地查看即可。

可以通过burp插件的⽅方式,在每一个请求发起时自动在cookie中追加探测字段(例如rememberMe=tkswifty),如果响应中包含=deleteMe则直接⾼亮显示,那么就可以很便捷的发现使⽤了shiro的站点,进一步进行漏洞发现利⽤了:

Apache Shiro反序列化识别那些事_第4张图片

  • 相关cms

一些cms本身就是基于shiro进⾏开发的,例如jeesite、 jeecg、 ......


1.2.3 关键因素
  整个漏洞简单的cookie处理流程是:得到rememberMe的cookie值-->Base64解码-->AES解密-->反序列化。除了找到相关的参数(默认rememberMe)以外,还需要结合如下因素:

  • key

shiro在1.4.2版本之前, AES的模式为CBC, IV是随机生成的,并且IV并没有真正使用起来。所以整个AES加解密过程的key就很重要了,正是因为AES使用默认的KEY/常见的KEY/KEY泄露导致反序列化的cookie可控,从⽽引发反序列化漏洞。


常见的key如下:

kPH+bIxk5D2deZiIxcaaaA==(1.2.4默认key)
2AvVhdsgUs0FSA3SDFAdag==
4AvVhmFLUs0KTA3Kprsdag==
3AvVhmFLUs0KTA3Kprsdag==
wGiHplamyXlVB11UXWol8g==
Z3VucwAAAAAAAAAAAAAAAA==
6ZmI6I2j5Y+R5aSn5ZOlAA==
ZUdsaGJuSmxibVI2ZHc9PQ==
1QWLxg+NYmxraMoxAXu/Iw==

有时候可能存在未知key的情况,那么可以采取 Shiro-721 的报错逻辑来进⾏遍历key(前提是正常登录得到一个rememberMe的值):


Shiro721:

rememberMe cookie通过AES-128-CBC模式加密,易受到Padding Oracle攻击。可以通过结合有效的rememberMe cookie作为Padding Oracle攻击的前缀,然后精⼼制作rememberMe来进⾏反序列化攻击。


Tip:可以结合JRMP gadget使⽤用,可以⼤大幅减少生成序列化数据的长度,同时在1.4.2版本后,shiro已经更换 AES-CBC AES-CBC AES-GCM AES-GCM ,无法再通过Padding Oracle遍历key。

  • 可用gadget

 利⽤链(gadget chains),俗称gadget。通俗来说就是一种利⽤方法,它是从触发位置开始到执⾏命令的位置结束,也可以说是漏洞验证方法(POC)。shiro反序列化中常⽤的有(遇到过的):

URLDNS
CommonsBeanutils1
CommonsCollections*
JRMPClient
JRMPListener
C3P0
Spring1


1.2.4漏洞识别

  • 基于OOB

可以使用ysoserial-URLDNS-gadget结合dnslog进⾏检测,其不受JDK版本和安全策略影响, 除非存在网络限制DNS不能出网。构造好对应的请求后,若dnslog成功记录到记录,则可以说明漏洞存在。

并且这种方式也是遍历key很不错的方法,通过在dnslog域名前加⼊对应key的randomNum,记录到对应请求时即可直接定位对应的key了: 

Apache Shiro反序列化识别那些事_第5张图片

  • 基于时间延迟

在不出网的情况下,可以结合SQL盲注的思路,可以考虑结合时间延迟进⾏判断和获取数据,可以通过改写ysoserial,执⾏对应的时间延迟代码,例如这里如果系统不是windows类型的话则会进行时间延迟: 

try{
if(!(System.getProperty("os.name").toLowerCase().contains("win"))){
Thread.currentThread().sleep(10000L);
}
} catch(Exception e){}


具体效果

Apache Shiro反序列化识别那些事_第6张图片

  • 基于报错

在不出⽹的情况下,若相关web应⽤未屏蔽报错信息,可以考虑结合触发Java异常进⾏判断和获取数据,可以通过改写ysoserial,执⾏对应的代码进⾏异常抛出,例如下⾯的代码,通过抛出NoClassDefFoundError异常,在异常信息中输出shiro-vul-discover关键字进⾏判断

String result = "shiro-vul-discover";
throw new NoClassDefFoundError(new String(result));

具体效果

Apache Shiro反序列化识别那些事_第7张图片

1.3日志审计
在⽇志信息⾥是可以看到序列化报错的信息的,可以根据相关日志查看相关应⽤是否遭到shiro反序列化攻击尝试


以在Tomcat的报错⽇志 catalina.out 为例,关注RememberMeManager的相关信息可以看到相关的异常:

org.apache.shiro.crypto.CryptoException: Unable to execute 'doFinal' with
cipher instance [javax.crypto.Cipher@19fe76e1].
at
org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:462)
at
org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:445)
at
org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:390)
at
org.apache.shiro.crypto.JcaCipherService.decrypt(JcaCipherService.java:382)
at
org.apache.shiro.mgt.AbstractRememberMeManager.decrypt(AbstractRememberMeMa
nager.java:482)at
org.apache.shiro.mgt.AbstractRememberMeManager.convertBytesToPrincipals(Abs
tractRememberMeManager.java:419)
at
org.apache.shiro.mgt.AbstractRememberMeManager.getRememberedPrincipals(Abst
ractRememberMeManager.java:386)
at
org.apache.shiro.mgt.DefaultSecurityManager.getRememberedIdentity(DefaultSe
curityManager.java:613)
at
org.apache.shiro.mgt.DefaultSecurityManager.resolvePrincipals(DefaultSecuri
tyManager.java:501)
at
org.apache.shiro.mgt.DefaultSecurityManager.createSubject(DefaultSecurityMa
nager.java:347)
at
org.apache.shiro.subject.Subject$Builder.buildSubject(Subject.java:845)
at
org.apache.shiro.web.subject.WebSubject$Builder.buildWebSubject(WebSubject.
java:148)
at
org.apache.shiro.web.servlet.AbstractShiroFilter.createSubject(AbstractShir
oFilter.java:292)
at
org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractS
hiroFilter.java:359)
at
org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFi
lter.java:125)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Applicatio
nFilterChain.java:193)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterC
hain.java:166)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.j
ava:202)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.j
ava:96)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBas
e.java:526)at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:13
9)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92
)
at
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogV
alve.java:678)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav
a:74)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.jav
a:66)
at
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtoc
ol.java:861)
at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.ja
va:1579)
at
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java
:49)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1
149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:
624)
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.j
ava:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.crypto.BadPaddingException: Given final block not properly
padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)at
org.apache.shiro.crypto.JcaCipherService.crypt(JcaCipherService.java:459)
... 33 more
2019-12-14 23:52:15,860 INFO
[org.apache.shiro.session.mgt.AbstractValidatingSessionManager]: Validating
all active sessions...
2019-12-14 23:52:15,889 INFO
[org.apache.shiro.session.mgt.AbstractValidatingSessionManager]: Finished
session validation. No sessions were stopped.
2019-12-14 23:52:20,046 WARN
[org.apache.shiro.mgt.AbstractRememberMeManager]: There was a failure while
trying to retrieve remembered principals. This could be due to a
configuration problem or corrupted principals. This could also be due to a
recently changed encryption key, if you are using a shiro.ini file, this
property would be 'securityManager.rememberMeManager.cipherKey' see:
http://shiro.apache.org/web.html#Web-RememberMeServices. The remembered
identity will be forgotten and not used for this request.
2019-12-14 23:52:20,046 WARN
[org.apache.shiro.mgt.DefaultSecurityManager]: Delegate RememberMeManager
instance of type [org.apache.shiro.web.mgt.CookieRememberMeManager] threw
an exception during getRememberedPrincipals().

合天网安实验室:

CVE-2019-0192 Apache Solr远程反序列化代码执行漏洞

https://www.hetianlab.com/expc.do?ec=ECIDde9d-11f0-4ac2-921f-b04f7e137c75

成为更好的自己

你可能感兴趣的:(Apache Shiro反序列化识别那些事)