VirtualBox Slirp NAT ํŒจํ‚ท ํž™ ์ต์Šคํ”Œ๋กœ์ž‡

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์š”์•ฝ

  • VirtualBox๋Š” ํŒจํ‚ท ๋ฒ„ํผ(mbufs)๊ฐ€ ์ธ๋ผ์ธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ์ฝœ๋ฐฑ(pfFini, pfDtor)์„ ๊ฐ€์ง„ ์ปค์Šคํ…€ zone allocator์— ์กด์žฌํ•˜๋Š”, ํฌ๊ฒŒ ์ˆ˜์ •๋œ Slirp ํฌํฌ๋ฅผ ํฌํ•จํ•œ๋‹ค.
  • ๊ฒŒ์ŠคํŠธ๋Š” ์‹ ๋ขฐ๋œ m->m_len์„ ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” IP ํ—ค๋” ๊ธธ์ด๋กœ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์ดํ›„์˜ ๋ชจ๋“  ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ๋“ค์„ ๋ฌด๋ ฅํ™”ํ•˜๊ณ  infoleak ๋ฐ overwrite primitives๋ฅผ ์œ ๋ฐœํ•œ๋‹ค.
  • checksum์ด 0์ด๊ณ  ip_len์ด ๊ณผ๋„ํ•œ UDP ํŒจํ‚ท์„ ์•…์šฉํ•˜๋ฉด, ๊ฒŒ์ŠคํŠธ๋Š” mbuf ๊ผฌ๋ฆฌ์™€ ์ธ์ ‘ ์ฒญํฌ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ exfiltrateํ•˜์—ฌ ํž™ ๋ฐ zone ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
  • ์กฐ์ž‘๋œ IP ์˜ต์…˜์„ ์ œ๊ณตํ•˜๋ฉด ip_stripoptions()๊ฐ€ ์ œ์ž๋ฆฌ์—์„œ memcpy()๋กœ ๋„ˆ๋ฌด ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•˜๋„๋ก ๊ฐ•์ œ๋˜์–ด, ๊ณต๊ฒฉ์ž๊ฐ€ ๋‹ค์Œ mbuf์˜ struct item ํ—ค๋”๋ฅผ ๋ฎ์–ด์“ฐ๊ณ  ๊ทธ zone ํ•„๋“œ๋ฅผ ์™„์ „ํžˆ ์ œ์–ด๋˜๋Š” ๋ฐ์ดํ„ฐ๋กœ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์†์ƒ๋œ mbuf๋ฅผ freeํ•˜๋ฉด ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ๊ณตํ•œ ์ธ์ˆ˜๋ฅผ ๊ฐ€์ง„ zone->pfFini()๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค; ์ด๋ฅผ memcpy@plt๋กœ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ํ•˜๋ฉด arbitrary copy/write primitive๊ฐ€ ๋˜์–ด non-PIE VirtualBox ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด๋ถ€์˜ GOT ์—”ํŠธ๋ฆฌ๋‚˜ ๋‹ค๋ฅธ ์ œ์–ด ๋ฐ์ดํ„ฐ๋กœ ํ–ฅํ•˜๋„๋ก ์กฐ์ข…ํ•  ์ˆ˜ ์žˆ๋‹ค.

Packet allocator anatomy

VirtualBox๋Š” ๊ฐ ์ธํ„ฐํŽ˜์ด์Šค๋งˆ๋‹ค zone_clust๋ผ๋Š” zone์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  Ethernet ํ”„๋ ˆ์ž„์„ ํ• ๋‹นํ•œ๋‹ค. ๊ฐ 0x800-byte ๋ฐ์ดํ„ฐ ์ฒญํฌ๋Š” ์ธ๋ผ์ธ ํ—ค๋”๊ฐ€ ์•ž์— ๋ถ™๋Š”๋‹ค:

struct item {
uint32_t magic;      // 0xdead0001
void    *zone;       // uma_zone_t pointer with callbacks
uint32_t ref_count;
LIST_ENTRY(item) list; // freelist / used list links
};

