漏洞复现
Vulhub-漏洞环境搭建
1panel
Bash
Tomcat
Siro框架漏洞
Apache Struts2
Apache 中间件
ThinkPHP框架漏洞
MySQL写入shell
Redis
MySQL提权
Fastjson反序列化漏洞
Spring
Jenkins
WebLogic
-
+
首页
Siro框架漏洞
 ## 概述 Shiro 是一款轻量级的 Java 安全框架,提供了身份认证、授权、加密和会话管理等功能。 Shiro 的目标是简化 Java 安全编程,并提供更好的开发体验。 Shiro 的主要特点如下: - 易于学习和使用:Shiro 设计简单,易于学习和使用。 - 灵活性高:Shiro 可以适用于任何应用场景,支持多种应用程序类型。 - 安全性高:Shiro 的安全性能比较优越,提供了多种方式来保护应用程序的安全性。 - 扩展性好:Shiro 框架提供了可扩展性插件机制,可以方便地扩展框架的功能,满足不同的需求。 - 企业级支持:Shiro 是从 Apache 基金会获得支持的框架,拥有众多企业用户。  Shiro有三大核心组件,即Subject、SecurityManager 和 Realm。 > Subject Subject 代表当前用户,是 Shiro 框架中最重要的组件之一。Subject 封装了用户的所有信息,包括身份(用户名和密码)和角色等。在一个应用程序中,可能有多个 Subject,每个 Subject 可以访问应用程序中的资源。 用户可以通过 Subject 登录应用程序,并执行诸如访问资源、修改个人配置等操作。Shiro 提供了简单易用的方法来管理用户的登录和退出行为,以及 Session 管理等。 > SecurityManager SecurityManager 是 Shiro 的核心组件,负责管理和协调整个应用程序的安全机制。它的主要职责是认证、授权、加密和会话管理等。 SecurityManager 将应用程序中的所有安全操作委托给适当的 Realms 进行处理,并存储和管理有关用户身份、角色和权限等信息。 SecurityManager 还可以配置多个 Realms,以便应用程序可以集成不同的认证和授权方案。 > Realm Realm 是 SecurityManager 中负责处理用户身份认证和授权的组件。Shiro 支持多种不同类型的 Realm,包括 JDBC Realm、LDAP Realm、Active Directory Realm 等。 每个 Realm 负责验证用户的身份,并获取用户的权限信息,以便 SecurityManager 可以根据这些信息进行访问控制和授权。Realm 还可以实现缓存机制,提高系统性能。 ## 特征 > 核心特征:RememberMe Cookie Shiro 的 “记住我”(RememberMe)功能会生成特定格式的 Cookie,这是识别 Shiro 应用的最核心、最直接的特征。 | 特征细节 | 具体表现 | 探测价值 | | ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | Cookie 名称 | 固定为 rememberMe(首字母小写,无空格或特殊字符)。 | 浏览器 F12 查看 Cookie 列表,若存在rememberMe Cookie,大概率是 Shiro 应用。 | | Cookie 值格式 | 1. 未勾选 “rememberMe”:值为deleteMe(登录后未勾选时,Shiro 会设置此值清除旧 Cookie);<br />2. 勾选 “rememberMe”:值为Base64 编码后的序列化数据(长度较长,通常几百到几千字符,如dGltZXN0YW1wOi8vMTIzLjQ1LjY3Ljg5OjE2...)。 | 若存在deleteMe或长 Base64 格式的rememberMe,可 100% 初步判定为 Shiro 应用;<br />Base64 值是 Shiro-550 漏洞探测的关键载体(需解码分析序列化格式)。 | | Cookie 属性 | 通常携带Path=/(作用域为全站)、HttpOnly(防 XSS 窃取)属性,部分配置会加Secure(仅 HTTPS 传输)。 | 结合rememberMe名称 +Path=/+HttpOnly,可进一步确认 Shiro 框架。 | > 响应头特征(未授权 / 认证场景) 当访问 Shiro 保护的资源(未登录或权限不足)时,服务器返回的响应头会带有 Shiro 的权限控制痕迹,是漏洞探测的重要辅助特征。 | 特征类型 | 具体表现 | 探测价值 | | ------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | WWW-Authenticate 头 | 未认证访问受保护资源时,响应头会返回 WWW-Authenticate: Basic realm="Shiro Realm" 或 Bearer realm="Shiro Realm"(取决于 Shiro 的认证策略配置)。 | “Shiro Realm” 关键字直接暴露框架身份,是无rememberMe Cookie 时的核心识别依据。 | | 状态码与跳转 | 1. 未认证时,可能返回 401 Unauthorized(无权限访问);2. 配置了登录页跳转时,返回 302 Found,Location 头指向登录页(如/login.jsp、/auth/login)。 | 401 状态码 +WWW-Authenticate头,可快速定位 Shiro 的权限拦截逻辑;302 跳转的登录页路径可作为后续探测的入口(如测试登录表单的 RememberMe 参数)。 | ## Shiro550(CVE-2016-4437) ### 概述 Shiro550 漏洞(CVE-2016-4437)是 Apache Shiro 框架中一个反序列化远程代码执行漏洞,因漏洞利用与 [Remember Me] 功能的加密密钥相关(默认密钥特征被安全圈简称为 “550”)而得名。 核心原因是 Shiro 1.2.4及以下版本中,“记住我(Remember Me)” 功能的加密密钥为硬编码,且序列化数据的解密与反序列化过程缺乏安全校验: 1. 硬编码密钥:Shiro 对 “Remember Me” 的用户身份信息(序列化数据)采用 AES 加密,但其加密 / 解密密钥(decryptionCipherKey)在源码中是固定值(默认密钥:kPH+bIxk5D2deZiIxcaaaA==,Base64 编码后的 AES 密钥),所有使用默认配置的 Shiro 应用均共用该密钥。 2. 当用户勾选 “记住我” 登录后,Shiro 会将用户身份信息序列化→AES 加密→Base64 编码,最终存储在rememberMe Cookie 中。 3. 后续访问时,Shiro 会读取该 Cookie,经过 Base64 解码→AES 解密→反序列化,恢复用户身份。 若攻击者伪造包含恶意代码的序列化数据,用默认密钥加密后构造RememberMe Cookie,目标服务器解密后反序列化时,会触发恶意代码执行(RCE)。 ### 漏洞版本 Shiro <= 1.2.4 ### 漏洞原理 所实验的版本号是shiro-shiro-root-1.13.0,下载地址:https://github.com/apache/shiro/releases 由于漏洞点是RememberMe处导致的,所以导入项目后直接搜索相关类:  这是一个接口,没有具体的实现。  按住Ctrl + H 可以查看该接口的实现。  优先看下CookieRememberMeManager类,再该类的方法中有一个rememberSerializedIdentity方法。  该方法的主要功能为:将序列化后的值通过base64进行编码,写入到cookie中,再响应给用户侧。 那么作为服务端,肯定有解码并且反序列化读取的过程,该过程发生在getRememberedSerializedIdentity方法中:  进行base解码,返回的内容就是base64解密后的值,解码之后还是一段AES加密后的值,所以要看谁调用了这个函数。  谁调用了这个方法呢?使用Ctrl+H 看下层级关系,上一级是一个抽象类 AbstractRememberMeManager  在该类中,将getRememberedSerializedIdentity方法写成了一个抽象方法。  那么解密的过程发生在: principals = convertBytesToPrincipals(bytes, subjectContext);  跟进这个函数 convertBytesToPrincipals:调用了decrypt()函数  跟进decrypt()函数:该函数的参数是已经加密的AES值(即解码后的Base64值)  跟getDecryptionCipherKey()函数,解密需要的KEY:   根据描述:所使用的解密密钥就是加密的密钥,即对称加密算法。 找一下设置加密的Key相关方法:  再跟cipherKey参数,最终在shiro.ini中,找到cipherKey值。  实现的方法是在CookieRememberMeManagerTest类中:  默认的Key(也被称为硬编码) 是:kPH+bIxk5D2deZiIxcaaaA== ### 漏洞复现 1、启动容器:  2、访问8080端口,使用admin:vulhub进行登录,   直接使用Shiro反序列化利用工具:添入默认密钥和目标地址,直接一键  一键利用工具建议选择GitHub中Star星比较高的! ## Shiro721(CVE-2019-12422) ### 概述 核心是利用AES-CBC 加密模式的 Padding Oracle 攻击,在未知密钥的情况下,伪造或解密 [RememberMe] 功能的 Cookie,最终触发反序列化远程代码执行(RCE)。 ### 漏洞版本 Apache Shiro 1.2.5 ~ 1.4.0 ### 漏洞原理 Shiro550 修复后(1.2.5 及以上版本),官方移除了硬编码密钥,要求用户自定义 AES 密钥,但加密逻辑仍存在缺陷: - 加密模式风险:Shiro 对 “RememberMe” Cookie 的加密仍使用AES-CBC 模式,该模式需要对不足块大小的数据进行 “填充”(Padding,如 PKCS#5/PKCS#7)。若加密数据的填充不符合规则,解密时会抛出 “填充错误” 异常。 - 响应差异泄露:当攻击者发送填充错误的恶意 Cookie 时,Shiro 会返回不同的错误响应(如 HTTP 状态码、响应内容差异) 例如,填充正确但解密失败时返回一种提示,填充错误时返回另一种提示。这种 “响应差异” 被称为 “Padding Oracle”,攻击者可利用该差异逐步破解加密数据或伪造恶意 Cookie。 - 反序列化未修复:即使密钥未知,攻击者通过 Padding Oracle 攻击伪造出合法的加密 Cookie 后,Shiro 仍会对其解密并反序列化,若 Cookie 中包含恶意序列化数据,将触发 RCE。 > 什么是 “ 填充(Padding)” 以 AES 为例,它是一种 “块加密算法”,只能处理固定大小的 “数据块”(AES 的块大小固定为 128 位,即 16 字节)。当待加密的数据长度不是块大小的整数倍时,就需要通过 “填充” 补足,这是块加密的基础操作。 块加密算法(如 AES、DES)的核心是:每次加密 / 解密只能处理固定长度的数据块(AES 为 16 字节)。如果原始数据的长度不是块大小的整数倍(比如 10 字节、20 字节),就需要在数据末尾添加一些 “填充字节”,使总长度刚好是块大小的整数倍。 例如: - 原始数据长度为 10 字节(不足 16 字节),需要填充 6 字节,总长度变为 16 字节(1 个块); - 原始数据长度为 20 字节(1 个块 16 字节 + 剩余 4 字节),需要填充 12 字节,总长度变为 32 字节(2 个块)。 填充不是随意添加字节,而是需要遵循约定的规则(否则解密时无法正确去除填充)。Shiro 中使用的是PKCS#7 填充规则(与 PKCS#5 兼容,适用于块大小≤255 字节的场景),规则如下: - 设块大小为B(AES 中B=16字节),原始数据长度为L; - 需要填充的字节数为P = B - (L % B)(即 “块大小 - 数据长度对块大小的余数”); - 填充的P个字节中,每个字节的值均为P(即填充字节的 “值” 等于填充的 “数量”)。 举例: 原始数据长度 = 10 字节(L=10): - 填充字节数P=16-10=6; - 填充 6 个字节,每个字节的值为0x06(十六进制),最终总长度 = 16 字节。 原始数据长度 = 16 字节(L=16,刚好是 1 个块): - 此时L%B=0,填充字节数P=16; - 填充 16 个字节,每个字节的值为0x10,最终总长度 = 32 字节(2 个块)。 解密时,算法会读取最后一个字节的值P,然后去除末尾P个字节,即可恢复原始数据(这就是填充规则的核心作用:让解密方知道需要去掉多少填充字节)。 > Shiro721 中 “填充错误的响应差异” 如何被利用? 在 Shiro 的 “RememberMe” 功能中,加密的RememberMe Cookie 解密流程如下: 1. 服务器读取 Cookie 值→Base64 解码→AES-CBC 解密(使用用户配置的密钥); 2. 解密后,先检查填充是否符合 PKCS#7 规则: - 若填充错误→抛出BadPaddingException,服务器可能返回特定错误响应(如 HTTP 500 状态码,或包含 “填充错误” 的提示); - 若填充正确→继续反序列化数据,若反序列化失败(如数据不是合法的序列化格式)→返回另一种响应(如 HTTP 200 但认证失败,提示 “无效的 rememberMe 令牌”)。 这种 “填充错误” 和 “填充正确但反序列化失败” 的响应差异(状态码、响应内容、响应时间等),就是 “Padding Oracle”(填充预言机)。 攻击者可利用这种差异,通过以下方式伪造恶意 Cookie: 1. 构造大量不同填充的恶意数据,加密后作为rememberMe Cookie 发送给服务器; 2. 根据服务器的响应差异,判断当前填充是否正确(“是” 或 “否”); 3. 逐步调整填充和数据内容,最终 “猜解” 出能通过填充校验的加密数据(即使不知道密钥); 4. 当伪造的数据包含恶意序列化代码时,服务器解密后反序列化就会触发远程代码执行。 ## 认证绕过漏洞(CVE-2020-1957) ### 概述 Apache Shiro1.5.2之前版本中存在安全漏洞。攻击者可借助特制的请求利用该漏洞绕过身份验证。 Shiro框架通过拦截器功能来对用户访问权限进行控制,如anon, authc等拦截器。 anon为匿名拦截器,不需要登录即可访问;authc为登录拦截器,需要登录才可以访问。 Shiro的URL路径表达式为Ant格式,路径通配符\表示匹配零个或多个字符串,比如:\可以匹配/hello,但是匹配不到/hello/,因为通配符无法匹配路径。 假设/hello接口设置了authc拦截器,访问/hello会进行权限判断,但如果访问的是/hello/,那么将无法正确匹配URL,直接放行,进入到spring拦截器。 spring中的/hello和/hello/形式的URL访问的资源是一样的,从而实现了权限绕过。 ### 漏洞复现 访问admin路径时,状态码为302  访问/xxx 不存在的路径时,状态码404  两个路径组合时,状态码404  当路径为/xxx/..;/admin/时,状态为200  登录成功,认证权限绕过  ## Shiro 1.2.4反序列化漏洞 ### 漏洞描述 在Shiro <= 1.2.4中,反序列化过程中所用到的AES加密的key是硬编码在源码中[密钥是写死在代码中的],当用户勾选RememberMe并登录成功,Shiro会将用户的cookie值序列化,AES加密,接着base64编码后存储在cookie的rememberMe字段中,服务端收到登录请求后,会对rememberMe的cookie值进行base64解码,接着进行AES解密,然后反序列化。由于AES加密是对称式加密(key既能加密数据也能解密数据),所以当攻击者知道了AES key后,就能够构造恶意的rememberMe cookie值从而触发反序列化漏洞。 ``` Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。 ``` ``` rememberMe的流程为 1.序列化用户身份对象.:['java','-jar',fp,gadget,command] 2.对序列化后的数据进行AES加密,密钥为常量.encryptor = AES.new(base64.b64decode(CipherKey), mode, iv) 3.base64编码:base64.b64encode(iv + encryptor.encrypt(file_body)) 4.设置到cookie中:requests.get(target,cookies={'rememberMe': payload.decode()},timeout=10) ``` ``` shiro的解析流程: 1.读取cookie中的rememberMe的值. payload.decode() 2.base64解码. 3.AES解密 4.反序列化 第四点就触发像dnslog发送请求了. ``` **特征判断:**返回包中含有rememberMe=deleteMe字段 **攻击成功的条件:** 1.能够有对外的shiro功能 2.能够猜中框架的key值 > Shiro key的获取方式 **1.结合Dnslog与URLDNS** 在进行漏洞探测的时候,一般会使用ysoserial-URLDNS-gadget结合dnslog进检测,其受JDK版本和相关的安全策略影响, **除非存在网络限制DNS不能出网**。 通过判断dnslog是否收到对应的请求,判断漏洞是否存在。这是获取key比较实用方法,**通过在dnslog域名前加对应key的randomNum,结合对应的dnslog记录,即可获取到应用对应的Shiro key了** **2.利用时间延迟或报错** 结合Dnslog与URLDNS方法有一个前提是DNS能出网。那么在不出网的情况下就需要找一个替代的方案了。结合SQL盲注的思路,可以考虑执行如下代码结合时间延迟进行判断,若系统是linux系统,则睡眠10s ``` try{ if(!(System.getProperty("os.name").toLowerCase().contains("win"))){ Thread.currentThread().sleep(10000L); } } catch(Exception e){} 1 ``` **3.结合CookieRememberMeManaer** **4.利用JRMP协议** **5.依赖shiro自身进行key检测** ### 漏洞复现 1、页面存在remember me,抓包查看是否有rememberMe=deleteMe字段  2、工具利用  命令执行  ## Apache Shiro 认证绕过漏洞 ### 概述 CVE-2020-1957 Apache Shiro1.5.2之前版本中存在安全漏洞。攻击者可借助特制的请求利用该漏洞绕过身份验证。 Shiro框架通过拦截器功能来对用户访问权限进行控制,如anon, authc等拦截器。 anon为匿名拦截器,不需要登录即可访问;authc为登录拦截器,需要登录才可以访问。Shiro的URL路径表达式为Ant格式,路径通配符*表示匹配零个或多个字符串,比如:/*可以匹配/hello,但是匹配不到/hello/,因为*通配符无法匹配路径。 假设/hello接口设置了authc拦截器,访问/hello会进行权限判断,但如果访问的是/hello/,那么将无法正确匹配URL,直接放行,进入到spring拦截器。spring中的/hello和/hello/形式的URL访问的资源是一样的,从而实现了权限绕过。 ### 漏洞复现 访问admin路径时,状态码为302  访问/xxx 不存在的路径时,状态码404  两个路径组合时,状态码404  当路径为/xxx/..;/admin/时,状态为200  登录成功,认证权限绕过 
毛林
2025年11月1日 14:16
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码