security
CHAPTER 93 / 96
읽기 약 2분
FUNCTION
힙 오버플로우와 Use-After-Free
핵심 개념
힙 버퍼 오버플로우·UAF — 방어: free 후 NULL, RAII 패턴. Chrome/Firefox UAF 사례.
본문
힙 오버플로우
// ⚠️ 교육 목적
#include <stdlib.h>
#include <string.h>
int main(void) {
char *buf = malloc(16);
char *secret = malloc(16);
strcpy(secret, "PASSWORD");
// ❌ buf 영역을 넘어 secret까지 덮어씀
strcpy(buf, "AAAAAAAAAAAAAAAAAAAAAAAAAA"); // 27 바이트
// 힙은 보통 buf와 secret이 인접
// → secret 변조됨
free(buf);
free(secret);
return 0;
}
// 방어:
// 1. 항상 strncpy/snprintf
// 2. -fsanitize=address (런타임 탐지)
// 3. 힙 일관성 검사 (glibc malloc 보호)Use-After-Free (UAF)
// ⚠️ 교육 목적
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char *p = malloc(16);
strcpy(p, "Original");
free(p);
// ❌ UAF — p는 더 이상 유효하지 않음
char *q = malloc(16); // q가 p와 같은 메모리 받을 수 있음
strcpy(q, "Hijacked");
printf("p: %s\n", p); // "Hijacked" 출력 (의도와 다름)
free(q);
return 0;
}
// 안전 패턴:
#define SAFE_FREE(p) do { free(p); (p) = NULL; } while (0)
int safe_main(void) {
char *p = malloc(16);
SAFE_FREE(p);
// p는 NULL — 사용 시 즉시 segfault (조용한 버그보다 명확)
if (p != NULL) {
// 실행 안 됨
}
return 0;
}Double Free
// ⚠️ 교육 목적
#include <stdlib.h>
int main(void) {
char *p = malloc(16);
free(p);
free(p); // ❌ Double free
// 글리브 모던 버전:
// free(): double free detected in tcache 2
// Aborted (core dumped)
// 공격: double free → 힙 메타데이터 손상 → 임의 쓰기
// 모던 glibc는 tcache·MALLOC_CHECK_ 으로 일부 차단
return 0;
}RAII (Resource Acquisition Is Initialization) 패턴
// C에는 자동 destructor 없음 — 수동으로 RAII 흉내
// goto cleanup 패턴
#include <stdio.h>
#include <stdlib.h>
int do_work(void) {
char *buf1 = NULL, *buf2 = NULL;
FILE *fp = NULL;
int rc = -1;
buf1 = malloc(1024);
if (!buf1) goto cleanup;
buf2 = malloc(2048);
if (!buf2) goto cleanup;
fp = fopen("data.txt", "r");
if (!fp) goto cleanup;
// 작업...
rc = 0;
cleanup:
free(buf1); // free(NULL)은 안전
free(buf2);
if (fp) fclose(fp);
return rc;
}C++ smart pointer 비교 (개념)
// C++의 unique_ptr은 자동 RAII
// std::unique_ptr<int> p(new int(42));
// 함수 종료 시 자동 delete
// C에서 비슷하게 — GCC __attribute__((cleanup))
#include <stdio.h>
#include <stdlib.h>
void auto_free(void *p) {
void **pp = (void**)p;
free(*pp);
}
#define SCOPED_PTR __attribute__((cleanup(auto_free)))
int main(void) {
SCOPED_PTR char *p = malloc(100);
// 함수 종료 시 자동 free
return 0;
}ASan으로 UAF 탐지
gcc -fsanitize=address -g uaf.c -o uaf
./uaf
# 출력:
# ==12345== ERROR: AddressSanitizer: heap-use-after-free
# READ of size 1 at 0x... thread T0
# #0 0x... in main uaf.c:10
#
# 0x... is located 0 bytes inside of 16-byte region [0x..., 0x...)
# freed by thread T0 here:
# #0 0x... in __interceptor_free
# #1 0x... in main uaf.c:7
# previously allocated by thread T0 here:
# #0 0x... in __interceptor_malloc
# #1 0x... in main uaf.c:5실전 CVE 사례
Chrome UAF (자주 발생):
- CVE-2023-2033 V8 type confusion
- CVE-2023-3079 V8 UAF
방어: V8 sandbox, MiraclePtr (Chromium의 dangling pointer 방지)
Firefox UAF:
- CVE-2023-32205 SpiderMonkey JIT
방어: ASan + Fuzzing + RUST 일부 모듈
브라우저들의 대응:
- Chrome → Rust 일부 도입
- Mozilla → Rust 적극 채택 (Servo, Stylo)
- Apple → Swift 우선다음 챕터
CH.10 "정수 오버플로우" — 수학적 함정.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 C 코드의 malloc/free 흐름을 분석해서 UAF·double free 가능 경로를 자동 탐지해줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
Chrome/Firefox UAF CVE 5개의 패치 패턴을 비교해서 일반화 가능한 방어 원칙을 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 코드베이스에 ASan + 코드 리뷰 체크리스트 + RAII 패턴을 적용하는 로드맵을 만들어줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 메모리 안전 언어(Rust)로의 전환이 한국 기업에서 어떤 속도로 진행 중인지 솔직히 알려줘.
⭐ 이것만 기억하세요
힙 오버플로우와 Use-After-Free는 이 3가지만 확실히 잡으세요
1.힙 오버플로우는 인접 청크를 덮어쓰고, UAF는 해제된 메모리를 다시 사용하는 패턴
2.SAFE_FREE 매크로 + ASan 두 가지로 거의 모든 UAF 탐지·차단 가능
3.다음 챕터 CH.10에서 정수 오버플로우 — 메모리 외 흔히 놓치는 수학적 함정
공유하기
진행도 93 / 96