Skip to content

nftables nft_byteorder OOB (CVE-2023-35001)

"overlayfs" etiketine rağmen bu slug CVE-2023-35001'i belgeler: nftables jumpstack'ine bir netfilter nft_byteorder_eval() out-of-bounds read/write'ı; Synacktiv bunu Pwn2Own Vancouver 2023'te Ubuntu'yu root'lamak için kullandı.

Adlandırma notu

Alias'lar (nft_byteorder OOB, "StackRot-adjacent") gerçek konunun bir overlayfs kusuru değil, Synacktiv'in Pwn2Own 2023'te exploit ettiği nftables nft_byteorder bug'ı olan CVE-2023-35001 olduğunu açıkça gösterir. Bu not, gerçek CVE'yi anlatır.

Mechanism

Bir u32/u16 union'ının register array'i jumpstack'e doğru neden over-read ettiği

nftables, küçük bir per-packet register file'ını okuyup yazan expression'ları dolaşarak bir rule'u evaluate eder. nft_byteorder, bir register değerini byte-swap eden (host<->network order) expression'dır. Evaluator'ı, source ve destination register'larını alias'lamak için bir union deklare eder:

static void nft_byteorder_eval(const struct nft_expr *expr,
                               struct nft_regs *regs,
                               const struct nft_pktinfo *pkt)
{
    ...
    union { u32 u32; u16 u16; } *s, *d;
    s = (void *)&regs->data[priv->sreg];
    d = (void *)&regs->data[priv->dreg];
    ...
    case 2:                 /* 2-byte elements */
        for (i = 0; i < priv->len / 2; i++)
            d[i].u16 = ntohs((__force __be16)s[i].u16);
}

Bug şu: sizeof(union {...}), en büyük üyesinin boyutudur (4 byte), bu yüzden s[i] / d[i], 2-byte (u16) durumunda bile index başına 4 byte ilerler. len/2 iterasyonu register array'in sonunu aşacak şekilde seçilen bir len ile, loop regs->data[]'nin out of bounds'una read ve write yapar. Stack'te register'ların hemen ardında yatan şey rule-evaluation context'idir — özellikle de kaydedilmiş rule / last_rule pointer'larını tutan struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]. Bozuk stride dolayısıyla o kernel-stack pointer'ları üzerinde controlled bir OOB read/write verir.

İhlal edilen invariant şu: bir expression yalnızca fixed-size register file'a dokunmalıdır. 2-byte'lık bir operasyonu 4-byte'lık bir stride ile ele alarak, evaluator in-bounds bir register index'ini out-of-bounds bir stack erişimine çevirir.

Walkthrough

Bug, nftables'ı configure edebilen herhangi bir kullanıcı tarafından erişilebilir. Ubuntu'da unprivileged_userns_clone varsayılan olarak açıktır, bu yüzden unprivileged bir kullanıcı bir user namespace'e girip private bir net namespace üzerinde CAP_NET_ADMIN kazanabilir.

# Conceptually: from an unprivileged user namespace + net namespace,
# install an nft table/chain and an nft_byteorder expression in a subchain
# whose source register sits at the top of the register array and whose
# destination is at the bottom (or vice versa) with a 2-byte size and a
# length that makes the 4-byte stride walk into the jumpstack.
unshare - Urn bash      # new user + net namespace (Ubuntu default config)

OOB'den primitive'leri inşa etmek (Synacktiv'in zinciri):

  1. Read primitive. source/destination'ı, misaligned stride jumpstack pointer'larını (rule, last_rule) out of bounds okuyacak ve register içeriği üzerinden geri sızdıracak şekilde konumlandır — bir kernel pointer leak verir.
  2. Write primitive. Tersine çevir: register'lara seçilmiş değerler yerleştir ve misaligned d[i].u16 write'larının bir jumpstack pointer'ının low 16 bit'ini overwrite etmesine izin ver; bu, rule evaluation'ı attacker'ın expression data içine gömdüğü bir fake rule'a yönlendirir.
  3. Module/kernel base leak'le. nf_tables.ko ve kernel base'i leak'lemek için corrupted bir rule handle / crafted nft_byteorder read'leri kullan.
  4. Code execution. Attacker byte'larını (bir network packet'inde teslim edilen) stack'lenmiş bir return address üzerine kopyalayan fake bir nft_payload expression'ı üzerinden pivot et; root'a escalate etmek için bir ROP chain çalıştır.

Gereksinimler

nftables'ı programlama yeteneğine ihtiyaç duyar — yani CAP_NET_ADMIN, ki varsayılan Ubuntu'da unprivileged bir user namespace içinde elde edilebilir. Yayınlanan exploit, Pwn2Own image kernel 5.19.0-35'i hedefledi.

Detection

  • Unprivileged user namespace'lerden gelen nftables rule install'ları çoğu sunucuda anomalidir; namespace creation + nft netlink op'larını audit'lemek setup'ı yakalar.
  • KASAN, nft_byteorder_eval'de bir stack/global-out-of-bounds raporlar.

Mitigation

  • Element stride'ını düzelten upstream fix'i uygula; böylece 2-byte byteorder operasyonları 2 byte ilerler ve in bounds kalır.
  • Unprivileged kullanıcılara CAP_NET_ADMIN'i reddetmek için kernel.unprivileged_userns_clone=0 (veya user.max_user_namespaces=0) ayarla.

References