KASLR繞過及提權利用(CVE-2023-35001)

合天网安实验室發表於2024-04-11

前言

本文將介紹如何繞過KASLR以及如何提權利用。

KASLR繞過

可以利用byteorder操作加上netlink組訂閱可以洩露rule中的handle欄位。該方法應該是可以用來洩露kernel基地址的,但是作者還提出另一種方法進行洩露。應該是為了提權利用做鋪墊。

由於發現已經洩露的模組的基地址,因此可以利用模組地址偽造表示式。

作者找到了range表示式,用於偽造其餘表示式。總大小為0x23。並且表示式是八位元組對齊的,因此該結構體會佔用0x28位元組。

struct nft_range_expr {
    struct nft_data     data_from;
    struct nft_data     data_to;
    u8          sreg;
    u8          len;
    enum nft_range_ops  op:8;
};

具體的佈局如下

image-20240227185357673

可以看到data_fromdata_to都是從使用者態中傳遞過去的資料,因此我們可以在這些區域內偽造表示式,這有點像在CTF中,我們洩露了堆塊基址後,隨意偽造堆塊。

由於我們有0x28位元組的空間,但是實際能夠操作的空間是data_fromdata_to兩段,即0x20的空間大小。因此我們需要挑選小於0x20的規則表示式進行偽造,並且能夠執行洩露功能的。

這裡作者選用了byteorder表示式,可以看到該表示式在對齊後只佔用八位元組。

struct nft_byteorder {
    u8          sreg;
    u8          dreg;
    enum nft_byteorder_ops  op:8;
    u8          len;
    u8          size;
};

構造後,可以發現還有八位元組的data_to沒有用,但是並不能直接丟棄不適用,因為在呼叫完byteorder操作後還需要繼續執行其他規則表示式。

image-20240227190243722

但是其他表示式都是需要大於0x8的,畢竟一個操作指標就佔用八位元組了,此時作者選用了meta表示式。可以看到meta表示式也只用到了三個位元組,剛好對應range表示式的sreglen以及op

struct nft_meta {
    enum nft_meta_keys  key:8;
    u8          len;
    union {
        u8      dreg;
        u8      sreg;
    };
};

meta表示式的操作如下,在meta表示式中meta->key執行具體的操作,如[1],但是若該值是非法值則會執行[2],可以看到該meta表示式僅會丟擲異常,但是不會終止執行,這就說明即使meta->key是非法值也不會影響後續規則表示式的正常執行。

File: linux-5.19\net\netfilter\nft_meta.c
418: void nft_meta_set_eval(const struct nft_expr *expr,
419:               struct nft_regs *regs,
420:               const struct nft_pktinfo *pkt)
421: {
422:    const struct nft_meta *meta = nft_expr_priv(expr);
423:    struct sk_buff *skb = pkt->skb;
424:    u32 *sreg = &regs->data[meta->sreg];
425:    u32 value = *sreg;
426:    u8 value8;
427: 
428:    switch (meta->key) { ----> [1]
429:    case NFT_META_MARK:
430:        skb->mark = value;
431:        break;
432:    case NFT_META_PRIORITY:
433:        skb->priority = value;
434:        break;
435:    case NFT_META_PKTTYPE:
436:        value8 = nft_reg_load8(sreg);
437: 
438:        if (skb->pkt_type != value8 &&
439:            skb_pkt_type_ok(value8) &&
440:            skb_pkt_type_ok(skb->pkt_type))
441:            skb->pkt_type = value8;
442:        break;
443:    case NFT_META_NFTRACE:
444:        value8 = nft_reg_load8(sreg);
445: 
446:        skb->nf_trace = !!value8;
447:        break;
448: #ifdef CONFIG_NETWORK_SECMARK
449:    case NFT_META_SECMARK:
450:        skb->secmark = value;
451:        break;
452: #endif
453:    default:
454:        WARN_ON(1); ---->[2]
455:    }
456: }

因此第二個偽造的表示式也找到了,就是meta表示式。由於我們直接偽造了規則表示式,因此不會進行暫存器引數的校驗,只要選擇核心地址選擇洩露即可。

image-20240227191748571

這裡簡單說一下偽造的規則頭,此時的len需要設定為0x20以及islast需要設定為0。

最後洩露的效果如下,即使核心已經丟擲了異常,但是不會影響後續表示式的正常執行。

image-20240227192131407

【----幫助網安學習,以下所有學習資料免費領!加vx:dctintin,備註 “部落格園” 獲取!】

 ① 網安學習成長路徑思維導圖
 ② 60+網安經典常用工具包
 ③ 100+SRC漏洞分析報告
 ④ 150+網安攻防實戰技術電子書
 ⑤ 最權威CISSP 認證考試指南+題庫
 ⑥ 超1800頁CTF實戰技巧手冊
 ⑦ 最新網安大廠面試題合集(含答案)
 ⑧ APP客戶端安全檢測指南(安卓+IOS)

提權利用

既然可以隨意偽造表示式,因此我們可以偽造payload表示式。

struct nft_payload {
    enum nft_payload_bases  base:8;
    u8          offset;
    u8          len;
    u8          dreg;
};

image-20240227194109554

regs下方存在著nft_do_chain函式返回地址,因此可以直接透過payload表示式將提權payload注入進來。

image-20240227194544551

由於我們可以偽造payload表示式,因此注入的payload長度不受限,因此採用

  • commit_creds(prepare_kernel_cred(0)),構造root憑證

  • 接著利用find_task_by_vpidinit_nsproxy以及switch_task_namespaces切換名稱空間。

  • 最後利用蹦床swapgs_restore_regs_and_retrun_to_usermode返回到使用者空間完成提權利用。

image-20240227195613084

完整exphttps://github.com/h0pe-ay/Vulnerability-Reproduction/tree/master/CVE-2023-35001(nftables)

更多網安技能的線上實操練習,請點選這裡>>

相關文章