VirtualBox 힙 취약점이 여전히 심각하다.
2017년 작성된 초안에서 CVE-2017-3558이 발견되었다. 이는 VirtualBox의 NAT 네트워킹 스택에서 발생하는 취약점으로, 게스트 VM이 호스트의 사용자 공간으로 침투할 수 있게 한다. 놀랍게도 8년이 지난 지금도 코드 경로는 거의 그대로라, 컨테이너 환경이 대세인 오늘날 다시 한번 심층적인 분석이 필요한 상황이다.
VirtualBox의 Slirp 힙, 격리 기능을 어떻게 배신하는가
QEMU와 VirtualBox 모두에서 NAT를 담당하는 구식 사용자 모드 네트워킹 에뮬레이터인 Slirp. 게스트의 에뮬레이트된 NIC에서 원시 IP 패킷을 낚아채 재포장한 뒤, 커널 권한 없이 호스트의 소켓을 통해 내보낸다. 꽤나 똑똑한 방식이지만, VirtualBox는 이를 과도하게 변형했다. 포트를 제거하고 커스텀 할당기를 덧붙이는 식이다.
각 NAT 인터페이스는 자체 존 할당기를 갖는다. 3,072개의 2,048바이트 청크로 구성되며, nmbclusters=1024+32*64. 프리리스트는 높은 주소에서 시작해 낮은 주소로 이동한다. 각 청크 앞에는 인라인 메타데이터가 붙는다:
struct item {
uint32_t magic; // (항상 0xdead0001)
uma_zone_t zone; // (zone으로 가는 포인터; uma_zone_t는 struct uma_zone *)
uint32_t ref_count;
struct {
struct type *le_next; // (다음 요소)
struct type **le_prev; // (이전 le_next의 주소)
} list; // (프리리스트 또는 사용 중인 힙 청크 목록인 used_items의 항목)
};
메모리 해제는 m_freem → m_free → mb_free_ext → uma_zfree → uma_zfree_arg → slirp_uma_free 순서로 폭포수처럼 떨어진다.
여기서 문제가 생긴다. uma_zfree_arg() 함수가 이 메타데이터를 엿본다:
void uma_zfree_arg(uma_zone_t zone, void *mem, void *flags) {
struct item *it;
[...]
it = &((struct item *)mem)[-1];
Assert((it->magic == ITEM_MAGIC));
Assert((zone->magic == ZONE_MAGIC && zone == it->zone));
zone->pfFree(mem, 0, 0); // (zone->pfFree는 slirp_uma_free)
[...]
}
Assert() 구문은 VirtualBox 다운로드 페이지에서 제공하는 릴리스 빌드에서는 제거된다. 마법 값(magic) 검사도, 존 유효성 검사도 없다.
그 후 slirp_uma_free()는 it->zone을 무조건 신뢰하고 pfFini를 가져온 뒤 다음을 호출한다:
{공격자가 제어 가능한 포인터}({공격자가 제어 가능한 포인터}, {패킷 데이터 포인터}, {공격자가 제어 가능한 u32});
게스트가 제어하는 힙에서 임의의 함수 호출이 가능한 셈이다.
2025년에도 공격자는 이 취약점을 악용할 수 있을까?
코드의 고정성이 문제다. 해당 글은 “묘사된 코드 중 상당수가 그 이후로 많이 변하지 않은 것 같다”고 지적한다. VirtualBox 7.0 소스를 확인해 보면 slirp_uma_free의 골격은 그대로 유지되고 있다. 릴리스 버전의 Assert() 제거? 여전하다. 리눅스 호스트에서는 재배치 불가능한 바이너리가 상황을 더 악화시키고, 필요하다면 memcpy() 패턴이 ROP를 돕는다.
게스트가 조작된 이더넷 프레임을 보내면 힙이 넘쳐나고, 청크의 item 구조체가 망가진다. it->zone이 공격자 데이터로 향하도록 만든다. pfFini를 쓰기 가능한 가젯으로 향하게 하면, 호스트 사용자 공간이 장악된다. 커널 침투는 아직 완성되지 않은 단계지만, VBoxDrv를 통한 권한 상승이 가능하다.
위험도는? 공유 호스팅 VM, 모의 해킹, 레드팀 실험실 등에서는 높다고 할 수 있다. NAT 모드의 매력, 즉 게스트 방화벽 역할이 오히려 독이 되는 셈이다.
Heartbleed의 할당기 오작동과 유사한 맥락이다. 벤더들은 증상만 치료할 뿐 근본적인 문제는 외면한다. VirtualBox의 대응? 2017년 이후 별도의 공지는 없으며, 이 재조명에 대한 언급이 없다.
사용자 공간 탈출은 커널 RCE만큼 치명적이진 않지만, 이는 시작일 뿐이다. 거기서부터는 리눅스 호스트의 수많은 취약점, 예를 들어 Dirty COW 같은 것을 이용할 수 있다.
예상컨대, 국가 차원의 공격 세력들은 이 취약점을 에어 갭 환경에서의 작전에 활용할 것이다. 커널 제로데이 취약점을 찾는 대신, 사용자 공간에서 더 빠르게 침투할 수 있다면 굳이 그럴 필요가 없을 테니 말이다.
VM 네트워킹이 여전히 지뢰밭인 이유
NAT 모드는 게스트 트래픽을 호스트 트래픽처럼 위장한다. 보안보다 편리성을 우선시하는 방식이다. Slirp의 사용자 모드 장점은 힙 스프레이 공격 앞에 무너진다.
대안은? 브리지 네트워킹은 게스트를 그대로 노출시키므로 필수적으로 방화벽 설정이 필요하다. 혹은 호스트의 eBPF를 활용해 정책을 적용할 수도 있다. 하지만 관성은 강하다. 수백만 명의 사용자가 매일 VBox NAT를 켠다.
Oracle의 관리 능력에 대한 비판도 나온다. 무료이고 기능이 풍부하지만, 패치가 늦는다는 지적이다. 이 2017년의 유령은 분명히 보여준다. VM 하이퍼바이저는 요새가 아니라는 것을.
지금 당장 완화해야 한다. 가능하다면 NAT를 비활성화하라. 직접 컴파일한다면 엄격한 빌드 설정을 사용하라. 게스트 시스템도 감사하라. 악성코드는 패킷 플러딩을 좋아한다.
VM에서 호스트 사용자 공간으로의 패치되지 않은 경로. 놀랍도록 직관적이다.
🧬 관련 인사이트
자주 묻는 질문
VirtualBox의 CVE-2017-3558이란 무엇인가? NAT 모드에서 Slirp 힙 손상을 통해 발생하는 게스트-호스트 탈출 취약점으로, 사용자 공간에서 임의의 함수 호출을 가능하게 한다.
2025년에도 VirtualBox NAT는 안전한가? 완전히 안전하지는 않다. 핵심 결함이 여전히 존재하므로, 대신 브리지 또는 호스트 전용 모드를 사용하는 것이 좋다.
VM 탈출로부터 어떻게 보호할 수 있는가? 하이퍼바이저를 샌드박스 처리하고, 불필요한 네트워킹을 비활성화하며, 힙 사용량 이상 징후를 모니터링하라.