mbuf๊ฐ€ ํ•ด์ œ๋  ๋•Œ ํ˜ธ์ถœ ์Šคํƒ m_freem -> ... -> slirp_uma_free()๋Š” ์ธ๋ผ์ธ ํ—ค๋”๋ฅผ ์‹ ๋ขฐํ•ฉ๋‹ˆ๋‹ค:

  1. uma_zfree_arg()๋Š” item = (struct item *)mem - 1์„ ์žฌ๊ณ„์‚ฐํ•˜๊ณ  item->zone์„ ๊ฒ€์ฆํ•ด์•ผ ํ•˜์ง€๋งŒ Assert()๋Š” ๋ฆด๋ฆฌ์Šค ๋นŒ๋“œ์—์„œ ์ปดํŒŒ์ผ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  2. slirp_uma_free()๋Š” zone = item->zone์„ ๋กœ๋“œํ•˜๊ณ  ์กฐ๊ฑด ์—†์ด zone->pfFini(zone->pData, data_ptr, zone->size)๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ zone->pfDtor(...)๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ mbuf ํ—ค๋”์— ๋Œ€ํ•œ ๋ชจ๋“  write-what-where๋Š” free() ์ค‘์— ์ œ์–ด ๊ฐ€๋Šฅํ•œ ๊ฐ„์ ‘ ํ˜ธ์ถœ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

Infoleak via m->m_len override

VirtualBox๋Š” ip_input() ์ƒ๋‹จ์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค:

if (m->m_len != RT_N2H_U16(ip->ip_len))
m->m_len = RT_N2H_U16(ip->ip_len);

Because the assignment happens before verifying the IP header, a guest can advertise any length up to 0xffff. The rest of the stack (ICMP, UDP, fragmentation handlers, etc.) assumes m->m_len is trustworthy and uses it to decide how many bytes to copy off the mbuf.

์ฒดํฌ์„ฌ์ด 0์ธ UDP ํŒจํ‚ท(์ฆ‰ โ€œno checksumโ€)์„ ์‚ฌ์šฉํ•˜๋ผ. NAT fast-path๋Š” payload ๋ฌด๊ฒฐ์„ฑ์„ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  m->m_len ๋ฐ”์ดํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋ฏ€๋กœ ip_len์„ ๋ถ€ํ’€๋ฆฌ๋ฉด Slirp๊ฐ€ ์‹ค์ œ ๋ฒ„ํผ๋ฅผ ๋„˜์–ด ์ฝ๊ณ  heap residues๋ฅผ ๊ฒŒ์ŠคํŠธ๋‚˜ NAT ๋ฐ–์˜ ํ˜‘๋ ฅํ•˜๋Š” ์™ธ๋ถ€ ํ—ฌํผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค. ์ฒญํฌ ํฌ๊ธฐ๊ฐ€ 2048 ๋ฐ”์ดํŠธ์ด๋ฏ€๋กœ leak์€ ๋‹ค์Œ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค:

  • ๋‹ค์Œ mbuf์˜ inline struct item โ€” freelist ์ˆœ์„œ์™€ ์‹ค์ œ zone ํฌ์ธํ„ฐ๋ฅผ ๋“œ๋Ÿฌ๋‚ธ๋‹ค.
  • magic ํ•„๋“œ ๊ฐ™์€ heap cookies โ€” ์ดํ›„ corruptions๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ์œ ํšจํ•ด ๋ณด์ด๋Š” ํ—ค๋”๋ฅผ ๋งŒ๋“ค๋„๋ก ๋„์›€.

IP options๋กœ ์ธ์ ‘ ์ฒญํฌ ํ—ค๋” ๋ฎ์–ด์“ฐ๊ธฐ

๊ฐ™์€ ์ž˜๋ชป๋œ ๊ธธ์ด๋Š” ํŒจํ‚ท์„ ip_stripoptions()๋ฅผ ํ†ตํ•˜๊ฒŒ ํ•˜์—ฌ overwrite ๊ธฐ๋ณธ ๋™์ž‘์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค(์ด๋Š” IP header์— options๊ฐ€ ์žˆ๊ณ  payload๊ฐ€ UDP/TCP์ผ ๋•Œ ํŠธ๋ฆฌ๊ฑฐ๋œ๋‹ค). ํ—ฌํผ๋Š” m->m_len์œผ๋กœ๋ถ€ํ„ฐ ๋ณต์‚ฌ ๊ธธ์ด๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ  memcpy()๋ฅผ ํ˜ธ์ถœํ•ด ์ „์†ก ํ—ค๋”๋ฅผ ์ œ๊ฑฐ๋œ ์˜ต์…˜ ์œ„๋กœ ์ด๋™์‹œํ‚จ๋‹ค:

  1. ๊ธด ip_len์„ ์ œ๊ณตํ•˜์—ฌ ๊ณ„์‚ฐ๋œ ์ด๋™ ๊ธธ์ด๊ฐ€ ํ˜„์žฌ mbuf๋ฅผ ๋„˜์–ด๊ฐ€๋„๋ก ํ•œ๋‹ค.
  2. IP options๋ฅผ ์ ์€ ์ˆ˜ ํฌํ•จ์‹œ์ผœ Slirp๊ฐ€ stripping ๊ฒฝ๋กœ๋กœ ์ง„์ž…ํ•˜๊ฒŒ ํ•œ๋‹ค.
  3. memcpy()๊ฐ€ ์‹คํ–‰๋˜๋ฉด ๋‹ค์Œ mbuf์—์„œ ์ฝ์–ด ํ˜„์žฌ mbuf์˜ payload์™€ inline header์— ๋ฎ์–ด์จ magic, zone, ref_count ๋“ฑ์„ ์†์ƒ์‹œํ‚จ๋‹ค.

