前言
本文將介紹如何繞過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;
};
具體的佈局如下
可以看到data_from
與data_to
都是從使用者態中傳遞過去的資料,因此我們可以在這些區域內偽造表示式,這有點像在CTF
中,我們洩露了堆塊基址後,隨意偽造堆塊。
由於我們有0x28
位元組的空間,但是實際能夠操作的空間是data_from
與data_to
兩段,即0x20
的空間大小。因此我們需要挑選小於0x20
的規則表示式進行偽造,並且能夠執行洩露功能的。
這裡作者選用了byteorder
表示式,可以看到該表示式在對齊後只佔用八位元組。
struct nft_byteorder {
u8 sreg;
u8 dreg;
enum nft_byteorder_ops op:8;
u8 len;
u8 size;
};
構造後,可以發現還有八位元組的data_to
沒有用,但是並不能直接丟棄不適用,因為在呼叫完byteorder
操作後還需要繼續執行其他規則表示式。
但是其他表示式都是需要大於0x8
的,畢竟一個操作指標就佔用八位元組了,此時作者選用了meta
表示式。可以看到meta
表示式也只用到了三個位元組,剛好對應range
表示式的sreg
、len
以及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 = ®s->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
表示式。由於我們直接偽造了規則表示式,因此不會進行暫存器引數的校驗,只要選擇核心地址選擇洩露即可。
這裡簡單說一下偽造的規則頭,此時的len
需要設定為0x20以及islast
需要設定為0。
最後洩露的效果如下,即使核心已經丟擲了異常,但是不會影響後續表示式的正常執行。
【----幫助網安學習,以下所有學習資料免費領!加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;
};
在regs
下方存在著nft_do_chain
函式返回地址,因此可以直接透過payload
表示式將提權payload
注入進來。
由於我們可以偽造payload
表示式,因此注入的payload
長度不受限,因此採用
-
commit_creds(prepare_kernel_cred(0))
,構造root
憑證 -
接著利用
find_task_by_vpid
、init_nsproxy
以及switch_task_namespaces
切換名稱空間。 -
最後利用蹦床
swapgs_restore_regs_and_retrun_to_usermode
返回到使用者空間完成提權利用。
完整exp
:https://github.com/h0pe-ay/Vulnerability-Reproduction/tree/master/CVE-2023-35001(nftables)
更多網安技能的線上實操練習,請點選這裡>>