Use After Free(UAF)
Use After Free(UAF)는 프로그램의 동적 메모리 관리 과정에서 발생하는 심각한 메모리 취약점으로, 메모리를 해제한 후에도 해당 메모리 공간을 계속 참조하면서 발생하는 오류입니다. 이로 인해 데이터 손상, 프로그램 크래시, 심지어 임의 코드 실행과 같은 보안상의 큰 문제가 발생할 수 있습니다🛡️.
Use After Free란 무엇인가? 💡
Use After Free(UAF)는 동적으로 할당된 메모리(Heap)를 free(해제) 한 뒤에도, 이전에 참조하던 포인터를 통해 그 영역을 사용하는 상황에서 발생합니다. 이러한 영역은 다른 데이터로 재할당 되어 있을 수 있으므로, 예기치 않은 동작이나 취약점의 원인이 됩니다.
발생 원리 및 메커니즘 🔍
동적 메모리(Heap)는 프로그램이 실행되는 동안 필요에 따라 공간을 할당합니다. 예시 코드를 보면 아래와 같이 UAF가 발생합니다:
#include <stdio.h>
int* heap1 = malloc(256);
free(heap1);
// 이후 heap1을 사용 -> UAF 취약점 발생
printf("%d\n", *heap1);
heap1이 가리키는 메모리가 이미 해제되었음에도 불구하고, 값을 읽거나 쓰게 되면 문제가 발생합니다. 이 공간이 다른 객체에 재할당되어 있다면, 의도치 않은 정보 노출이나 권한 상승이 가능합니다.
왜 위험한가? 🚨
- 데이터 손상: 해제된 메모리 공간이 재활용되어 새로운 데이터와 혼재될 수 있기 때문에, 데이터의 무결성이 깨질 수 있습니다.
- 프로그램 크래시: 잘못된 포인터 참조로 인해 Segmentation fault와 같은 치명적 오류가 발생할 수 있습니다.
- 임의 코드 실행 가능성: 공격자는 해당 영역을 조작해 원하는 코드를 실행시켜 시스템 권한을 탈취할 수도 있습니다.
실제 공격 사례 및 활용 🎯
대표적인 UAF 공격 사례로는 웹 브라우저 Exploit, OS 커널 취약점(CVE-2024-1086 등)이 있습니다. 해제된 함수 포인터 또는 객체 포인터가 그대로 남아 있을 경우, 공격자가 이 영역에 악성코드를 삽입해 실행하도록 유도할 수 있습니다.
- 브라우저 Heap Spray 기법과 병행되어 사용됨.
- 모바일/iOS의 checkm8, 시스템 펌웨어 업데이트 과정에서 UAF 활용.
- Linux Kernel의 CVE-2024-1086 취약점에서 UAF가 활용되어, 권한 상승이나 원격 제어가 이루어진 사례 있음.
코드 예제와 분석 🧑💻
아래는 함수 포인터를 이용한 UAF 취약점 활용 예제입니다:
char name;
void (*print)(void*);
} test;
void printName(test* t) {
printf("printName: %s\n", t->name);
}
int main(void) {
test* t = malloc(sizeof(test));
strcpy(t->name, "John");
t->print = printName;
t->print(t);
free(t);
test* t2 = malloc(sizeof(test));
scanf("%s", t2->name);
t2->print(t2); // 이미 해제된 포인터를 사용
free(t2);
return 0;
}
위 코드에서 t->print는 해제된 후에도 여전히 printName을 가리키고 있어, 만약 t2의 print를 조작하면 악성 코드 실행이 가능합니다.
어떻게 방어하는가? 🛡️
- 메모리 해제 후 null 포인터로 초기화
free한 포인터는 반드시 NULL로 초기화해 dangling pointer 사용을 막아야 합니다. - 스마트 포인터/메모리 관리 도구 활용
C++ 등에서는 스마트 포인터(std::unique_ptr, std::shared_ptr)로 자동 관리하면 UAF 위험을 크게 줄일 수 있습니다. - 정적/동적 분석 도구 사용
AddressSanitizer, Valgrind 등 분석 도구를 통해 UAF 취약점을 미리 찾아낼 수 있습니다. - 메모리 보호 정책 적용(Coalescing policy 개선)
메모리 관리 정책을 변경하여 해제된 메모리의 즉시 병합(immediate coalescing)을 적용하면 UAF 발생 빈도를 줄일 수 있습니다.
UAF 관련 위험 및 대응 방안 요약 📝
- Dangling pointer 방지: free 후 즉시 null 처리!
- 메모리 관리 자동화: 스마트 포인터 이용!
- 코드 리뷰 및 분석 도구 적용: AddressSanitizer, 메모리 검사 툴 적극 적용!
- 최신 보안 패치 적용: OS, 라이브러리, 브라우저 등 취약점의 신속한 패치!
결론🎉
Use After Free(UAF) 취약점은 시스템 보안의 근간을 흔드는 매우 위험한 버그입니다🔥. 개발자는 꼭 동적 메모리 사용에 주의하고, 포인터 관리와 메모리 해제 후 참조를 엄격하게 금지하며, 보안 도구 및 정책을 적극적으로 적용해야 합니다.
UAF 취약점을 잘 이해하고 안전한 코딩 습관을 길러, 보안사고 없는 프로그래밍 환경을 만드세요👍.
비유: "도서관 책 대출과 반납 이야기" 📚
- 책 빌리기(malloc)
도서관에서 책 한 권을 빌립니다. 이 책은 특별한 번호(메모리 주소)를 가지고 있고, 여러분은 대출증(포인터)로 언제든지 그 책을 볼 수 있습니다. - 책 반납하기(free)
다 읽은 후에는 책을 도서관에 반납합니다. 도서관에는 책을 다시 빌려줄 준비를 위해 반납된 책을 책장에 꽂아 둡니다. 이 책장(Free List 혹은 Tcache)에 있는 책들은 반납된 상태이지만, 내용은 아직 그대로 있습니다. - 같은 책 다시 빌리기(메모리 재할당)
누군가 같은 번호의 책을 또 빌리게 되는데, 도서관은 새 책을 꺼내는 대신 반납된 책장에 있던 책을 다시 빌려 줍니다. 문제는, 첫 번째 사람이 가진 오래된 대출증(포인터)이 아직 유효하다고 믿고 그 책 내용을 보거나 수정할 수 있다는 점입니다. - Use After Free 문제
첫 번째 사람이 이미 반납한 책을 계속 참조하면, 그 책 내용이 누군가에 의해 바뀌었을 수도 있어서 엉뚱한 내용이나 위험한 내용(악성 코드)을 보거나 실행하게 될 위험이 있습니다.
즉, 반납됐지만 "아직 가지고 있는 대출증"으로 반납한 책을 쓰는 것이 바로 Use After Free입니다.
이처럼 프로그래밍에서 메모리를 동적으로 할당받아 사용하다가 해제(free)한 뒤에도, 해제된 메모리를 가리키는 포인터가 존재하면, 그 메모리가 다시 재사용될 때 예상치 못한 위험한 상황이 발생할 수 있다는 뜻입니다.
쉽게 말해,
"책을 도서관에 반납했는데, 반납한 책을 계속 읽으려고 하는 상황"이 바로 Use After Free입니다! 📖❌
댓글
댓글 쓰기