ํ• ๋‹น์ž๋Š” ๋™์ผ ์ธํ„ฐํŽ˜์ด์Šค์˜ ํŒจํ‚ท์„ freelist ์ƒ์—์„œ ์ธ์ ‘ํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ฏ€๋กœ, ์ด ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋Š” ์ ์ ˆํ•œ heap grooming ์ดํ›„์— ๋‹ค์Œ ์ฒญํฌ๋ฅผ ๊ฒฐ์ •๋ก ์ ์œผ๋กœ ๋ฎ์นœ๋‹ค.

uma_zone_t ์œ„์กฐ๋กœ pfFini ํƒˆ์ทจํ•˜๊ธฐ

์ธ์ ‘ํ•œ struct item์„ ์†์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋ฉด, ์ต์Šคํ”Œ๋กœ์ž‡์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง„ํ–‰๋œ๋‹ค:

  1. ์œ ์ถœ๋œ heap ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฒŒ์ŠคํŠธ๊ฐ€ ์™„์ „ํžˆ ์ œ์–ดํ•˜๋Š” mbuf ์•ˆ์— ๊ฐ€์งœ uma_zone ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค. ๋‹ค์Œ์„ ์ฑ„์šด๋‹ค:
    • pfFini์— memcpy()์˜ PLT ์—”ํŠธ๋ฆฌ
    • pData์— ์›ํ•˜๋Š” ๋ชฉ์ ์ง€ ํฌ์ธํ„ฐ(์˜ˆ: GOT ์—”ํŠธ๋ฆฌ, vtable ์Šฌ๋กฏ, ํ•จ์ˆ˜ ํฌ์ธํ„ฐ ๋ฐฐ์—ด)
    • size์— ๋ณต์‚ฌํ•  ๋ฐ”์ดํŠธ ์ˆ˜
    • ์„ ํƒ: pfDtor๋ฅผ 2๋‹จ๊ณ„ ํ˜ธ์ถœ๋กœ ์„ค์ •(์˜ˆ: ์ƒˆ๋กœ ์“ด ํ•จ์ˆ˜ ํฌ์ธํ„ฐ๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก)
  2. ๋Œ€์ƒ mbuf์˜ zone ํ•„๋“œ๋ฅผ ๊ฐ€์งœ ๊ตฌ์กฐ์ฒด ํฌ์ธํ„ฐ๋กœ ๋ฎ์–ด์“ฐ๊ณ , list ํฌ์ธํ„ฐ๋ฅผ ์กฐ์ •ํ•ด freelist ์žฅ๋ถ€๊ฐ€ ์ถฉ๋Œ์„ ํ”ผํ•  ์ˆ˜ ์žˆ์„ ๋งŒํผ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€๋˜๊ฒŒ ํ•œ๋‹ค.
  3. mbuf๋ฅผ freeํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด slirp_uma_free()๋Š” mbuf์— ๊ฒŒ์ŠคํŠธ ์ œ์–ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๋™์•ˆ memcpy(dest=pData, src=item_data, n=size)๋ฅผ ์‹คํ–‰ํ•ด arbitrary write๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

Linux VirtualBox ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” non-PIE์ด๋ฏ€๋กœ memcpy์™€ system์˜ PLT ์ฃผ์†Œ๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ์–ด ์ง์ ‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฒŒ์ŠคํŠธ๋Š” ๋˜ ๊ฐ€๋กœ์ฑ„์ง„ ํ˜ธ์ถœ์ด ์‹คํ–‰๋  ๋•Œ ์ฐธ์กฐ๊ฐ€ ์œ ์ง€๋˜๋Š” ๋‹ค๋ฅธ mbuf ์•ˆ์— /bin/sh ๊ฐ™์€ ๋ฌธ์ž์—ด์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

