🧟 해제 후 사용(UAF) 시뮬레이터 KISA A-5 · 해제된 자원 사용

객체가 해제됐는데 그 객체를 가리키던 포인터(이제 댕글링)가 계속 사용됩니다. 공격자가 해제된 슬롯에 조작된 객체를 재할당하면, 피해자가 낡은 포인터를 역참조할 때 공격자 데이터를 읽거나 실행하게 됩니다 — 전형적인 vtable/함수포인터 탈취.

① 힙 단계별 실행: 해제 → 재사용 → 역참조 VULNERABLE

Session 객체가 함수 포인터 onRender()를 가집니다. 단계를 진행하며 같은 힙 슬롯이 해제된 뒤 공격자에게 점거되는 동안 p가 계속 그 슬롯을 가리키는 것을 보세요.
피해자 포인터
Session* p
= 0x0
char* q (attacker)
= 0x0
힙 슬롯 @ 0xA10
0xA10
(미할당)

② 안전: 해제 후 NULL + 스마트 포인터 SECURE

free(p) 직후 p = NULL로 설정하면, 이후 사용은 공격자 데이터를 조용히 실행하는 대신 결정적으로(NULL 역참조) 크래시됩니다. 더 나은 방법: std::unique_ptr는 댕글링 사용 자체를 소유권/컴파일 단계에서 차단합니다.

③ 취약 vs 안전 코드

VULNERABLE — C++
Session* p = new Session();   // 0xA10
delete p;                     // 슬롯 해제, p는 그대로 0xA10
// ... 공격자가 같은 크기 버퍼 할당 → 0xA10 재사용 ...
char* q = (char*) malloc(sizeof(Session));
fill_with_payload(q);         // q->vptr = &system

p->onRender();   // ← 해제된 포인터 역참조
                 //   = 공격자가 심은 함수 포인터 호출 → RCE
SECURE — C / C++
// 1) 해제 후 즉시 무효화
Session* p = new Session();
delete p;
p = nullptr;          // 이후 p->... 는 결정적 크래시
if (p) p->onRender(); // NULL 가드로 안전

// 2) 소유권을 타입으로 강제 (권장)
auto p = std::make_unique<Session>();
// p가 스코프를 벗어나면 자동 해제,
// 댕글링/이중해제 자체가 발생하지 않음
p->onRender();
방어 핵심: 해제 직후 포인터를 NULL/nullptr로 무효화 · RAII 스마트 포인터(unique_ptr/shared_ptr)로 소유권·수명을 타입으로 강제 · 소유 raw 포인터를 공유하지 말 것 · CI에서 강화 할당자/ASAN으로 UAF 조기 탐지.
⚠️ 교육용 시뮬레이션입니다. 힙·포인터·주소는 모두 mock JS 객체이며 실제 메모리를 할당·해제·역참조하지 않습니다.