Struts 2 漏洞(下)

一、简述

除了核心的 OGNL 注入和文件上传漏洞,Struts 2 框架的常见漏洞还集中在重定向 / 转发注入、类型转换漏洞、拦截器配置缺陷、依赖组件漏洞、XML 配置注入等方面,这些漏洞虽未必都是 RCE 级高危,但易被组合利用,也是攻防重点。


二、重定向 / 转发注入漏洞(Open Redirect)

核心原理

Struts 2 的redirect/redirectAction结果类型,或手动拼接response.sendRedirect()时,若直接使用未过滤的用户输入作为跳转 URL,会导致开放重定向攻击

典型场景
  • Action 中接收redirectUrl参数,直接用于重定向:

    java 复制代码
    // 危险代码
    public String execute() {
        String redirectUrl = ServletActionContext.getRequest().getParameter("redirectUrl");
        return "redirect:" + redirectUrl; // 用户可传入恶意URL
    }
  • struts.xml中配置redirectAction时使用动态参数:

    XML 复制代码
    <!-- 危险配置 -->
    <result name="redirect" type="redirect">${redirectUrl}</result>

危害

  • 钓鱼攻击:诱导用户跳转到仿冒网站(如https://your-site.com/redirect?redirectUrl=http://fake-bank.com);
  • 配合 CSRF:绕过浏览器同源策略,窃取用户 Cookie/Token。
修复方案
  1. 白名单校验 (最安全):仅允许跳转到预定义的合法域名 / 路径:

    java 复制代码
    // 安全示例
    private static final Set<String> ALLOWED_REDIRECT_DOMAINS = Set.of("your-site.com", "api.your-site.com");
    
    public String execute() {
        String redirectUrl = getRedirectUrl();
        URL url = new URL(redirectUrl);
        if (!ALLOWED_REDIRECT_DOMAINS.contains(url.getHost())) {
            return "error"; // 非法跳转,返回错误页
        }
        return "redirect:" + redirectUrl;
    }
  2. 禁用动态拼接 :在struts.xml中使用固定 URL,避免 OGNL 表达式:

    XML 复制代码
    <!-- 安全配置 -->
    <result name="redirect" type="redirect">/home.action</result>

三、类型转换漏洞

核心原理

Struts 2 的OGNL 类型转换器(Type Converter)在处理用户输入(如字符串转对象、数组)时,若输入格式异常,可能触发:

  • 拒绝服务(DoS):构造特殊输入导致 OOM / 死循环;
  • 信息泄露:类型转换异常时,返回详细的栈跟踪信息(包含类路径、数据库配置);
  • 绕过校验:利用类型转换规则绕过参数校验(如字符串转布尔值时,"false"被转为true)。

典型 CVE:CVE-2020-17530

  • 影响版本:2.5.0-2.5.29
  • 原理:OGNL 类型转换时处理null值不当,导致 DoS 攻击。
修复方案
  1. 升级至 2.5.30 + 版本;

  2. 自定义类型转换器,增加异常捕获和输入校验:

    java 复制代码
    public class SafeStringToBooleanConverter extends DefaultTypeConverter {
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (value == null) {
                return false; // 统一处理null值
            }
            try {
                return super.convertValue(context, value, toType);
            } catch (Exception e) {
                // 屏蔽异常详情,返回默认值
                return false;
            }
        }
    }
  3. 关闭生产环境的异常栈跟踪:

    XML 复制代码
    <!-- struts.xml -->
    <constant name="struts.devMode" value="false" />
    <constant name="struts.exception.logEnabled" value="true" />
    <constant name="struts.exception.wrapWithActionError" value="true" />

四、拦截器配置缺陷

1. 拦截器未生效 / 绕过

原理
  • Action 未继承struts-default包,导致默认安全拦截器(如paramsvalidation)未加载;
  • 自定义拦截器栈时,遗漏核心安全拦截器;
  • 通过!*等特殊字符绕过拦截器匹配规则。
典型场景
XML 复制代码
<!-- 危险配置:自定义包未继承struts-default,拦截器全部失效 -->
<package name="custom" namespace="/" abstract="true">
    <interceptors>
        <interceptor-stack name="myStack">
            <!-- 遗漏params、validation等安全拦截器 -->
            <interceptor-ref name="logger"/>
        </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="myStack"/>
</package>
修复方案
  • 所有自定义包必须extends="struts-default"

  • 自定义拦截器栈需包含defaultStack(核心安全拦截器):

    XML 复制代码
    <interceptor-stack name="mySecureStack">
        <interceptor-ref name="defaultStack"/> <!-- 包含params、validation、fileUpload等 -->
        <interceptor-ref name="logger"/> <!-- 自定义拦截器后置 -->
    </interceptor-stack>

