메모리 손상 취약점은 사이버 보안에서 중요한 이슈 중 하나이다. 특히 Use-After-Free(UAF) 취약점은 지속적으로 발견되며, 많은 보안 사고의 원인이 되고 있다. 이번에는 UAF취약점의 원리와 Heap Spray 기법을 살펴보겠습니다.
UAF는 프로그램이 메모리에서 해제된 객체를 참조하려고 시도할 때 발생하는 메모리 취약점이다. 이 취약점은 주로 C, C++과 같은 수동 메모리 관리 언어에서 발생하며, 힙 영역에서 할당된 메모리를 free로 해제하고, 메모리를 다시 할당 시 같은 공간을 재사용하면서 생기는 문제이다.
UAF 취약점은 일반적으로 다음과 같은 과정으로 발생한다.
이 과정에서 해제된 메모리를 가리키는 포인터(Dangling Pointer)가 UAF 취약점의 핵심적인 원리가 된다. 해제된 메모리를 참조하는 포인터가 남아 있는 상태에서 메모리를 재할당하거나 악성 데이터를 주입해 프로그램의 동작을 조작할 수 잇다.
Object *obj = (Object *)malloc(sizeof(Object));
obj->
Method();
free(obj); //obj는 이제 dangling pointer가 된다.
위 코드에서 obj 포인터는 메모리가 해제된 후에도 여전히 해제된 메모리 주소를 가리키고 있다. 이러한 포인터를 Dangling Pointer라고 한다.
공격자가 HeapSpray와 같은 기법을 사용하면, 해제된 메모리 공간이 재할당될 때 해당 공간을 공격자의 데이터로 채울 수 있다.
HeapSpray(); // 공격자의 코드로 힙을 채움
obj->
Method(); // 이제 obj는 공격자가 제어하는 메모리를 가리킴
프로그램이 Dangling Pointer를 통해 해제된 메모리에 접근할 때, 이미 공격자가 해당 메모리에 심어둔 악의적인 데이터를 사용하게 된다. 이를 통해 공격자는 프로그램의 실행 흐름을 변경하거나 임의 코드를 실행할 수 있다.
#include <stdlib.h>
int main() {
int *ptr = (int*)malloc(sizeof(int)); // 메모리를 동적으로 할당
free(ptr); // 할당받은 메모리 해제
*ptr = 10; // 이미 해제된 메모리를 참조하여 값을 할당
return 0;
}
위 코드는 메모리를 할당하고 해제한 후에도 해당 메모리를 계속 사용하려고 시도하고 있다. 이는 전형적인 UAF 취약점 사례이다.
위 코드를 안전하게 수정하면 다음과 같다:
#include <stdlib.h>
int main() {
int *ptr = (int*)malloc(sizeof(int)); // 메모리를 동적으로 할당
if (ptr != NULL) {
free(ptr); // 할당받은 메모리 해제
ptr = NULL; // 포인터를 NULL로 설정
}
return 0;
}
이 방식은 메모리 해제 후 포인터를 NULL로 설정하여 해제된 메모리 영역을 더 이상 가리키지 않도록 하여 잘못된 메모리 접근을 방지한다.
Heap Spray는 공격자가 특정 메모리 주소에 데이터를 반복적으로 기록하여 대상 프로세스의 힙 메모리 영역을 채우는 악용 기술이다. 이 기술은 UAF와 같은 취약점 공격의 성공률을 높이는 데 자주 사용된다. 스프레이 라는 단어에서 느낄 수 있듯이 힙 메모리 영역을 모두 채우는 방법이다.
Heap Spray는 보안 취약점을 직접 악용하는 기법이라기 보다는, 기존의 취약성을 이용한 공격 성공률을 높이는 데 사용되는 기술이다. 힙 스프레이 기법은 다음과 같은 원리로 동작한다.
var tag = unescape('%u6548%u7061%u5320%u7270%u7961');
var nop = unescape('%u9090%u9090');
var headersize = 20;
var slack = headersize + tag.length;
while(nop.length < slack) nop += nop;
var filter = nop.substring(0, slack);
var chunk = nop.substring(0, nop.legnth - slack);
while(chunk.length + slack < 0x40000) chunk = chunk + chunk + filter;
var chunk_Array = new Array();
for (index = 0; index < 500; index++) {
chunk_Array[index] = chunk + tag;
}
이 코드는 힙 메모리에 NOP 슬라이드와 함께 특정 태그를 반복적으로 할당하여 Heap Spray를 시도하고 있다.
UAF 취약점과 Heap Spray 기법을 결합한 공격 시나리오는 다음과 같다.
UAF취약점과 밀접한 관련이 있는 것이 Double Free 취약점이다. Double Free는 동일한 힙 메모리 공간에 대해 메모리 해제를 2번 시도하여 발생하는 취약점이다. 이 두 취약점은 모두 힙 메모리 관리와 관련된 문제로, 함께 고려되는 경우가 많다.