Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
SC3010-Computer-Security — 使用Struts2和PowerShell重现CVE-2017-5638 OGNL注入漏洞。 | Kitploit
工具/GitHubGitHub/aipeacs/sc3010-computer-security
静态分析漏洞分析代码分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育Payload 开发实验室与实践Archived
GitHubaipeacs/sc3010-computer-security

SC3010-Computer-Security

使用Struts2和PowerShell重现CVE-2017-5638 OGNL注入漏洞。

54个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
查看仓库
分享

SC3010-计算机安全 —— CVE-2017-5638 攻击复现

此仓库是 SC3010 计算机安全课程项目 的一部分。
它复现了 CVE-2017-5638,这是 Apache Struts 2(版本 2.3.5–2.3.31 和 2.5–2.5.10)中的一个严重远程代码执行漏洞,因 2017 年 Equifax 数据泄露事件而广为人知,该事件导致约 1.47 亿人的个人信息被窃取。

该漏洞源于一个单一的设计缺陷:当 Apache Struts 无法解析 multipart/form-data 上传请求时,它会构建一条错误消息,将原始的 Content-Type 标头(未经任何清理)嵌入到一个字符串中,然后该字符串会通过 OGNL 表达式计算器进行处理。攻击者若将 OGNL 表达式放入 Content-Type 标头中,则可在服务器端以 Tomcat 进程用户的身份执行该表达式。

此仓库包含:

  • 一个可运行的存在漏洞的 Java/Maven 服务器(Struts2 2.3.28),带有一个文件上传端点。
  • 一个 PowerShell 攻击脚本,演示了从注入到 RCE 的完整攻击链。
  • 来自 Apache Struts 2.3.28 的带注释的参考源代码文件,标注了调用链的每个步骤。

背景知识

  • OGNL 注入是如何工作的?

仓库结构

root@kitploit:~
SC3010-Computer-Security/
├── simulation/
│   ├── backend/          # 存在漏洞的 Apache Struts2 2.3.28 服务器(Java/Maven)
│   └── attack-script/    # CVE-2017-5638 漏洞攻击脚本
│       └── exploit_cve_2017_5638.ps1   # PowerShell(跨平台)
├── struts-src-code/          # Apache Struts2 参考源码 + 法律声明
│   ├── licenses/             # LICENSE、NOTICE 以及组件许可证
│   └── src/
│       ├── struts2-core/     # 请求处理管线类 + 存在漏洞的 JakartaMultiPartRequest
│       ├── xwork2/           # ActionContext.java、OgnlUtil.java
│       └── ognl/             # OgnlContext.java
├── diagrams/                 # 状态机 + 顺序图,带注释的 OGNL 攻击载荷
└── _notes/                   # 背景阅读材料

攻击模拟

  • 设置与使用说明请参见 simulation/README.md。

攻击状态机图

下图显示了 Struts2 请求管线中的每个决策分支。红色路径是攻击者强制采取的路径;灰色 → ... 分支是安全路径,在攻击中不会触发。