2. 权限拦截器(RolesInterceptor)绕过

原理

RolesInterceptor仅校验角色名称是否匹配,但未校验角色是否真实存在,或可通过参数篡改绕过:

  • 传入roles=*通配符;
  • 构造空角色参数,触发拦截器逻辑漏洞。
修复方案
  • 禁用RolesInterceptor的通配符匹配;

  • 结合 Spring Security/Shiro 做二次权限校验,不依赖 Struts 内置拦截器;

  • 硬编码允许的角色列表,禁止动态传入: xml

    复制代码
    <interceptor-ref name="roles">
        <param name="allowedRoles">ADMIN,OPERATOR</param> <!-- 固定角色,不使用${} -->
    </interceptor-ref>

五、依赖组件漏洞

Struts 2 的核心功能依赖第三方组件,这些组件的漏洞会直接传导到 Struts 应用,是易被忽视的 "间接漏洞":

1. XWork 组件漏洞

XWork 是 Struts 2 的核心依赖,旧版本存在:

  • OGNL 解析逻辑漏洞(如 CVE-2021-31805);
  • 序列化 / 反序列化漏洞(CVE-2022-41852)。

2. Freemarker/Velocity 模板注入

Struts 2 整合 Freemarker/Velocity 时,若模板中直接使用${}渲染用户输入(而非 Struts 标签),会导致模板注入:

html 复制代码
<!-- 危险的Freemarker模板 -->
<div>${param.username}</div> <!-- 直接渲染用户输入,可注入Freemarker表达式 -->
<!-- 安全写法 -->
<div><s:property value="username" escapeHtml="true"/></s:property></div>

3. Commons FileUpload 漏洞

Struts 2 默认使用commons-fileupload处理文件上传,该组件旧版本(<1.4)存在:

  • 路径遍历(CVE-2018-11771);
  • 内存溢出(DoS)漏洞。
修复方案
  • 同步升级 Struts 依赖的所有组件:

    XML 复制代码
    <!-- pom.xml 强制升级核心依赖 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.5</version> <!-- 最新稳定版 -->
    </dependency>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.33</version>
    </dependency>
  • 模板渲染必须使用 Struts 标签(s:property),并开启escapeHtml="true"

六、XML 配置注入(Struts 配置文件漏洞)

核心原理

若 Struts 的struts.xml/struts-config.xml支持动态加载(如从数据库 / 外部文件读取配置),攻击者可注入恶意 XML 节点:

  • 新增恶意 Action,执行任意代码;
  • 修改拦截器配置,禁用安全拦截器;
  • 注入redirect节点,实现开放重定向。
典型场景
  • 应用允许上传struts.xml配置文件;
  • 通过 JNDI 加载远程恶意struts.xml
修复方案
  1. 禁止动态加载外部struts.xml

    XML 复制代码
    <!-- struts.xml 禁用动态配置加载 -->
    <constant name="struts.configuration.files" value="struts-default.xml,struts.xml" />
    <constant name="struts.configuration.reload" value="false" /> <!-- 生产环境禁用配置热加载 -->
  2. struts.xml放在WEB-INF目录下(禁止外部访问);

  3. 校验配置文件的 MD5 / 签名,防止被篡改。


总结

  1. Struts 2 的非核心漏洞中,重定向注入、拦截器配置缺陷、依赖组件漏洞是实际攻防中最常出现的,需重点关注配置层面的加固;
  2. 类型转换漏洞和 XML 配置注入虽危害稍低,但易被组合利用,核心防护手段是禁用 dev 模式、升级依赖、白名单校验
  3. 所有漏洞的底层防护逻辑一致:最小权限原则 (禁用不必要的功能)+ 输入白名单 (拒绝一切未校验的用户输入)+ 版本及时升级
相关推荐
HEU_firejef2 小时前
实战篇(一)BitMap实现签到功能
java·redis
若丶相见2 小时前
腾讯云完整部署方案:CODING + CI/CD + Docker + Nginx + K8s 扩展
前端·后端
java1234_小锋2 小时前
Java高频面试题:讲一下 ZooKeeper 的持久化机制?
java·zookeeper·java-zookeeper
油墨香^_^2 小时前
Spring Cloud Feign 进阶详解:契约测试、负载均衡、文件上传与原生API
java·开发语言
前路不黑暗@3 小时前
Java项目:Java脚手架项目的地图服务(十)
java·数据库·spring boot·笔记·学习·spring cloud·maven
014-code4 小时前
Redisson 常用技巧
java·redis
java干货4 小时前
明明删了数据,磁盘却满了?
java
之歆4 小时前
HA 高可用集群指南
java·开发语言
CHANG_THE_WORLD4 小时前
指针入门一
java·前端·网络