Fragmentation์„ ํ†ตํ•œ Heap grooming

Slirp์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ณ„ zone์€ ๊นŠ์ด๊ฐ€ 3072 ์ฒญํฌ์ด๊ณ  ์ฒ˜์Œ์—๋Š” ์—ฐ์† ๋ฐฐ์—ด๋กœ ํ• ๋‹น๋˜์–ด freelist๊ฐ€ ๋†’์€ ์ฃผ์†Œ์—์„œ ๋‚ฎ์€ ์ฃผ์†Œ๋กœ ์ˆœํšŒ๋œ๋‹ค. ๊ฒฐ์ •๋ก ์  ์ธ์ ‘์„ฑ์€ ๋‹ค์Œ์œผ๋กœ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค:

  • NAT์— ์ผ์ • ํฌ๊ธฐ์˜ IP_MF fragment๋ฅผ ๋‹ค์ˆ˜ ํ˜๋ ค๋ณด๋‚ด์–ด reassembly ์ฝ”๋“œ๊ฐ€ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ mbuf ์‹œํ€€์Šค๋ฅผ ํ• ๋‹นํ•˜๊ฒŒ ํ•œ๋‹ค.
  • ํƒ€์ž„์•„์›ƒ๋˜๋Š” fragment๋ฅผ ๋ณด๋‚ด ํŠน์ • ์ฒญํฌ๋ฅผ ์žฌํ™œ์šฉํ•˜์—ฌ frees๊ฐ€ LIFO ์ˆœ์„œ๋กœ freelist๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ํ•œ๋‹ค.
  • freelist walk์— ๋Œ€ํ•œ ์ง€์‹์„ ์‚ฌ์šฉํ•ด ๋ฏธ๋ž˜์˜ ํ”ผํ•ด์ž mbuf๋ฅผ IP options overflow๋ฅผ ์‹ค์„ mbuf ๋ฐ”๋กœ ๋’ค์— ๋ฐฐ์น˜ํ•œ๋‹ค.

์ด๋Ÿฌํ•œ grooming์€ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ชฉํ‘œ struct item์„ ์ •ํ™•ํžˆ ํƒ€๊ฒฉํ•˜๋„๋ก ํ•˜๊ณ  ๊ฐ€์งœ uma_zone์ด leak primitive์˜ ๋ฒ”์œ„ ๋‚ด์— ๋‚จ์•„์žˆ๊ฒŒ ๋ณด์žฅํ•œ๋‹ค.

From arbitrary write to host code execution

memcpy-on-free primitive๋ฅผ ์ด์šฉํ•˜๋ฉด:

  1. ๊ณต๊ฒฉ์ž๊ฐ€ ์ œ์–ดํ•˜๋Š” /bin/sh ๋ฌธ์ž์—ด๊ณผ ๋ช…๋ น ๋ฒ„ํผ๋ฅผ ์•ˆ์ •์ ์ธ mbuf๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
  2. primitive๋ฅผ ์‚ฌ์šฉํ•ด GOT ์—”ํŠธ๋ฆฌ๋‚˜ ๊ฐ„์ ‘ ํ˜ธ์ถœ ์ง€์ (์˜ˆ: NAT ์žฅ์น˜ ์ƒํƒœ ๋‚ด๋ถ€์˜ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ)์„ system()์˜ PLT ์—”ํŠธ๋ฆฌ๋กœ ๋ฎ์–ด์“ด๋‹ค.
  3. ๋ฎ์–ด์“ด ํ˜ธ์ถœ์„ ํŠธ๋ฆฌ๊ฑฐํ•œ๋‹ค. VirtualBox๊ฐ€ NAT ์žฅ์น˜๋ฅผ ํ˜ธ์ŠคํŠธ ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€์—์„œ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ํŽ˜์ด๋กœ๋“œ๋Š” VirtualBox๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์œผ๋กœ ์‹คํ–‰๋˜์–ด guest-to-host escape๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค.

๋Œ€์ฒด ํŽ˜์ด๋กœ๋“œ๋กœ๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์†Œํ˜• ROP ์ฒด์ธ์„ ์‹ฌ๊ณ  ๊ทธ ์ฃผ์†Œ๋ฅผ ์ž์ฃผ ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ์— ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜, pfFini/pfDtor ์ž์ฒด๋ฅผ ์—ฐ์‡„๋œ gadgets๋กœ ์žฌ์ง€์ •ํ•ด ๋ฐ˜๋ณต์ ์ธ ์“ฐ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

References

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