Software Exploit and Kernel Protection KAIST CySec Lab
Content Kernel Background Software Attack and Defense History Practice
Kernel Background
What is kernel 컴퓨터 애플리케이션과 하드웨어 사이에 중간자 역할을 하는 프로그램 주요 기능 애플리케이션 제어 processor 자원 할당 Momory 애플리케이션-유저 인터페이스 System call
List of core kernel systems Kernel Entrance System call table, device driver Process Scheduler(Context switch), interrupt, Process Control Block(PCB) Memory Virtual memory, page allocator Storage Virtual file system Network Socket
Kernel Entrance System call System call table 커널 혹은 IO장치를 대상으로 요청을 위한 인터페이스 x86 아키텍쳐에서는 int 0x80 명령어 또는 systenter 명령어로 발 생 System call이 발생하게 되면 커널에 존재하는 시스템콜 진입지 점로 실행흐름이 변경 시스템콜 핸들러 루틴은 커널에서 코드가 동작할 준비를 함과 동시에 user level에서 요청한 시스템 서비스를 system call table 을 참조하여 요청에 대응한 시스템콜 핸들러 호출 System call table 시스템 콜 핸들러의 주소를 가지고 있는 배열 예, open(), write(), send(), recv(), mmap() 등
Kernel Privilege and Modes Kernel/User mode CPU에 의해 현재 동작상태가 kernel/user mode인지 구분됨 Intel x86의 경우 일부 명령어(int/iret, sysenter/sysexit)가 수행될 때 mode가 바뀜
Process & Security Buffer Overflow/DEP, Stack Cookie SEH Overwrite/SEHOP, SafeSEH Heap Overflow, Use After Free(UAF)/ DEP Return Oriented Programming/ASLR
Process Control Block 커널이 process를 관리하기 위한 구조체 Process id Process state Address space for the process Registers Scheduling information(우선순위,, CPU점유 시간) 마지막 실행 시 간 I/O information 등 Process 구조체에는 중요한 정보들이 많기 때문에 변조될 경우 심각한 문제가 발생할 수도 있음 (uid를 변경할 경우 일반user권한 process가 root process가 되기도 함)
Process Control Block linux task_struct state thread_info … mm tty thread fs files signal mm_struct fs_struct files_struct signal_struct task_struct
Memory Management 프로세스(프로그램) 메모리 레이아웃 각 프로세스마다 4G byte의 논리 주소 할당 (32bit OS 경우) code stack data Virtual address space Kernel Physical address space Process B Virtual address space code stack data Kernel 0x00000000 0xFFFFFFFF 0xC0000000 3G byte 1G byte Kernel Process A
Memory Address Translation (Paging) 가상주소-물리주소 메모리 변환 31 22 21 12 11 Directory Table Offset 가상 주소 12 Page Page Table 10 Page Directory 10 물리주소 PTE 20 PDE 20 32 CR3
Memory Address Translation (Paging) 0x40010040가상주소에 해당하는 물리주소 0100000000 0000010000 000001000000 0x040 물리주소 0x80000040 256 16 index address 256 0x0000C000 128 0x0000A000 0x00008000 index address 32 0x50000000 16 0x40000000 0x00008000 index address 32 0x90000000 16 0x80000000 0x00008000 Page Directory Page Table (0x0000A000) Page Table (0x0000C000)
Page Table Entry Page Table Entry P(Present) : whether this page exist in memory R/W(Read/Write) : Read-only(0), Read/Write(1) U/S(User/Supervisor) : Only Ring0 Accessible (0), Ring0,Ring3 Accessible (1) PWT(Page-Level Write-Through),PCD(Page-Level Cache-Disable) , G: Cache Policy A(Accessed) : Set when the page was last used D(Dirty) : whether the page has been written PAT(Page Attribute Type) : Set when assign memory type Address of page frame G PAT D A PCD PWT U/ S R/W P 31 12 8 7 6 5 4 3 2 1
Kernel Memory Protection 프로세스 내 메모리 관리 code 영역만 실행권한 data, heap, stack 실행권한 없음
Kernel Memory Protection 프로세스 간 메모리 격리 프로세스 별로 다른 Page Directory/Table을 참조하기 때문에 다 른 프로세스 영역 메모리 접근 불가 User 프로세스에서 Kernel 메모리 접근 불가 Kernel이 위치한 메모리 영역에 해당하는 Page Table Entry에는 Supervisor bit 상태로 되어 있기 때문에 User 프로세스에서는 접 근 불가
Software Attack & Defense
Eternal War in Memory Overview [RAID `12 Veen]
History Attack & Defense Attack Defense Buffer(Stack/Heap) Overflow Stack Canary, NX Return Oriented Programming (ROP) Address Space Layout Randomization (ASLR)
Attack: Buffer(Stack) Overflow 개요 프로그램에서 사용하는 외부 입력값 혹은 데이터의 길이 제한이 없을 경우 버퍼크기보다 큰 입력값을 통하여 프로그램 흐름을 변경하는 공격 예) strcat, strcmp, strcpy같은 취약한 함수 char *strcpy(char *dest, const char *src) //vuln.c int main(int argc, char *argv[]) { char buff[40]; strcpy(buff, argv[1]); } RET EBP Buff[40] 0xbfffff00 0xbfffff30 Attack Code 0xbfffff00
Defense: Stack Canary 개요 프로그램 실행 시 난수로 Canary값을 생성하여 저장해 놓았다가 함수가 Return 되기 전 return 값과 Canary값을 비교하여 다를 경 우 예외 발생 Compiler에 적용된 기술 (Default) Windows : Stack Cookie, Linux : Canary Buff[40] Attack Code Canary Saved Canary Saved Frame Pointer ret
Defense: NX (No-eXecute) 개요 데이터(스택, 힙) 메모리 영역에 실행권한을 삭제함으로써, input 과 같은 데이터가 실행되는 것을 방지 Windows : DEP(Data Execute Prevention) Linux : Exec Shield, PaX Attack Code 0xbfffff00 Buff[40] Read, Write, No-eXecute Saved Frame Pointer ret
Attack: Return-Oriented Programming (ROP) 개요 데이터영역(Stack, Heap)에 실행하고자 하는 코드를 넣는 것이 아니라 이미 존재하는 코드를 이용할 수 있는 Control Data를 통 해 원하고자 하는 프로그램을 수행하는 기법
Return-Oriented Programming (ROP) Stack Code Actions [0x400000] = 1+2 0xb8800000 0x00000001 0xb8800010 0x00000002 0xb8800020 0x00400000 0xb8800030 0xb8800000: pop eax ret ... 0xb8800010: pop ebx 0xb8800020: add eax, ebx 0xb8800030: mov [ebx], eax esp eax = 1 ebx = 2 eax += ebx ebx = 0x400000 *ebx = eax [Oakland `12 IPR]
Defense: Address Layout Randomization 개요 ROP를 통하여 코드를 재사용 하지 못하게 하기 위해 프로그램 실행시마다 Library 및 data(stack,heap) 위치가 변하도록 하는 기 술
Window & Linux Protection Memory Protection Windows Linux XP sp2,sp3 2003 sp1, sp2 Vista sp0 Vista sp1 Window 7 Stack Cookie O DEP X ASLR Ret Hat 9.0 Fedora 11 Fedora 12 Ubuntu 9.0.4 Ubuntu 9.10 Canary X O NX ASLR
Is the Memory-War Over Yet? ASLR ASLR은 완벽하게 공격을 방어할 수 있는 기술이 아님. 32bit의 경우 entropy가 작아서 brute force에 의해 우회가능 ASLR이 적용되지 않는 영역이 존재함 program의 code영역 및 특정 library Memory Leak에 의해 library의 위치를 알아낼 수 있음 Eternal War in Memory!
HW: Practice
Goal 사용자계정에서 root권한을 획득한 뒤 /home/sk/Workspace/password 파일 읽기 계정정보 공격방법 암호 : p4ssword 공격방법 BufferOverflow 취약점이 존재하는 root소유의 vuln 프로그램을 공격 vuln 프로그램의 소스코드는 vuln.c에 있음
Vuln.c void vuln(char *input){ char buff[40]; strcpy(buff, input); printf("showing message : %s\n",buff); } int main(int argc, char *argv[]){ if(argc!=2){ printf("Usage: %s [Message] argcount: %d\n",argv[0], argc); return 0; vuln(argv[1]);
x86 Register X86 레지스터 다음에 실행할 명령어 위치 : EIP 일반 : EAX, EBX, ECX, EDX 인덱스 : ESI, EDI 스택 : EBP, ESP 낮은주소 ESP→ 지역 변수 (buff[40]) EBP→ Vuln 함수 stack frame Saved EBP Saved RET main main 함수 stack frame 높은주소
x86 instruction 주요 명령어 명령어 표기(intel) 동작 push push reg esp = esp-4, [esp] = reg pop pop reg reg = [esp] mov mov dest, src dest = src lea lead dest, src lea = src의 주소 call call 주소 주소에 있는 함수호출 ret 함수복귀 leave esp = ebp jmp jmp 주소 실행흐름 주소로 이동
Call Convention main함수에서 vuln(arg1, arg2, arg3)함수를 호출할 때 stack 구조 낮은주소 EIP → push arg3 지역 변수 (buff[40]) push arg2 push arg1 EBP→ Saved EBP call vuln Saved RET arg1 EIP → push ebp arg2 mov ebp, esp arg3 ⁞ ESP→ main leave ret EBP→ 높은주소
GDB GNU 디버거 사용방법 : gdb [프로그램] 명령어 Set disassembly-flavor (intel|att) : 디스어셈블 표현 설정 r (un) [parameter] : 프로그램 실행 disas 함수이름 : 함수 disassemble b(reak) 함수이름 or b 0x주소 : 브레이크 포인트 설정 c(ontinue) : 멈춘 지점부터 프로그램 다시 진행 Si, ni, : 한줄씩 명령어 실행 i(nfo) r(egister) : 현재 시점의 register 상태 보기 x/4x [주소], x/10i [주소]: 지정된 주소부터 메모리 상태 보기 숫자 : 지정된 주소부터 살펴보고자 하는 개수 x or i : x일 경우 메모리 내용 16진수로 표현, i일 경우 명령어로 표현 GDB내 스크립트 사용 가능 : r AAAAAAAAAAAAAAAAAAAAFFFFFFFF r `python –c ‘print “A*16”+”\xFF\xFF\xFF\xFF”’`
Practice 공격순서 vuln.c 소스코드 살펴보고 취약점 발생위치 확인 gdb로 vuln 프로그램 분석 (1) 입력값을 변화시켜 가면서 입력값이 프로그램 흐름에 영향을 미치 는 길이 확인 완전히 프로그램 흐름을 임의로 조작할 수 있는 상태 공격자의 원하는 코드 준비 (쉘: 명령어 입력 대기창 실행 프로 그램) (2) 미리 만들어둔 ./eggshell 을 실행시키면 메모리에 공격코드를 위치 시키고 공격코드가 있는 주소를 알려줌 (1)에 사용할 입력값 중 ret을 덮어쓸 부분에 (2)에서 알려준 주소 를 사용함 Password파일 읽기
Linux Security Features Canary 활성화 : 기본, 비활성화 : gcc –fno-stack-protector NX 활성화 : 기본, 비활성화 : gcc -z execstack ASLR (/proc/sys/kernel/randomize_va_ space) 활성화 Sysctl –w kernel.randomize_va_space=1 (라이브러리, 스택) Sysctl –w Kernel.randomize_va_space=2 (기본, 라이브러리, 힙, 스택) 비활성화 : sysctl –w kernel.randomize_va_space=0