对于古老的Struts2 框架的逻辑概述和漏洞分析
字数 1818 2025-08-19 12:41:39
Struts2框架逻辑概述与漏洞分析
1. Struts2框架概述
Struts2是一个基于JavaEE的MVC框架,虽然基于Servlet API,但通过Filter机制实现核心功能。这种设计使Struts2应用更加灵活高效。
1.1 基本配置
web.xml配置示例:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
struts.xml配置示例:
<struts>
<constant name="struts.devMode" value="true" />
<package name="myapp" extends="struts-default">
<action name="myaction">
<result>/index.jsp</result>
</action>
</package>
</struts>
2. Struts2核心处理逻辑
2.1 请求处理流程
- FilterPipeline处理:使用过滤器链处理每个请求
- StrutsPrepareAndExecuteFilter:第一个过滤器,负责:
- 准备请求参数
- 执行控制器方法
- 处理结果
- 清理请求
2.2 URL获取逻辑
org.apache.struts2.RequestUtils#getUri方法逻辑:
- 尝试获取
javax.servlet.include.servlet_path属性 - 如果为空,使用
getServletPath() - 如果Servlet路径为空,使用
request.getRequestURI() - 移除上下文路径获取相对路径
2.3 请求处理核心方法
handleRequest方法:
- 接收
HttpServletRequest对象 - 根据路径和参数查找对应Action类
- 调用
execute方法执行业务逻辑
executeStaticResourceRequest方法:
public boolean executeStaticResourceRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
StaticContentLoader staticResourceLoader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
if (staticResourceLoader.canHandle(resourcePath)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
return true;
} else {
return false;
}
}
2.4 静态资源处理
uiStaticContentPath:
- 指定UI静态内容路径(默认"WEB-INF/struts-ui-static")
cleanupPath方法处理路径:
protected String cleanupPath(String path) {
if (path.startsWith(uiStaticContentPath)) {
return path.substring(uiStaticContentPath.length());
} else {
return path;
}
}
DefaultStaticContentLoader#findStaticResource:
- 根据请求路径查找静态资源
- 返回包含文件信息的
StaticResource对象
2.5 路径处理关键点
- 二次解码URL:
protected String buildPath(String name, String packagePrefix) throws UnsupportedEncodingException {
String resourcePath;
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
resourcePath = packagePrefix + name.substring(1);
} else {
resourcePath = packagePrefix + name;
}
return URLDecoder.decode(resourcePath, encoding);
}
- pathPrefixes:
org/apache/struts2/static/template/static/
org/apache/struts2/interceptor/debugging/
3. 路由映射机制
3.1 ActionMapping
- 映射HTTP请求到Action类
- 包含信息:
- Action类全限定名
- 请求方法
- 请求路径
3.2 路由查找逻辑
org.apache.struts2.dispatcher.mapper.DefaultActionMapper#getMapping:
- 遍历
PackageConfig配置查找匹配URI - 获取namespace和actionName
- URI中斜杠之前的部分不影响路由结果
示例:
ActionMapping mapping1 = new ActionMapping("/users", "users", "list");
ActionMapping mapping2 = new ActionMapping("/users/{id}", "users", "show");
ActionMapping mapping3 = new ActionMapping("/users/{id}/edit", "users", "edit");
3.3 命名空间处理
- 默认命名空间是空字符串
- 作为"catch-all"命名空间
- 如果在指定命名空间找不到action配置,会搜索默认命名空间
3.4 ActionProxy
- 代理对象,封装Action类方法
- 提供
execute方法 - 执行流程:
- 查找ActionMapping
- 创建ActionProxy
- 调用拦截器
- 执行Action方法
- 返回ActionResult
3.5 serviceAction方法
org.apache.struts2.dispatcher.Dispatcher#serviceAction:
- 查找ActionMapping
- 通过ActionProxy执行Action
- 处理异常并返回ActionResult
4. 拦截器机制
4.1 Interceptors
- 每个Action类对应一个ActionInterceptor列表
- 在执行Action前后调用拦截器
- 可对请求和响应进行处理:
- 添加请求头
- 修改请求参数
- 拦截请求执行
4.2 setParameters方法
- 将请求参数绑定到Action类的POJO对象
- 使用OGNL引擎实现参数绑定
- 通过getter/setter方法完成绑定
5. 漏洞分析(CVE-2023-22518)
5.1 漏洞原理
namespaceActionConfigs哈希表包含:- 当前package定义的action
- 通过
extends继承的父package中的action
- 路由可能指向非预期URL
5.2 配置示例
<package name="default"></pacakge>
<package name="setup" extends="default" namespace="/setup">
<action name="setup-restore" class="com.atlassian.confluence.importexport.actions.SetupRestoreAction">
</action>
</package>
<package name="admin" extends="setup" namespace="/admin">
<action name="console" class="com.atlassian.confluence.admin.actions.AdministrationConsoleAction" method="doDefault">
</action>
</pacakge>
<package name="json" extends="admin" namespace="/json"></pacakge>
- 请求
/json/console会直接指向/admin/console
5.3 补丁分析
@Deprecated
@WebSudoRequired
@SystemAdminOnly
public class SetupRestoreAction extends RestoreAction {
// 添加了权限注解
}
6. 安全建议
- 及时更新Struts2版本
- 限制静态资源访问
- 谨慎配置package继承关系
- 对敏感操作添加权限控制
- 避免使用开发模式(struts.devMode)生产环境