flawopen.com/Teardowns/cve-2024-26642-linux-nftables-anonymous-set-timeout

● CVE-2024-26642 · CVSS 7.8 · Hoch
Sicherheitsforschung · FlawOpen

CVE-2024-26642: Anonymes Set mit Timeout-Flag in Linux nf_tables

CVE-2024-26642 (CVSS 7.8 laut NIST): nf_tables_newset() akzeptierte anonyme Sets, die zusätzlich das Timeout-Flag trugen – eine Kombination, die kein Userspace-Werkzeug erzeugt. Dadurch unterlagen an eine Regel gebundene Sets dem Ablauf von Elementen und der Garbage Collection. Linux 6.8 weist sie mit -EOPNOTSUPP ab.

💡 Einfache Erklärung (ELI5)

Eine Garderobe hat zwei Systeme. Nummerierte Haken gehören einen Abend lang genau einem Gast und werden geräumt, sobald er geht. Zeitmarken sammelt stündlich ein Mitarbeiter ein, der alles Abgelaufene entfernt. Das Formular erlaubt, für denselben Mantel beide Kästchen anzukreuzen: Der Haken wird dann beim Gehen des Gasts geräumt und zusätzlich nach dem Plan des Mitarbeiters. Zwei Leute halten sich für denselben Haken zuständig, und keiner kennt den Zeitplan des anderen. Die Lösung ist einfach: Das Formular lehnt dieses Kästchenpaar jetzt ab.

Kernkonzepte & Begriffe

nf_tables set
Kernel-Datenstruktur mit Adressen, Ports oder anderen Schlüsseln, gegen die nftables-Regeln prüfen; angelegt per Netlink-Nachricht NFT_MSG_NEWSET und verarbeitet von nf_tables_newset().
Anonymes Set (NFT_SET_ANONYMOUS)
Ein unbenanntes Set wie { 22, 80 }, das direkt in einer Regel steht. Es ist an genau diese Regel gebunden und wird in derselben Transaktion mit ihr zerstört.
NFT_SET_TIMEOUT
Flag, das Set-Elementen eine Ablaufzeit gibt. Abgelaufene Elemente entfernt die Garbage Collection des Sets.
NFT_SET_EVAL
Flag für Sets, die aus dem Paketpfad aktualisiert werden, genutzt von alten meter-Anweisungen. Der Fix lässt anonym + Timeout + Eval für sie weiter zu.
CAP_NET_ADMIN in einem User-Namespace
nf_tables nimmt Konfiguration von jedem Prozess mit CAP_NET_ADMIN in seinem Netzwerk-Namespace an. Ein unprivilegierter Benutzer erhält dieses Recht, indem er einen User-Namespace anlegt, sofern die Distribution das erlaubt.

Ursachenanalyse

nf_tables_newset() in net/netfilter/nf_tables_api.c prüfte die Set-Flags nur auf unbekannte Bits und auf die Konflikte MAP+OBJECT und EVAL+OBJECT. NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT wurde akzeptiert, sodass ein Set, dessen Lebensdauer an eine einzige Regel und Transaktion gebunden ist, zusätzlich Elemente haben konnte, die ablaufen und von der Garbage Collection eingesammelt werden. Userspace erzeugt diese Kombination nie, und der Lebensdauer-Code war nicht dafür ausgelegt. Der Upstream-Fix lehnt sie mit -EOPNOTSUPP ab, sofern nicht zusätzlich NFT_SET_EVAL gesetzt ist. Den daraus folgenden Speicherfehler beschreibt die öffentliche Dokumentation nicht im Detail; das NIST bewertet ihn mit 7.8 (Vertraulichkeit, Integrität und Verfügbarkeit hoch), die Kernel-CNA mit 5.5 (nur Verfügbarkeit).

Schritt-für-Schritt Angriffsablauf

Schritt 1

CAP_NET_ADMIN erlangen

Ein lokaler Benutzer legt einen User- und einen Netzwerk-Namespace an (wo unprivilegierte User-Namespaces erlaubt sind) und besitzt damit CAP_NET_ADMIN über den nf_tables-Zustand dieses Namespace.

Schritt 2

Das ungültige Set anfordern

In einem Netlink-Batch sendet der Prozess NFT_MSG_NEWSET mit NFTA_SET_FLAGS = NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT und bindet das Set über einen Lookup-Ausdruck an eine neue Regel.

Schritt 3

Der Kernel akzeptiert

nf_tables_newset() findet kein verbotenes Flag-Paar und legt ein regelgebundenes anonymes Set an, dessen Elemente eine Ablaufzeit haben.

Schritt 4

Ungetestete Lebensdauerpfade

Commit, Abbruch oder Löschen der Regel lösen nun gleichzeitig den Abbau des Sets und die Garbage Collection der Elemente aus – in Pfaden, die der Transaktionscode von nf_tables nicht sicher behandelt.

Quellcode: Verwundbar vs. Sicher

VERWUNDBARE IMPLEMENTIERUNG
/* net/netfilter/nf_tables_api.c: nf_tables_newset(), before the fix */
	if (nla[NFTA_SET_FLAGS] != NULL) {
		flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
		if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
			      NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
			      NFT_SET_MAP | NFT_SET_EVAL |
			      NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
			return -EOPNOTSUPP;
		/* Only one of these operations is supported */
		if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
			     (NFT_SET_MAP | NFT_SET_OBJECT))
			return -EOPNOTSUPP;
		if ((flags & (NFT_SET_EVAL | NFT_SET_OBJECT)) ==
			     (NFT_SET_EVAL | NFT_SET_OBJECT))
			return -EOPNOTSUPP;
		/* BUG: NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT is accepted. A rule-bound
		 * anonymous set now also gets per-element expiry and garbage
		 * collection, a combination nft never creates and the set
		 * lifetime code was not written for. */
	}
GEHÄRTETER SICHERHEITS-PATCH
/* net/netfilter/nf_tables_api.c: nf_tables_newset(), commit 16603605b667 */
	if (nla[NFTA_SET_FLAGS] != NULL) {
		flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
		if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
			      NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
			      NFT_SET_MAP | NFT_SET_EVAL |
			      NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
			return -EOPNOTSUPP;
		/* Only one of these operations is supported */
		if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
			     (NFT_SET_MAP | NFT_SET_OBJECT))
			return -EOPNOTSUPP;
		if ((flags & (NFT_SET_EVAL | NFT_SET_OBJECT)) ==
			     (NFT_SET_EVAL | NFT_SET_OBJECT))
			return -EOPNOTSUPP;
		/* FIX: anonymous sets are never used with timeouts from userspace,
		 * so reject the combination before the set exists. NFT_SET_EVAL
		 * stays allowed so legacy meters keep working. */
		if ((flags & (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT | NFT_SET_EVAL)) ==
			     (NFT_SET_ANONYMOUS | NFT_SET_TIMEOUT))
			return -EOPNOTSUPP;
	}

Checkliste für Engineering & Systemsicherheit

Quellen