
# Pädagogische Neufassung des Copy-Fail-PoC (CVE-2026-31431) — Linux-Kernel-LPE über algif_aead-In-Place-Krypto + splice()-Page-Cache-Schreibvorgang
Pädagogische Neuaufbereitung des Proof-of-Concept von Theori/Xint für CVE-2026-31431,
eine lokale Privilegieneskalations-Schwachstelle in der algif_aead-Krypto-Socket-Schnittstelle
des Linux-Kernels. Betrifft jeden Mainline-Kernel von 4.14 (Juli 2017)
bis 6.18.21 sowie den stabilen 6.19-Zweig bis 6.19.11.
Nur für Bildungszwecke und autorisierte Sicherheitsforschung. Führen Sie dies NICHT auf Systemen aus, die Ihnen nicht gehören oder für die Sie keine ausdrückliche schriftliche Genehmigung zum Testen haben. Die Ausführung auf einem verwundbaren Host verschafft jedem unprivilegierten lokalen Benutzer sofortigen Root-Zugriff. Die Autoren übernehmen keine Verantwortung für Missbrauch.
Der Linux-Kernel stellt seit Kernel 3.2 über die AF_ALG-Socket-Familie
(<linux/if_alg.h>) eine In-Kernel-Kryptografie-API für Userspace bereit. Userspace
öffnet einen SOCK_SEQPACKET-Socket, bindet ihn an eine Algorithmus-Vorlage (z. B.
"aead" / "authencesn(hmac(sha256),cbc(aes))") und sendet Daten zur
Verschlüsselung oder Entschlüsselung.
Im Jahr 2017 wurde eine Leistungsoptimierung zusammengeführt, die es AEAD-Algorithmen ermöglicht, Daten an Ort und Stelle zu verschlüsseln oder zu entschlüsseln, wenn der Kernel erkennt, dass Quelle und Ziel dieselben zugrunde liegenden Seiten gemeinsam nutzen. Dadurch wird bei jedem Vorgang eine redundante Speicherkopie vermieden.
Die authencesn-Vorlage (die Extended-Sequence-Number-Unterstützung zur
authentifizierten Verschlüsselung hinzufügt) enthält während der Entschlüsselung einen
Scratch-Schreibvorgang: Sie schreibt ESN-Bytes in einen bestimmten Offset innerhalb des
Datenpuffers des Vorgangs, bevor die Authentifizierungsprüfung ausgeführt wird. Wenn die
Quellseiten des Vorgangs über splice() aus dem Page-Cache einer regulären Datei
stammen und die In-Place-Optimierung aktiv ist, geht dieser Scratch-Schreibvorgang
direkt zurück in diese gecachten Seiten.
Da der Page-Cache des Kernels ein gemeinsames Mapping ist — jeder Prozess, der dieselbe Datei öffnet, sieht dieselben physischen Seiten — kann ein unprivilegierter Benutzer:
/usr/bin/su) mit O_RDONLY öffnen.AF_ALG-Operations-Socket splicesen.authencesn-Entschlüsselung auslösen; der ESN-Scratch-Schreibvorgang
beschädigt die Seite an einem kontrollierten Offset mit angreiferkontrollierten Bytes.Off-Host-Integritätsscanner (AIDE, Tripwire, IMA/EVM), die Prüfsummen von On-Disk-Dateien vergleichen, sind für diesen Angriff völlig blind. Der Schreibvorgang verschwindet nach einer Page-Cache-Verdrängung oder einem Neustart und hinterlässt keine forensische Spur auf der Festplatte.
Durch das Zielen auf /usr/bin/su (ein setuid root-Binary) und das Überschreiben
eines Verzweigungsbefehls, der die PAM-Authentifizierungsprüfung schützt, erhält der
Angreifer eine passwortlose Root-Shell.
Der Optimierungs-Commit, der den Fehler einführte, landete im 4.14-Entwicklungszyklus
(Juli 2017). Jeder Kernel, der mit CONFIG_CRYPTO_USER_API_AEAD=y und
CONFIG_CRYPTO_AUTHENC=y (beides gängige Standardwerte) in den obigen Bereichen
kompiliert wurde, ist verwundbar.
Überprüfen Sie den Sicherheits-Tracker Ihrer Distribution für den genauen Advisory-Status.
os.splice wurde in Python 3.10 hinzugefügt)/usr/bin/su, weltweit lesbar,
da es setuid ist)# Zeigt, was geschrieben würde, ohne den Kernel zu berühren (sicher):
python3 copy_fail_exploit.py --dry-run
# Patcht den /usr/bin/su-Page-Cache (verwundbarer Kernel erforderlich):
# WARNUNG: verwundbarer Kernel erforderlich — nur auf Systemen verwenden, die Ihnen gehören
python3 copy_fail_exploit.py
# Patcht und eskaliert sofort zu Root:
python3 copy_fail_exploit.py --spawn-shell
# Verwendet ein benutzerdefiniertes Ziel-Binary und Payload:
python3 copy_fail_exploit.py --target /usr/bin/sudo --payload-file ./custom_patch.bin
# Ausführliche Ausgabe (jeden 4-Byte-Schreibvorgang ausgeben):
python3 copy_fail_exploit.py --verbose --dry-run
Standardmäßig ist --spawn-shell aus. Nach dem Patchen gibt das Skript Folgendes aus:
[+] Patch auf Page-Cache von '/usr/bin/su' angewendet (Festplatte unverändert).
Führen Sie `su` aus, um zu eskalieren, oder führen Sie es erneut mit --spawn-shell aus.
Zum Wiederherstellen: echo 3 | sudo tee /proc/sys/vm/drop_caches
Sie müssen dem Shell-Spawn mit --spawn-shell zustimmen. Dies ist beabsichtigt:
Es zwingt Sie, zu verstehen, was der Exploit getan hat, bevor Sie das Ergebnis ausführen.
Einrichten des Primitivs.
Der Exploit öffnet einen AF_ALG-Socket und bindet ihn an die
authencesn(hmac(sha256),cbc(aes))-Vorlage mit einem Dummy-All-Null-Schlüssel. Er
konfiguriert dann die Authentifizierungs-Tag-Größe auf 4 Bytes über ALG_SET_AEAD_AUTHSIZE.
accept() auf dem Kontroll-Socket liefert einen Operations-Socket, der einzelne
Entschlüsselungsanfragen übermitteln kann.
Auslösen des Page-Cache-Schreibvorgangs.
Für jedes 4-Byte-Chunk des Patch-Payloads ruft der Exploit sendmsg() auf dem
Operations-Socket mit gesetztem MSG_MORE auf und übergibt 8 Bytes assoziierte Daten
(AAD): 4 Bytes Füllmaterial gefolgt von den 4 Payload-Bytes. MSG_MORE teilt dem
Kernel mit, den Vorgang zu halten, bis weitere Daten eintreffen. Er erstellt dann eine
Pipe und führt zwei splice()-Aufrufe aus — file_fd → pipe → op_sock — und spendet
die eigenen Page-Cache-Seiten der Datei als Eingabe für den Entschlüsselungsvorgang. Wenn
recv() schließlich aufgerufen wird, führt der Kernel die authencesn-Entschlüsselung aus.
Die In-Place-Optimierung greift (Quelle und Ziel sind dieselben Seiten), und der
ESN-Scratch-Schreibvorgang kopiert unsere Payload-Bytes in die Cache-Seite am
Ziel-Offset. recv() gibt EBADMSG zurück, weil das Authentifizierungs-Tag nicht
verifiziert werden kann — das ist erwartet und harmlos. Der Schreibvorgang ist bereits erfolgt.
Patchen des Binaries.
Das eingebettete Payload (wörtlich aus dem Theori-PoC übernommen) überschreibt einen
Verzweigungsbefehl in /usr/bin/su aus einem Standard-util-linux-Build und verwandelt
einen bedingten Sprung, der die PAM-Authentifizierung erzwingt, in einen unbedingten
Durchfall. Nach dem Patchen gelingt das Ausführen von su ohne Passwort und
erzeugt eine Root-Shell. Das On-Disk-Binary bleibt unberührt; das Verwerfen von
Page-Cache-Einträgen (echo 3 > /proc/sys/vm/drop_caches) macht die Änderung sofort rückgängig.
Für eine tiefere technische Analyse siehe die Referenzen unten, insbesondere den Xint-Blogbeitrag und das Theori-PoC-Repository.
- rule: AF_ALG-Socket von unprivilegiertem Prozess geöffnet
desc: >
CVE-2026-31431 — ein unprivilegierter Prozess hat einen AF_ALG (Familie 38)
Socket geöffnet, was der erste Schritt des Copy-Fail-Exploits ist.
condition: >
evt.type = socket and
evt.arg.domain = 38 and
not user.uid = 0
output: >
AF_ALG-Socket geöffnet (user=%user.name uid=%user.uid
pid=%proc.pid comm=%proc.name)
priority: WARNING
tags: [host, network, privilege_escalation, CVE-2026-31431]
rule CopyFail_CVE_2026_31431 {
meta:
description = "Erkennt Copy-Fail-Exploit-Skript im Speicher oder auf der Festplatte"
cve = "CVE-2026-31431"
strings:
$template = "authencesn(hmac(sha256),cbc(aes))" ascii
$splice = "os.splice" ascii
$aflag = "AF_ALG" ascii
condition:
all of them
}
Zu /etc/audit/rules.d/cve-2026-31431.rules hinzufügen:
-a always,exit -F arch=b64 -S socket -F a0=38 -k cve_2026_31431_afalg
Dann Protokolle überwachen mit:
ausearch -k cve_2026_31431_afalg --interpret
1. Kernel-Patch anwenden (empfohlen) Upgrade auf Kernel 6.18.22, 6.19.12, 7.0-rc7 oder später, oder wenden Sie das Sicherheitsupdate Ihrer Distribution an.
2. CONFIG_CRYPTO_USER_API_AEAD zur Build-Zeit deaktivieren Wenn Sie Ihren eigenen Kernel bauen, setzen Sie:
# CONFIG_CRYPTO_USER_API_AEAD is not set
Dies entfernt die gesamte AF_ALG-AEAD-Schnittstelle und beseitigt die Angriffsfläche.
Die meisten eingebetteten/gehärteten Bereitstellungen benötigen sie nicht.
3. seccomp — AF_ALG-Socket-Familie verweigern
Fügen Sie einen seccomp-Filter zu sensiblen Prozessen hinzu (oder systemweit über eine
LSM-Richtlinie), der socket(AF_ALG, ...) ablehnt:
// socket() verweigern, wenn domain == AF_ALG (38)
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 38, 0, 1),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | EACCES),
4. Page-Cache-Privilegien durch Kernel-Härtung einschränken
vm.unprivileged_userfaultfd=0 und ähnliche Tunables reduzieren die Angriffsfläche
von benutzerzugänglichen Kernel-Speicherschnittstellen, obwohl sie diese CVE nicht
direkt blockieren.
Der Exploit modifiziert nur den In-Memory-Page-Cache; das On-Disk-Binary wird nie berührt. Um den ursprünglichen Dateiinhalt im Speicher wiederherzustellen, verwerfen Sie den Page-Cache des Kernels:
echo 3 | sudo tee /proc/sys/vm/drop_caches
Dies verdrängt alle sauberen Seiten aus dem Cache. Der nächste Lesevorgang von /usr/bin/su
(oder welchem Binary auch immer gepatcht wurde) lädt die ursprünglichen Bytes von der
Festplatte neu.
Ein Neustart leert den Page-Cache ebenfalls vollständig.
MIT — siehe LICENSE.
MIT wurde einer benutzerdefinierten "Nur für Bildungszwecke"-Lizenz vorgezogen, da eine
solche Lizenz nicht als anerkannter OSI/SPDX-Bezeichner existiert. MIT ist permissiv,
rechtlich gut verstanden und mit Repositories für verantwortungsvolle Offenlegung
kompatibel. Die Bildungsabsicht wird im Modul-Docstring, im Haftungsausschluss-Abschnitt
dieser README und in der --help-Ausgabe ausgedrückt — nicht in einer rechtlich
zweifelhaften benutzerdefinierten Lizenzklausel.
| Zweig | Erste verwundbare Version | Letzte verwundbare Version | Behoben in |
|---|
| Mainline | 4.14 | 6.18.21 | 6.18.22 |
| 6.19 stable | 6.19.0 | 6.19.11 | 6.19.12 |
| 7.0-rc | 7.0-rc1 | 7.0-rc6 | 7.0-rc7 |
| Distribution | Mitgelieferter Kernel (ca.) | Gepatcht? |
|---|
| Debian 12 (Bookworm) | 6.1.x | Ja (Backport) |
| Debian 13 (Trixie) | 6.12.x / 6.14.x | Ja (Backport) |
| Ubuntu 24.04 LTS | 6.8.x | Ja (USN-7xxx) |
| Ubuntu 24.10 | 6.11.x | Ja |
| RHEL 9.x | 5.14.x (rebasiert) | Ja (RHSA) |
| Alpine 3.20 | 6.6.x | Ja (Backport) |
| Arch Linux | Rolling (≥ 6.18.22 jetzt) | Ja |
| Kali Linux 2026.1 | 6.18.12 | Verwundbar |
| Kali Linux 2026.2+ | 6.18.22+ | Behoben |
| Linux Mint 22 | 6.8.x (Ubuntu-Basis) | Ja (Ubuntu USN) |