Alibaba Sentinel SSRF漏洞代码审计
字数 1066 2025-08-29 22:41:11

Alibaba Sentinel SSRF漏洞代码审计与分析

一、Sentinel组件概述

Sentinel是阿里巴巴开源的面向分布式、多语言异构化服务架构的流量治理组件,主要功能包括:

  • 流量路由
  • 流量控制
  • 流量整形
  • 熔断降级
  • 系统自适应过载保护
  • 热点流量防护

二、漏洞背景

本文分析的SSRF漏洞不同于已知的CVE-2021-44139漏洞,而是与获取集群状态功能相关的新SSRF漏洞。

三、受影响版本

分析版本:v1.8.8(2025年5月时的最新Releases版)

四、漏洞详细分析

1. 漏洞入口点

漏洞位于com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterConfigController.java文件的119-146行,主要功能是获取集群或目标机器状态。

2. 参数处理流程

// 接收三个参数
String app = request.getParam("app");
String ip = request.getParam("ip");
String portStr = request.getParam("port");

// 参数非空检查
if (StringUtil.isEmpty(app)) {
    throw new IllegalArgumentException("app cannot be null or empty");
}
if (StringUtil.isEmpty(ip)) {
    throw new IllegalArgumentException("ip cannot be null or empty");
}
if (StringUtil.isEmpty(portStr)) {
    throw new IllegalArgumentException("port cannot be null or empty");
}

// 版本支持检查
if (!checkIfSupported(app, ip, port)) {
    return unsupportedVersion(app, ip, port);
}

3. 集群状态获取逻辑

// 异步获取集群状态
CompletableFuture<ClusterUniversalStateVO> future = clusterConfigService
    .getClusterUniversalState(app, ip, port)
    .thenApply(e -> new Result<>(e).setSuccess(true));

// 阻塞等待结果
try {
    return future.get();
} catch (ExecutionException e) {
    logger.error("Error when getting cluster state", e);
    return new Result<>().setSuccess(false)
        .setMsg(e.getCause().getMessage());
} catch (Exception e) {
    logger.error("Error when getting cluster state", e);
    return new Result<>().setSuccess(false)
        .setCode(-1)
        .setMsg(e.getMessage());
}

4. 服务层调用链

进入com/alibaba/csp/sentinel/dashboard/service/ClusterConfigService.java的148-166行:

public CompletableFuture<ClusterUniversalStateVO> getClusterUniversalState(
    String app, String ip, Integer port) {
    
    // 获取集群模式信息
    return sentinelApiClient.fetchClusterMode(ip, port)
        .thenApply(e -> new ClusterUniversalStateVO().setStateInfo(e))
        .thenCompose(state -> {
            // 获取客户端信息
            return sentinelApiClient.fetchClusterClientInfo(ip, port)
                .thenApply(e -> state.setClientInfo(e));
        })
        .thenCompose(state -> {
            // 获取服务器信息
            return sentinelApiClient.fetchClusterServerInfo(ip, port)
                .thenApply(e -> state.setServerInfo(e));
        });
}

5. API客户端实现

进入com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java的626-637行:

public CompletableFuture<ClusterStateSimpleEntity> fetchClusterMode(
    String ip, Integer port) {
    
    // 构建请求路径
    String url = String.format(FETCH_CLUSTER_MODE_PATH, ip, port);
    
    // 执行命令获取响应
    return executeCommand(ip, port, url, null, 
        response -> JsonUtils.parseObject(
            response.getContent(), ClusterStateSimpleEntity.class));
}

6. HTTP请求执行核心

最终在280-315行执行HTTP请求:

private <R> CompletableFuture<R> executeCommand(
    String ip, Integer port, String url, String body, 
    Function<HttpResponse, R> responseParser) {
    
    // 参数校验
    if (StringUtil.isEmpty(ip)) {
        throw new IllegalArgumentException("ip cannot be null or empty");
    }
    if (port == null || port <= 0) {
        throw new IllegalArgumentException("Invalid port");
    }
    
    // 构建基础URL
    String fullUrl = "http://" + ip + ":" + port + url;
    
    // 构造HTTP请求
    HttpRequestBase request;
    if (StringUtil.isEmpty(body)) {
        request = new HttpGet(fullUrl);
    } else {
        HttpPost postRequest = new HttpPost(fullUrl);
        postRequest.setEntity(new StringEntity(body, ContentType.APPLICATION_JSON));
        request = postRequest;
    }
    
    // 执行请求(漏洞点:未对IP地址进行充分校验)
    return asyncRequest(request, responseParser);
}

