Buffer Overflow Chap 10. Buffer Overflow a very common attack mechanism 1988 년 the Morris Worm 가처음사용한방법 버퍼에저장되는데이터의크기를검사하지않는, 프로그램의부주의한점을이용 prevention techniques 이알려져있음 여전히많은관심대상임 널리배포되어사용중인운영체제와응용프로그램에이러한버그가있는코드가존재함 Shellshock bashdoor. bash shell의취약성. 2014년에발견 Hearthbleed OpenSSL 의취약성. 2014 년발견 프로그래머의부주의한습관이여전히계속됨 2 History of Buffer Overflow Attacks Buffer Overflow/Buffer Overrun A buffer overflow (buffer overrun 이라고도함 ) NIST 에서다음과같이정의됨. A condition at an interface under which more input can be placed into a buffer or data holding area than the capacity allocated, overwriting other information. Attackers exploit such a condition to crash a system or to insert specially crafted code that allows them to gain control of the system. http://insecure.org/stf/smashstack.html 3 4
Buffer Overflow Basics Basic Buffer Overflow Example Buffer overflow programming error 프로세스가 fixed-sized buffer의제한을넘어서서데이터를저장하고자하는경우에발생 인접메모리위치에대한 overwrites 이위치에 program variables, parameters, or program control flow data가있을수있음 버퍼는프로세스의 stack, heap 또는 data section에위치 buffer overflow의결과 프로그램데이터손상 예상치못한프로그램실행흐름 (control transfer) 메모리접근위반 (violations) 공격자가선택한코드실행 주소증가방향 str1 str2 gets() 8 8 5 6 Buffer Overflow Attacks $ cc -g -o buf1 buf1.c $./buf1 abcdefg str2 = abcdefg / str1 = 1234567 $./buf1 abcdefgabc str2 = abcdefgabc / str1 = BC $./buf1 abcdefgabcdefgh1234567890 str2 = abcdefgabcdefgh1234567890 / str1 = BCDEFGH1234567890 $./buf1 abcdefgabcdefgh123456789012345 str2 = abcdefgabcdefgh123456789012345 / str1 = BCDEFGH123456789012345 세그멘테이션오류 공격자가 buffer overflow 공격을하기위해필요한작업 공격자가외부에서유입한데이터를사용하여동작시킬수있는프로그램에서 buffer overflow 취약을찾아내야함 버퍼가메모리에서저장되는방법을알아내어손상가능성을판단함 취약한프로그램의식별방법 프로그램소스코드분석 프로그램을실행하여초과된입력이어떻게처리되는지확인 취약한프로그램을식별하는도구사용 - fuzzing case 1: 길이 < 8 str1 내용불변 case 2: 8 길이 16 str1 내용변경 case 3: 길이 > 16 str1 내용전부변경, 다른곳에영향 7 8
Programming Language History 기계수준에서, 기계어에의해서처리된데이터는프로세서의레지스터또는메모리에저장됨 어셈블리언어프로그래머는저장된데이터에대한올바른해석을책임짐 현대고급언어는변수의자료형과수행가능한연산에대한강력한개념을갖고있음 buffer overflow 에취약하지않음 오버헤드존재, 약간의사용상제약 C 및관련언어는고급제어구조를갖고있지만메모리에대한직접접근허용 buffer overflow 에취약 전통적인코드에서널리사용됨 unsafe 하고취약한코드 Stack Buffer Overflows 버퍼가 stack 에위치할때에발생 stack smashing 이라고도함 검사되지않는 buffer overflow를이용하여공격 취약점공격에여전히널리이용됨 stack frame 함수마다 stack 에자신의 stack frame 공간을사용 용도 함수에서다른함수를호출할때에 return address 저장공간 호출하는함수로 parameter 들을전달하기위한저장공간 레지스터값임시저장공간 frame pointer: 현재함수의 stack frame 의기준위치를저장하는레지스터 9 10 Stack Frame with Functions P and Q 함수 P에서함수 Q를호출할때에 stack frame 구성 1. parameter들을 push 대개역순으로전달 2. 함수 Q를호출할때에 return address 저장 3. 현재의 frame pointer 저장 FP는현재의 SP로변경 4. local variable용공간확보 필요공간크기만큼 stack pointer 감소 5. 함수 Q 의 body 실행 buffer overflow 는 return address 와 frame pointer 를변경시킬수있음 Programs and Processes 메모리에 process 용공간배치 x 11 12
Classic Stack Overflow Classic Stack Overflow 입력에이진문자열을간단히제공하기위하여 perl 의 pack 함수사용가능 16 글자미만의이름 긴이름 13 14 Classic stack overflow (Stack) Stack Overflow Example buffer overflow 방지를위해 gets 대신에 fgets 사용 tmp 버퍼에두문자열이결합되어저장 tmp 에서 buffer overflow 가능 15 16
Stack Overflow Example (run) Common Unsafe C Standard Library Routines gets(char *str) sprintf(char *str, char *format,...) strcat(char *dest, char *src) strcpy(char *dest, char *src) vsprintf(char *str, char *fmt, va_list ap) read line from standard input into str create str according to supplied format and variables append contents of string src to string dest copy contents of string src to string dest create str according to supplied format and variables unsafe library functions str 또는 dest 가가리키는 buffer 의크기를확인하지않음 buffer overflow 발생가능 17 18 Shellcode Example Shellcode 공격자가제공하는코드 buffer overflow 가가능한버퍼에코드를저장 프로그램의제어를저장된공격자코드로전달하게함 대개공격자코드는 command line interpreter (shell) 을실행시키는기능을갖고있음 shellcode라고부름 machine code 프로세서, 운영체제에따라다름 공격코드를만들기위해서는어셈블리언어에대한이해가필요 최근에는이러한과정을자동화하는사이트와도구들이개발됨 Metasploit Project 침투 (penetration), IDS 서명개발, exploit( 악용 ) 연구를수행하는사람들에게유용한정보제공 https://www.metasploit.com/ Bourne shell 을실행하는 shellcode execve 함수를사용하여현재프로세스를 /bin/sh 프로그램으로변경하여실행 위치독립코드 shellcode 로사용하기위해서는 position-independent 해야함 shellcode 가적재되는위치를미리알수없기때문 19 20
- Position independent x86 assembly code Common x86 Assembly Language Instructions MOV src, dest LEA src, dest ADD / SUB src, dest AND / OR / XOR src, dest CMP val1, val2 JMP / JZ / JNZ addr PUSH src POP dest CALL addr LEAVE RET INT num NOP copy (move) value from src into dest copy the address (load effective address) of src into dest add / sub value in src from dest leaving result in dest logical and / or / xor value in src with dest leaving result in dest compare val1 and val2, setting CPU flags as a result jump / if zero / if not zero to addr push the value in src onto the stack pop the value on the top of the stack into dest call function at addr clean up stack frame before leaving function return from function software interrupt to access operating system function no operation or do nothing instruction 21 22 x86 Registers 32 bit 16 bit 8 bit 8 bit Use (high) (low) %eax %ax %ah %al Accumulators used for arithmetical and I/O operations and execute interrupt calls %ebx %bx %bh %bl Base registers used to access memory, pass system call arguments and return values %ecx %cx %ch %cl Counter registers %edx %dx %dh %dl Data registers used for arithmeticoperations, interrupt calls and IO operations %ebp Base Pointer containing the address of the current stack frame %eip Instruction Pointer or Program Counter containing the address of the next instruction to be executed %esi Source Index register used as a pointer for string or array operations %esp Stack Pointer containing the address of the top of stack shellcode JMP/CALL 속임수이용하여문자열 ("/bin/sh") 주소를 %esi에저장 문자열끝에널문자복사 %eax를 0으로만들고, %al을문자열끝에복사 ( 널문자 ) 문자열주소를 arg[0] 에저장 : 0x8(%esi) arg[1] 값을 0 (NULL) 로만듬 : %eax를 0xc(%esi) 에복사 execve 시스템호출 parameter 준비 system call 번호 11 : %al 첫째인수 (sh) : %ebx %esi 둘째인수 (args) : %ecx 0x8(%esi) 주소 셋째인수 (NULL) : %edx 0xC(%esi) 주소 시스템호출 : int $0x80 23 24
Stack Overflow Attack Stack Overflow Variants 공격 target program a trusted system utility network service daemon commonly used library code shellcode 기능 접속할때에 remote shell 실행 공격자에게역으로접속하는 reverse shell 생성 shell 을만드는 local exploits 사용 현재다른공격을막고있는 firewall rules 무효화 chroot (restricted execution) 환경을깨서, 시스템에대한완전접근권한주기 25 26 Buffer Overflow Defenses Compile-Time Defenses: Programming Language buffer overflows 가널리이용됨 두가지방어방법 compile-time 방어 새로운프로그램에서공격을막을수있도록강화하는것을목표로함 run-time 방어 기존의프로그램에서공격을탐지하고중지시키는것을목표로함 프로그래밍언어선택 현대고급언어사용 buffer overflow 공격에취약하지않음 compiler 가범위검사를시행하고, 변수에대해서허용되는연산에대해서알고있음. 단점 실행시간에검사를하기위한코드가추가되어야함 융통성 (flexibility) 와안정성 (safety) 는자원사용면에서비용이듬 기계어와컴퓨터구조에서멀어질수록 ( 고급언어 ) 는일부명령어와하드웨어자원에대한접근을못하게됨 장치드라이버와같은일부코드를작성할때에제약이있음 27 28
Compile-Time Defenses: Safe Coding Techniques Examples of Unsafe C Code C 언어를사용하는설계자는 자료형의 safety 보다는공간효율성과성능을더강조 프로그래머가코드작성에주의를기울일책임있다고가정 프로그래머는코드를검사하여, unsafe 코드를다시작성하는것이필요함 ( 예 ) OpenBSD project 프로그래머는운영체제, 표준라이브러리, 공통유틸리티를포함한기존코드기반을감사함 (audit) 이결과가장안전한운영체제중하나로평가됨 to 버퍼의크기를알지못함 pos+len (to 버퍼의크기 ) 이어야함 29 30 Compile-Time Defenses: Language Extensions / Safe Libraries 버퍼참조범위검사루틴사용 정적할당배열에대해서는쉬움 동적할당배열 ( 메모리 ) 에대해서는컴파일시간에크기정보가없기때문에문제가있음 이를다루려면라이브러리루틴의확장및사용이필요 프로그램및라이브러리를다시컴파일해야함 타사응용프로그램에문제발생가능성 C 언어에대한우려는 unsafe 표준라이브러리루틴의사용에서나옴 안정성향상의한방법 - safe 루틴으로대체 ( 예 ) Libsafe: 복사연산이표준의미를구현하면서지역변수공간을넘어가지않도록검사 이전 stack frame 과 return 주소를보호 동적라이브러리로구현되며, 기존표준라이브러리에앞서적재됨 기존프로그램의재컴파일없이보호제공 Compile-Time Defenses: Stack Protection 함수에 entry 코드와 exit 코드를추가 스택프레임의손상여부검사 손상이발견되면프로그램종료 Safeguard canary 사용 entry 코드는이전 frame pointer 앞에 canary 저장 exit 코드는 canary 의변경여부검사 canary 값을예측하지못하게하기위해서 random 값사용 프로세스생성시에임의값을선택하여저장 Visual C++ 에서 /GS 옵션을사용하면이러한기능제공 단점 : stack frame 의구조가변경됨 ret addr old FP canary local vars 31 32
Run-Time Defenses: Executable Address Space Protection Stackshield 과 Return Address Defender (RAD) 스택프레임의구조를변경하지않고검사 GCC extensions entry 코드와 exit 코드를추가 함수 entry 코드는 return address 의복사본을안전한메모리영역에복사 함수 exit 코드는스택에있는 return address 와안전한영역에저장된값을비교 변경이발견되면즉시프로그램을종료시킴 ret addr old FP local vars copy 비교 저장공간 ret addr 가상주소지원사용 일부메모리영역을실행불가로지정 메모리관리장치의지원필요 SPARC/Solaris 시스템에서오랫동안사용 x86 Linux/Unix/Windows systems에서도최근에지원 executable stack code에대한지원문제 buffer overflow 공격을막기위해서 stack 과 heap 을실행불가로지정 just-in-time 컴파일러, 자바런타임시스템, 및리눅스시그널처리기는스택에실행코드를배치하므로, 실행불가능이아닌특별한방법이요구됨 33 34 Run-Time Defenses: Address Space Randomization 중요데이터구조의위치조작 스택, heap, 전역데이터 각프로세스에 random shift 사용 위치예측을어렵게함 프로그램이이용가능한주소공간을크지만, 작은부분만이용 이러한주소공간을넓게사용함 스택영역을 1 MB 정도이동하면프로그램에영향은적지만공격자가 target 주소를예측하는것을불가능하게함 heap 영역의버퍼와표준라이브러리함수의위치를 random 배치 Run-Time Defenses: Guard Pages guard page 프로세스주소공간에서메모리의중요영역사이에 guard 페이지를배치 불법적인주소는 MMU 에설정되어서이주소에대한접속시도는프로세스실행을종료시킴. guard page 의확장 스택프레임들사이와 heap 버퍼들사이에 guard page 배치 많은수의 page mapping 이필요하기때문에실행시간이낭비됨 35 36
Replacement Stack Frame Return to System Call buffer 와저장된 old frame pointer 주소를덮어쓰는방법 스택에저장된 old frame pointer는 dummy stack frame을참조하도록변경 ( 교체 ) 함 현재함수가교체된 dummy function으로 return됨 프로그램제어가 overwrite된 buffer에있는shellcode로전달됨 Off-by-one attacks coding 오류로가용공간보다 1바이트더많이복사했을때에 buffer overflow 발생 ( 조건검사에서 <, > 대신에 <=, >= 사용 ) buffer 바로위에 old frame pointer가있다면공격가능 Defenses 함수 exit 코드에서스택프레임또는 return address 변경을탐지하는스택보호방법사용 스택영역을실행불가영역으로지정 (non-executable stacks) 실행불가 stack 에대한공격 return address 를표준함수로변경 대개 system() 과같은함수의주소사용사용 공격자는 return address 위의스택에적절한 parameter 구성 함수가 return 하면라이브러리함수가실행됨 공격자는정확한버퍼주소를필요로함 두라이브러리함수를연속호출할수도있음 strcpy() 를사용하여 shellcode 를 stack 이아닌영역으로복사 복사된 shellcode를호출 Defenses 함수 exit 코드에서스택프레임또는 return address 의변경을탐지하는스택보호방법사용 non-executable stacks 사용 메모리에있는스택과시스템라이브러리를임의의위치에배치 37 38 Heap Overflow Example Heap Overflow Attack Heap 에있는버퍼에대한공격 대개프로그램코드와전역데이터위에배치 동적자료구조 ( 연결리스트등 ) 에서사용됨 메모리할당요청을받으면 heap 공간에서메모리할당 No return address 스택과달리 return address가저장되지않음 실행제어를이동시키기가어려움 function pointer를포함하는자료구조에대해서 function pointer 를이용한공격가능 Defenses heap을실행불가영역으로지정 random 메모리할당 39 40
Global Data Overflow 전역변수버퍼공격 전역데이터는프로그램코드위부분에위치함 function pointer 와 vulnerable buffer 가있다면공격가능 인접한 process management tables 을이용한공격 이테이블에있는나중에호출될 function pointer 값을변경 Defenses 실행불가영역지정 함수포인터를이동 다른영역아래위치 Guard pages 사용 전역데이터와관리영역사이에배치 41 42 Example Global Data Overflow Attack 43 44