Skip to content
Tech News
← Back to articles

Claude Wrote a Full FreeBSD Remote Kernel RCE with Root Shell (CVE-2026-4747)

read original more articles
Why This Matters

The article highlights a critical remote kernel vulnerability (CVE-2026-4747) in FreeBSD that allows attackers to execute arbitrary code with root privileges through a stack buffer overflow in the RPCSEC_GSS implementation. This flaw emphasizes the importance of rigorous input validation and secure coding practices in kernel modules to prevent privilege escalation and remote exploits, which can significantly impact both the security of affected systems and the trustworthiness of the broader Unix-like ecosystem.

Key Takeaways

CVE-2026-4747 — FreeBSD kgssapi.ko RPCSEC_GSS Stack Buffer Overflow

Full Remote Kernel RCE → uid 0 Reverse Shell

Advisory: FreeBSD-SA-26:08.rpcsec_gss CVE: CVE-2026-4747 Affected: FreeBSD 13.5 (<p11), 14.3 (<p10), 14.4 (<p1), 15.0 (<p5) Tested on: FreeBSD 14.4-RELEASE amd64 (GENERIC kernel, no KASLR) Attack surface: NFS server with kgssapi.ko loaded (port 2049/TCP)

1. The Vulnerability

Root Cause

In sys/rpc/rpcsec_gss/svc_rpcsec_gss.c , the function svc_rpc_gss_validate() reconstructs an RPC header into a 128-byte stack buffer ( rpchdr[] ) for GSS-API signature verification. It first writes 32 bytes of fixed RPC header fields, then copies the entire RPCSEC_GSS credential body ( oa_length bytes) into the remaining space — without checking that oa_length fits.

static bool_t svc_rpc_gss_validate ( struct svc_rpc_gss_client * client , struct rpc_msg * msg , gss_qop_t * qop , rpc_gss_proc_t gcproc ) { int32_t rpchdr [ 128 / sizeof ( int32_t )]; // 128 bytes on stack int32_t * buf ; memset ( rpchdr , 0 , sizeof ( rpchdr )); // Write 8 fixed-size RPC header fields (32 bytes total) buf = rpchdr ; IXDR_PUT_LONG ( buf , msg -> rm_xid ); IXDR_PUT_ENUM ( buf , msg -> rm_direction ); IXDR_PUT_LONG ( buf , msg -> rm_call . cb_rpcvers ); IXDR_PUT_LONG ( buf , msg -> rm_call . cb_prog ); IXDR_PUT_LONG ( buf , msg -> rm_call . cb_vers ); IXDR_PUT_LONG ( buf , msg -> rm_call . cb_proc ); oa = & msg -> rm_call . cb_cred ; IXDR_PUT_ENUM ( buf , oa -> oa_flavor ); IXDR_PUT_LONG ( buf , oa -> oa_length ); if ( oa -> oa_length ) { // BUG: No bounds check on oa_length! // After 32 bytes of header, only 96 bytes remain in rpchdr. // If oa_length > 96, this overflows past rpchdr into: // local variables → saved callee-saved registers → return address memcpy (( caddr_t ) buf , oa -> oa_base , oa -> oa_length ); buf += RNDUP ( oa -> oa_length ) / sizeof ( int32_t ); } // gss_verify_mic() called after — but overflow already happened }

The buffer has only 128 - 32 = 96 bytes of space for the credential body. Any credential larger than 96 bytes overflows the stack buffer.

The Fix (14.4-RELEASE-p1)

The patch adds a single bounds check before the copy:

... continue reading