Skip to content
Tech News
← Back to articles

Claude wrote a full FreeBSD remote kernel RCE with root shell

read original more articles
Why This Matters

Researchers discovered a critical remote kernel vulnerability in FreeBSD (CVE-2026-4747) that allows attackers to execute arbitrary code with root privileges via a stack buffer overflow in the RPCSEC_GSS implementation. Exploiting this flaw can lead to full system compromise, highlighting the importance of timely patches and updates for affected versions. This vulnerability underscores the ongoing need for rigorous input validation and security audits in kernel modules to prevent severe exploits.

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