Use After Free
오늘 다뤄볼 취약점은 Use After Free입니다.
말 그대로 사용한 후 메모리를 해제했을 때에 취약점을 발견할 수도 없을 수도 있을 수도 있습니다.
이 취약점은 근래에 브라우저 취약점에서 많이 발견되었습니다.
[CVE-2012-4792 IE Use-After-Free Analysis and Exploit]
- http://pgnsc.tistory.com/348
멋쟁이 sweetchip님의 BoB 프로젝트 도중에 그 당시에 문서로 남겨놓으셨습니다!
이러한 UAF 취약점은 스택 영역에서 이루어지는 취약점이 아닌 힙 영역에서 발생하는 취약점입니다.
What is Heap?
출처 : https://namu.wiki/w/%EC%98%A4%EC%A6%88%EB%9E%9C%EB%93%9C
Heap은 프로그래머가 필요에 따라 메모리 공간이 동적 할당/소멸되는 영역입니다.
하지만 스택은 힙과는 달리 정적으로 할당이 되기 때문에 컴파일 시 미리 스택에 공간이 할당이 되어있습니다.
예를 들자면 아래와 같습니다.
0x08048510 <+0>: push ebp
0x08048511 <+1>: mov ebp, esp
0x08048513 <+3>: sub esp, 0x120
위의 어셈 코드와 같이 0x120(288)만큼 할당하는 코드를 볼 수 있듯이 스택은 컴파일할 때에 할당되는 영역입니다.
하지만 힙은 런타임 시 할당되는 유용하게 사용되는 공간입니다.
이 영역은 시작과 동시에 메모리에 올라고 프로그램이 종료될때까지 남아있습니다.
이러한 힙 영역을 사용하기 위해서는 동적할당에 대해 알아두어야됩니다.
info malloc !
흔히 C언어로 코딩 좀 해봤다 싶으면 봤을 듯한 함수인 malloc입니다.
이 malloc 함수는 동적으로 메모리를 할당하는 함수로서 아래와 같이 생겨먹었습니다.
void* malloc(size_t size)
함수를 호출 시 할당하고자 하는 메모리의 크기를 인자에 전달하면 그 크기만큼 메모리를 할당하게 되고 그리고 그 할당한 메모리의 주소를 리턴하게 됩니다.
메모리에 할당에 실패하면 NULL을 리턴하게 됩니다.
Eh? return type is void* ??
Hell o malloc
INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
할당을 하게 되면 이와 같은 구조를 가지고 있습니다.
prev_size 필드에는 free가 된 이전의 chunk의 사이즈를 가지고 있습니다.
size 필드에는 할당된 사이즈를 담고 있는데.
x86 아키텍처에서는 최소 4바이트 만큼의 공간이 필요합니다.
각 필드들은 8바이트 단위로 정렬이 되서 실제 크기는 더 커질 수 있습니다.
그리고 size 필드에는 3가지의 플래그가 있습니다.
P 플래그는 PREV_INUSE로 이전 chunk가 사용 여부를 나타내는 녀석입니다.
이 플래그가 지워져있으면 free chunk라는 의미가 됩니다.
N 플래그는 NON_MAIN_ARENA로 멀티 쓰레드로 돌아가는 프로그램에서 쓰레드마다 다른 힙 영역을 사용하는 경우
현재 chunk가 main 힙에 속하는지 여부를 나타냅니다.
M 플래그는 IS_MMAPPED로 해당 필드가 mmap()으로 할당된 것인지 아닌지를 나타냅니다.
mmap()으로 할당된 chunk는 malloc과는 다른 방식으로 메모리를 관리합니다.
#define PREV_INUSE 0x1
#define IS_MMAPPED 0x2
#define NON_MAIN_ARENA 0x4
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED|NON_MAIN_ARENA)
#define chunksize(p) ((p)->size & ~(SIZE_BITS))
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
Yeah Use After Free!
one에 입력한 내용이 two에도 출력이 되고 one 주소와 two의 주소가 같음을 볼 수 있습니다.
왜 이럴까요?
Why?
malloc의 caching 때문이다.
출처 : http://g.oswego.edu/dl/html/malloc.html
caching 기능의 Deferred Coalescing이 있는데.
free를 하더라도 chunk를 정리하는 것보다는 같은 사이즈로 요청을 받을 때에 병합또는 분할하는 시간을 절약하고자 재활용을 하게 해주는 것입니다.
출처 : 아는 동생의 중고거래 (무려 어제 있었던 일이다)
disas GDB
그리고 free한 뒤에 two를 malloc을 하게 됩니다.
free할 때에 재사용할 힙 공간이 처음에 사용한 0x804b008만 있기 때문에 자연스레 처음에 사용한 힙이 재사용되면서 전에 입력한 값이 출력이 되게 됩니다.
Use After Free in sample program
Scenario
먼저 사용을 하고 free를 해야 다시 할당을 할 때에 다시 그 공간을 사용하게 해야됩니다.
vuln의 id 값이 400보다 크면 id가 크다는 문자열을 띄워주면서 cleanMem을 실행하면서 vuln을 free를 해주게 됩니다.
그 다음에 vuln과 같은 크기로 vuln_tst을 할당하고 strcpy로 인자를 vuln_tst에 복사를 한 뒤에 vuln_tst를 free를 해주고 이미 free되있는 vuln을 호출하게 됩니다.
먼저 이에 대해서는 vuln과 vuln_tst은 같은 주소를 가르키고 있고, vuln_tst에 값을 크기 상관없이 조져버릴 수 있습니다.
그렇게 조져버린 메모리를 끝에서 호출을 하기 때문에 우리는 eip 주작질이 가능하게 됩니다.
Exploit
먼저 vuln의 clean이 어디에 위치해있는지를 알아봅니다.
그렇다면 clean은 24만큼 떨어진 곳에 있습니다.
이렇게 이후에 eip를 주작질을 할 수 있음을 볼 수 있습니다.
그 뒤로는 휘리릭 뾰로롱 하면 쉘이 따집니다.
넵, 안녕 !
길고 긴 글을 읽으시느라 수고하셨습니다.
'0x20 Security > 0x21 System' 카테고리의 다른 글
Buffer Overflow (BOF) (2) | 2016.07.22 |
---|---|
About LD_PRELOAD (0) | 2016.07.20 |
How main() is executed on linux (2) | 2016.07.04 |
System Hacking :: Memory Protection (0) | 2016.06.28 |
[SSA] 시스템 해킹 스터디 6주차 (349) | 2015.11.09 |