对于古老的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 请求处理流程

  1. FilterPipeline处理:使用过滤器链处理每个请求
  2. StrutsPrepareAndExecuteFilter:第一个过滤器,负责:
    • 准备请求参数
    • 执行控制器方法
    • 处理结果
    • 清理请求

2.2 URL获取逻辑

org.apache.struts2.RequestUtils#getUri方法逻辑:

  1. 尝试获取javax.servlet.include.servlet_path属性
  2. 如果为空,使用getServletPath()
  3. 如果Servlet路径为空,使用request.getRequestURI()
  4. 移除上下文路径获取相对路径

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 路径处理关键点

  1. 二次解码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);
}
  1. 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方法
  • 执行流程:
    1. 查找ActionMapping
    2. 创建ActionProxy
    3. 调用拦截器
    4. 执行Action方法
    5. 返回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. 安全建议

  1. 及时更新Struts2版本
  2. 限制静态资源访问
  3. 谨慎配置package继承关系
  4. 对敏感操作添加权限控制
  5. 避免使用开发模式(struts.devMode)生产环境
Struts2框架逻辑概述与漏洞分析 1. Struts2框架概述 Struts2是一个基于JavaEE的MVC框架,虽然基于Servlet API,但通过Filter机制实现核心功能。这种设计使Struts2应用更加灵活高效。 1.1 基本配置 web.xml配置示例 : struts.xml配置示例 : 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方法 : 2.4 静态资源处理 uiStaticContentPath : 指定UI静态内容路径(默认"WEB-INF/struts-ui-static") cleanupPath 方法处理路径: DefaultStaticContentLoader#findStaticResource : 根据请求路径查找静态资源 返回包含文件信息的 StaticResource 对象 2.5 路径处理关键点 二次解码URL : pathPrefixes : 3. 路由映射机制 3.1 ActionMapping 映射HTTP请求到Action类 包含信息: Action类全限定名 请求方法 请求路径 3.2 路由查找逻辑 org.apache.struts2.dispatcher.mapper.DefaultActionMapper#getMapping : 遍历 PackageConfig 配置查找匹配URI 获取namespace和actionName URI中斜杠之前的部分不影响路由结果 示例 : 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 配置示例 请求 /json/console 会直接指向 /admin/console 5.3 补丁分析 6. 安全建议 及时更新Struts2版本 限制静态资源访问 谨慎配置package继承关系 对敏感操作添加权限控制 避免使用开发模式(struts.devMode)生产环境