root@kitploit:~
flowchart TD
    Start([攻击者发送 HTTP POST /upload.action<br/>Content-Type: &#37;&#123;OGNL_PAYLOAD&#125;.multipart/form-data])
    Start --> PIPE

    PIPE["<b>Struts2 过滤器 → 包装 → 解析管线</b><br/>doFilter() → PrepareOperations.wrapRequest()<br/>→ Dispatcher.wrapRequest() → new MultiPartRequestWrapper()"]
    PIPE --> D_CT{"Content-Type 是否包含<br/>&quot;multipart/form-data&quot;?"}
    D_CT -- "否 → 普通请求 ..." --> OUT_NORM([非上传路径 ...])
    D_CT -- "是(攻击者在载荷后附加<br/>.multipart/form-data)" --> PARSE

    PARSE[/"<b>JakartaMultiPartRequest.parse()</b><br/>→ Commons FileUpload.parseRequest()"/]
    PARSE --> D_VALID{"FileUpload 能否解析<br/>Content-Type?"}
    D_VALID -- "能 → 正常文件上传 ..." --> OUT_OK([文件被提取、动作执行 ...])
    D_VALID -- "不能 — Content-Type 格式错误<br/>抛出 InvalidContentTypeException<br/>(消息 = 原始 Content-Type 字符串)" --> CATCH

    CATCH["parse() 的 catch 块<br/>调用 buildErrorMessage(e, &#123;&#125;)"]
    CATCH --> FIND

    FIND[/"<b>buildErrorMessage()</b><br/>→ LocalizedTextUtil.findText(class, errorKey, locale, e.getMessage(), args)"/]
    FIND --> D_KEY{"资源包是否有键<br/>struts.messages.upload.error.*?"}
    D_KEY -- "有 → 安全的本地化消息 ..." --> OUT_SAFE([安全地显示错误 ...])
    D_KEY -- "无 — 回退到<br/>e.getMessage() 作为默认值<br/>(攻击者的原始 Content-Type)" --> TRANSLATE

    TRANSLATE["TextParseUtil.translateVariables()<br/>扫描字符串中的 &#37;&#123;...&#125; 表达式"]
    TRANSLATE --> D_OGNL{"字符串是否包含<br/>&#37;&#123;...&#125; OGNL 表达式?"}
    D_OGNL -- "否 → 普通错误字符串 ..." --> OUT_PLAIN([安全错误消息 ...])
    D_OGNL -- "是 — 计算 OGNL<br/>在攻击者内容内部" --> SANDBOX

    SANDBOX[/"<b>OGNL 沙箱绕过</b><br/>#ognlUtil.getExcludedClasses().clear()<br/>#ognlUtil.getExcludedPackageNames().clear()"/]
    SANDBOX --> ACCESS

    ACCESS[/"<b>无限制反射</b><br/>#context.setMemberAccess(DEFAULT_MEMBER_ACCESS)"/]
    ACCESS --> RCE

    RCE[/"<b>RCE</b><br/>Runtime.getRuntime().exec(cmd)"/]
    RCE --> Done([命令以 Tomcat 进程用户身份执行])

    style Start fill:#d32f2f,color:#fff
    style Done fill:#d32f2f,color:#fff
    style OUT_NORM fill:#9e9e9e,color:#fff
    style OUT_OK fill:#9e9e9e,color:#fff
    style OUT_SAFE fill:#9e9e9e,color:#fff
    style OUT_PLAIN fill:#9e9e9e,color:#fff
    style SANDBOX fill:#b71c1c,color:#fff
    style ACCESS fill:#b71c1c,color:#fff
    style RCE fill:#b71c1c,color:#fff
    style CATCH fill:#e65100,color:#fff
    style TRANSLATE fill:#e65100,color:#fff

关于带有分支说明的完整状态机,请参见 diagrams/cve-2017-5638-state-machine.md。
关于顺序图视图和带注释的 OGNL 攻击载荷详解,请参见 diagrams/cve-2017-5638-attack-chain.md。


第三方软件声明

本仓库出于学术安全研究目的复制了 Apache Struts 2.3.28 的部分源代码。

Apache Struts 版权所有 © 2000–2016 The Apache Software Foundation。
根据 Apache 许可证 2.0 版 授权。
许可证副本请参见 struts-src-code/licenses/LICENSE.txt。
Apache 许可证要求的完整署名声明请参见 struts-src-code/licenses/NOTICE.txt。

Apache Struts 2 捆绑了其他第三方组件,每个组件受其各自许可证约束:

组件许可证文件
OGNL(对象图导航库)

来源参考:

  • apache/struts @ STRUTS_2_3_28 — Struts2 核心和 XWork
  • jkuhnert/ognl — OGNL 3.0.x
  • Gemini — 关于一般 OGNL 语言的咨询。
下载工具
struts-src-code/licenses/OGNL-LICENSE.txt
XWorkstruts-src-code/licenses/XWORK-LICENSE.txt
FreeMarkerstruts-src-code/licenses/FREEMARKER-LICENSE.txt