五、漏洞复现步骤

  1. 漏洞接口:/cluster/state_single(需要登录后访问)
  2. 完整路径:http://localhost:8080/cluster/state_single
  3. 构造请求示例:
    http://localhost:8080/cluster/state_single?app=SSRF-TEST&ip=127.0.0.1&port=80
    
  4. 可修改ip参数为任意目标地址进行SSRF攻击

六、漏洞原理总结

漏洞产生原因:

  1. 在构建HTTP请求时,直接拼接用户输入的IP地址和端口
  2. 缺乏对IP地址的完整合法性校验:
    • 未检查是否为内网IP
    • 未限制可访问的协议类型(只能使用HTTP)
    • 未对目标地址进行白名单限制

七、修复建议

  1. 增加IP地址校验逻辑:

    • 检查是否为内网地址
    • 实现IP白名单机制
  2. 限制协议类型:

    • 强制使用HTTPS
    • 禁用非常用协议
  3. 增加输入验证:

    if (!isValidIp(ip) || isInternalIp(ip)) {
        throw new IllegalArgumentException("Invalid IP address");
    }
    
  4. 使用安全的URL构建方式:

    URI uri = new URIBuilder()
        .setScheme("https")
        .setHost(validatedIp)
        .setPort(validatedPort)
        .setPath(url)
        .build();
    

八、学习要点

  1. SSRF漏洞常见触发场景:

    • 直接拼接用户输入构建URL
    • 缺乏对目标地址的校验
    • 能够访问内部服务
  2. 代码审计关键点:

    • 追踪用户输入流向
    • 检查HTTP请求构建过程
    • 验证所有外部输入
  3. 防御措施:

    • 输入验证和过滤
    • 输出编码
    • 最小权限原则
    • 网络层隔离
Alibaba Sentinel SSRF漏洞代码审计与分析 一、Sentinel组件概述 Sentinel是阿里巴巴开源的面向分布式、多语言异构化服务架构的流量治理组件,主要功能包括: 流量路由 流量控制 流量整形 熔断降级 系统自适应过载保护 热点流量防护 二、漏洞背景 本文分析的SSRF漏洞不同于已知的CVE-2021-44139漏洞,而是与获取集群状态功能相关的新SSRF漏洞。 三、受影响版本 分析版本:v1.8.8(2025年5月时的最新Releases版) 四、漏洞详细分析 1. 漏洞入口点 漏洞位于 com/alibaba/csp/sentinel/dashboard/controller/cluster/ClusterConfigController.java 文件的119-146行,主要功能是获取集群或目标机器状态。 2. 参数处理流程 3. 集群状态获取逻辑 4. 服务层调用链 进入 com/alibaba/csp/sentinel/dashboard/service/ClusterConfigService.java 的148-166行: 5. API客户端实现 进入 com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java 的626-637行: 6. HTTP请求执行核心 最终在280-315行执行HTTP请求: 五、漏洞复现步骤 漏洞接口: /cluster/state_single (需要登录后访问) 完整路径: http://localhost:8080/cluster/state_single 构造请求示例: 可修改 ip 参数为任意目标地址进行SSRF攻击 六、漏洞原理总结 漏洞产生原因: 在构建HTTP请求时,直接拼接用户输入的IP地址和端口 缺乏对IP地址的完整合法性校验: 未检查是否为内网IP 未限制可访问的协议类型(只能使用HTTP) 未对目标地址进行白名单限制 七、修复建议 增加IP地址校验逻辑: 检查是否为内网地址 实现IP白名单机制 限制协议类型: 强制使用HTTPS 禁用非常用协议 增加输入验证: 使用安全的URL构建方式: 八、学习要点 SSRF漏洞常见触发场景: 直接拼接用户输入构建URL 缺乏对目标地址的校验 能够访问内部服务 代码审计关键点: 追踪用户输入流向 检查HTTP请求构建过程 验证所有外部输入 防御措施: 输入验证和过滤 输出编码 最小权限原则 网络层隔离