Dig into Netfilter (五) —— CVE-2022-32250

CVE-2022-32250

漏洞分析

完整的表达式析构过程 / nft_set_binding

一些规则可以与集合绑定, 但其实真正绑定的是表达式和集合, 这类表达式有nft_lookup, nft_dynset, nft_objref.

代表这一关系的结构是nft_set_binding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* struct nft_set_binding - nf_tables set binding
*
* @list: set bindings list node
* @chain: chain containing the rule bound to the set
* @flags: set action flags
*
* A set binding contains all information necessary for validation
* of new elements added to a bound set.
*/
struct nft_set_binding {
struct list_head list;
const struct nft_chain *chain;
u32 flags;
};
阅读更多...

Dig into Netfilter (四) —— CVE-2022-34918

CVE-2022-34918

漏洞分析

在nft_set_elem_init函数中, 有几处使用memcpy的地方让人眼前一亮.
众所周知审溢出就是审读写时使用的大小是否小于等于分配内存时使用的大小.

但这几处分配空间使用的是tmpl->len, 而写入的长度是(set->klen + set->klen + set->dlen) (对应属性都存在的情况下), 这促使我们向上回溯看看这些值之间是否存在上述小于等于的关系.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void *nft_set_elem_init(const struct nft_set *set,
const struct nft_set_ext_tmpl *tmpl,
const u32 *key, const u32 *key_end,
const u32 *data, u64 timeout, u64 expiration, gfp_t gfp)
{
struct nft_set_ext *ext;
void *elem;

elem = kzalloc(set->ops->elemsize + tmpl->len, gfp);
if (elem == NULL)
return NULL;

ext = nft_set_elem_ext(set, elem);
nft_set_ext_init(ext, tmpl);

if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY))
memcpy(nft_set_ext_key(ext), key, set->klen);
if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END))
memcpy(nft_set_ext_key_end(ext), key_end, set->klen);
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
memcpy(nft_set_ext_data(ext), data, set->dlen);
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
*nft_set_ext_expiration(ext) = get_jiffies_64() + expiration;
if (expiration == 0)
*nft_set_ext_expiration(ext) += timeout;
}
if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
*nft_set_ext_timeout(ext) = timeout;

return elem;
}
阅读更多...

Dig into Netfilter (三) —— CVE-2022-1972 / CVE-2022-2078

新增集合

在nf_tables中, 还有一个set的概念. 虽然nf_tables没有使用iptables的match-action的概念, 但作为filter就少不了match的过程. set充当一个数据库, 而nft_lookup等指令用来在数据库中进行查找.

比如想要拦截192.168.1.4, 192.168.1.5等ip的包, 则可以通过如下方式创建命名集合(当然就有匿名集合)blackhole, 并向其中添加ip, 之后的rule即可直接使用这个set.

1
2
3
nft add set filter blackhole { type ipv4_addr\;}
nft add element filter blackhole { 192.168.1.4, 192.168.1.5 }
nft add rule ip input ip saddr @blackhole drop
阅读更多...

Dig into Netfilter (二) —— CVE-2022-1015 / CVE-2022-1016

CVE-2022-1016

源码版本为v5.17-rc7.

非常明显且诡异地存在了8年的一个漏洞: 状态机的regs没有初始化.攻击者可以通过该漏洞泄露内核基址.
作者的评价:

I have no idea how this survived for eight and a half years, because to me it stuck out like a sore thumb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unsigned int
nft_do_chain(struct nft_pktinfo *pkt, void *priv)
{
const struct nft_chain *chain = priv, *basechain = chain;
const struct nft_rule_dp *rule, *last_rule;
const struct net *net = nft_net(pkt);
const struct nft_expr *expr, *last;
struct nft_regs regs;
unsigned int stackptr = 0;
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
bool genbit = READ_ONCE(net->nft.gencursor);
struct nft_rule_blob *blob;
struct nft_traceinfo info;

阅读更多...

Dig into Netfilter (一) —— nf_tables核心概念

xtables? iptables? nf_tables !

nf_tables核心概念

源码版本为v5.8或v5.11

概述

根据作用及协议族, 在netfilter中分成不同的table., 每个table只能看到自己所属协议族的包.
每个table在其有的每一个hook点上有一条chain. 用户也可以添加自定义的chain, 但由于没有对应的hook点, 只能从内置的chain的rule中跳转到(其实从自定义的chain跳转到也行, 前提是前者能被触发). 实际上之前内置chain的说法并不准确, 不同于iptables, nft并不存在预定义的chain, 需要创建nft_base_chain并将其注册到hook点上.
多条rule可能在同一个hook点触发, 即属于同一条chain.
处理一条rule的过程实际是对rule中包含的expr求值(eval).

阅读更多...

Linux内核 KSM机制 -- ARM64 v5.0

(看源码看得最难受的一集)

Question

  • KSM机制的流程?
  • 如何理解KSM机制中的数据结构?

KSM概述

KSM指Kernel SamePage Merging,即内核同页合并,用于合
并内容相同的页面。KSM的出现是为了优化虚拟化中产生的冗余页面,
因为虚拟化的实际应用中在同一台主机上会有许多相同的操作系统和
应用程序,许多内存页面的内容可能是相同的,所以它们可以合并,
从而释放内存供其他应用程序使用。

KSM允许合并同一个进程或不同进程之间内容相同的匿名页面,这
对应用程序来说是不可见的。把这些相同的页面合并成一个只读的页
面,从而释放出多余的物理页面,当应用程序需要改变页面内容时,
会发生写时复制。

阅读更多...
  • Copyrights © 2022-2024 翰青HanQi

请我喝杯咖啡吧~

支付宝
微信