Apache Struts2远程代码执行漏洞(S2-001)复现
0X00 漏洞简介
此漏洞源于 Struts 2 框架中的一个标签处理功能:altSyntax。在开启时,支持对标签中的 OGNL 表达式进行解析并执行。Struts 2允许用户提交包含 OGNL 表达式字符串的表单数据,若表单验证失败,则服务器会将用户之前提交的OGNL 表达式(如:%{1+1}) 进行解析执行,然后将结果重新填充到对应的表单数据中。但OGNL 解析代码实际上是在 XWork 中,struts2标签解析主要依赖于 xwork2,所以该漏洞可以理解为 xwork2 的漏洞。
安全公告:https://cwiki.apache.org/confluence/display/WW/S2-001
影响范围:
-
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)——存储在页面,请求,会话和应用程序作用域中的属性
下面是一些OGNL在引入了struts标签的jsp页面中的用法:
<%--注,在jsp页面中要引入struts标签库,如下: --%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>TEST</title>
</head>
<body>
<%--注:ActionContext中的对象使用#号引用 --%>
登录成功,你的姓名为:<s:property value="#name"/>
<%--注:Action对象在值栈中总是可用的,因此如果一个Action对象有username和password属性,就可以随时使用这两个属性。如下: --%>
登录成功,你的用户名为:<s:property value="username"/>
</body>
</html>
若在会话中有一个名为“role”的属性,就可以按如下方式检索:
<s:property value="#session.role"/>
OGNL还支持处理集合即Map,List和Set。例如,要显示城市的下拉列表,可以使用如下代码:
<s:select name="city" list="{'Shanghai','Chengdu','Beijing','Wuhan'}" />
除了#,% 在 OGNL 表达式中也经常出现,它提供一个OGNL表达式运行环境。如下:
// 计算1+1
%{1+1}
// 获取user对象的username属性值
%{#user.username}
OGNL 表达式还支持类静态的方法调用和值访问,表达式的格式:@[类全名(包括路径名)]@[方法名|值名],例如:
// 调用java.lang.String的format方法,拼接字符串,结果为:成都Chengdu
@java.lang.String@format('成都%s','Chengdu')
0X02 漏洞分析
漏洞环境
此处用于分析调试的漏洞环境为:tomcat 9.0.22 + Struts 2.0.8 ,使用IDEA创建一个简单的 Struts 2 项目,有两个jsp页面,一个登录页面(index.jsp),登录成功后的欢迎页面(welcome.jsp)。编写用于处理登录逻辑的Action——LoginAction.java,登录成功则跳转到欢迎界面,否则返回登录页面。
Struts 2.0.8 下载地址:http://archive.apache.org/dist/struts/binaries/struts-2.0.8-all.zip
jsp页面关键代码如下,使用 struts 标签在 jsp 页面中构建表单,在欢迎页面显示登录成功的提示语句。
index.jsp
...
<s:form action="login">
<s:textfield name="username" label="username" />
<s:textfield name="password" label="password" />
<s:submit></s:submit>
</s:form>
...
welcome.jsp
...
登录成功 , <s:property value="username"&

文章详细介绍了ApacheStruts2的S2-001远程代码执行漏洞,包括漏洞产生的原因、受影响的版本范围、漏洞的工作原理和复现步骤。通过示例展示了OGNL表达式的使用,并提供了漏洞复现的环境配置和利用POC。最后,给出了修复该漏洞的建议,即升级Struts或XWork版本。

1828

被折叠的 条评论
为什么被折叠?



