freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

KASLR绕过及提权利用(CVE-2023-35001)
2024-04-11 08:30:30

前言

本文将介绍如何绕过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,备注“freebuf”获取!】

① 网安学习成长路径思维导图
② 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)

# 漏洞挖掘 # 提权 # 漏洞利用 # 绕过
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者