AF_UNIX MSG_OOB UAF & SKB ๊ธฐ๋ฐ ์ปค๋ ํ๋ฆฌ๋ฏธํฐ๋ธ
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
TL;DR
- Linux >=6.9์์ AF_UNIX
MSG_OOB์ฒ๋ฆฌ๋ฅผ ์ํmanage_oob()๋ฆฌํฉํฐ(5aa57d9f2d53)์ ๊ฒฐํจ์ด ๋์ ๋์์ต๋๋ค. ์ฐ์๋ ์ ๋ก-๊ธธ์ด SKB๊ฐu->oob_skb๋ฅผ ์ด๊ธฐํํ๋ ๋ก์ง์ ์ฐํํ์ฌ, ์ผ๋ฐ์ ์ธrecv()๊ฐ ํฌ์ธํฐ๊ฐ ์ฌ์ ํ ์ด์์๋ ๋์ OOB SKB๋ฅผ freeํ ์ ์์๊ณ ๊ทธ ๊ฒฐ๊ณผ CVE-2025-38236์ด ๋ฐ์ํ์ต๋๋ค. recv(..., MSG_OOB)๋ฅผ ์ฌ์คํํ๋ฉด danglingstruct sk_buff๋ฅผ ์ญ์ฐธ์กฐํฉ๋๋ค.MSG_PEEK๊ฐ ์์ ๊ฒฝ์ฐ, ๊ฒฝ๋กunix_stream_recv_urg() -> __skb_datagram_iter() -> copy_to_user()๊ฐ ์์ ์ ์ธ 1๋ฐ์ดํธ ์์ ์ปค๋ ์ฝ๊ธฐ๊ฐ ๋ฉ๋๋ค;MSG_PEEK๊ฐ ์์ผ๋ฉด ์ด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ ์ฌํ ๋น๋ ๊ฐ์ฒด์ offset0x40์ ๋์ธ 64๋นํธ ๊ฐ์ ์์ dword์ +4 GiB๋ฅผ ๋ํ๋, offset0x44์UNIXCB(oob_skb).consumed๋ฅผ ์ฆ๊ฐ์ํต๋๋ค.- order-0/1 unmovable pages๋ฅผ ์์ง(page-table spray)ํ๊ณ SKB slab ํ์ด์ง๋ฅผ buddy allocator๋ก ๊ฐ์ freeํ ๋ค ๋ฌผ๋ฆฌ ํ์ด์ง๋ฅผ pipe buffer๋ก ์ฌ์ฌ์ฉํจ์ผ๋ก์จ, ์ต์คํ๋ก์์ ์ ์ด๋ ๋ฉ๋ชจ๋ฆฌ์ SKB ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์์กฐํด dangling ํ์ด์ง๋ฅผ ์๋ณํ๊ณ read ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ
.data, vmemmap, per-CPU, ํ์ด์ง-ํ ์ด๋ธ ์์ญ์ผ๋ก ํผ๋ฒ์ํต๋๋ค โ usercopy hardening์๋ ๋ถ๊ตฌํ๊ณ . - ๋์ผํ ํ์ด์ง๋ ์ดํ ์๋ก ํด๋ก ๋ ์ค๋ ๋์ ์ต์์ ์ปค๋ ์คํ ํ์ด์ง๋ก ์ฌํ์ฉ๋ ์ ์์ต๋๋ค.
CONFIG_RANDOMIZE_KSTACK_OFFSET๋ ์ค๋ผํด์ด ๋ฉ๋๋ค:pipe_write()๊ฐ ๋ธ๋ก๋๋ ๋์ ์คํ ๋ ์ด์์์ ํ์งํ์ฌ ๊ณต๊ฒฉ์๋ spilledcopy_page_from_iter()๊ธธ์ด(R14)๊ฐ offset0x40์ ์์นํ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ +4 GiB ์ฆ๊ฐ๋ฅผ ๋ฐ์ฌํด ์คํ ๊ฐ์ ์์์ํต๋๋ค. - ์์ฒด ๋ฃจํ๋ฅผ ๋๋
skb_shinfo()->frag_list๋ ํ๋ ฅ ์ค๋ ๋๊ฐ ๋จ์ผMADV_DONTNEEDํ์ด ์๋ VMA์ ๋ํดmprotect()๋กcopy_from_iter()๋ฅผ ๋ฉ์ถ ๋๊น์ง UAF syscall์ ์ปค๋ ๊ณต๊ฐ์์ ๋ฐ๋ณต์ํค๊ฒ ํฉ๋๋ค. ๋ฃจํ๋ฅผ ๊นจ๋ฉด ์ฆ๊ฐ๊ฐ ์คํ ํ๊น์ด ํ์ฑํ๋ ์ ํํ ์์ ์ ํด์ ๋์ดbytes์ธ์๋ฅผ ๋ถํ๋ฆฌ๊ณcopy_page_from_iter()๊ฐ pipe buffer ํ์ด์ง๋ฅผ ๋์ด ๋ค์ ๋ฌผ๋ฆฌ ํ์ด์ง์ ์ฐ๊ฒ ๋ง๋ญ๋๋ค. - read ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก pipe-buffer PFN๊ณผ ํ์ด์ง ํ
์ด๋ธ์ ๋ชจ๋ํฐ๋งํจ์ผ๋ก์จ, ๊ณต๊ฒฉ์๋ ๋ค์ ํ์ด์ง๊ฐ PTE ํ์ด์ง์์ ํ์ธํ๊ณ OOB ๋ณต์ฌ๋ฅผ ์์์ PTE ์ฐ๊ธฐ๋ก ๋ณํํ์ฌ ๋ฌด์ ํ ์ปค๋ R/W/X๋ฅผ ํ๋ํฉ๋๋ค. Chrome์ ๋ ๋๋ฌ์์
MSG_OOB๋ฅผ ์ฐจ๋จํ์ฌ ์ ๊ทผ ๊ฐ๋ฅ์ฑ์ ์ํํ์ผ๋ฉฐ(6711812), Linux๋ ๋ก์ง ๊ฒฐํจ์32ca245464e1์์ ์์ ํ๊ณCONFIG_AF_UNIX_OOB๋ฅผ ๋์ ํด ํด๋น ๊ธฐ๋ฅ์ ์ ํํ์ผ๋ก ๋ง๋ค์์ต๋๋ค.
๊ทผ๋ณธ ์์ธ: manage_oob()๋ ํ๋์ ์ ๋ก-๊ธธ์ด SKB๋ง ๊ฐ์ ํ๋ค
unix_stream_read_generic()๋ manage_oob()๊ฐ ๋ฐํํ๋ ๋ชจ๋ SKB๊ฐ unix_skb_len() > 0์์ ๊ธฐ๋ํฉ๋๋ค. 93c99f21db36 ์ดํ manage_oob()๋ recv(MSG_OOB)๊ฐ ๋จ๊ธด ์ ๋ก-๊ธธ์ด SKB๋ฅผ ์ฒ์ ์ ๊ฑฐํ ๋๋ง๋ค skb == u->oob_skb ์ ๋ฆฌ ๊ฒฝ๋ก๋ฅผ ๊ฑด๋๋ฐ์์ต๋๋ค. ์ดํ์ ์์ (5aa57d9f2d53)์ ์ฌ์ ํ ์ฒซ ๋ฒ์งธ ์ ๋ก-๊ธธ์ด SKB์์ skb_peek_next()๋ก ๋์ด๊ฐ๋ฉด์ ๊ธธ์ด๋ฅผ ์ฌํ์ธํ์ง ์์์ต๋๋ค. ๋ ๊ฐ์ ์ฐ์๋ ์ ๋ก-๊ธธ์ด SKB๊ฐ ์์ผ๋ฉด ํจ์๋ ๋ ๋ฒ์งธ ๋น SKB๋ฅผ ๋ฐํํ๊ณ , unix_stream_read_generic()๋ ๋ค์ manage_oob()๋ฅผ ํธ์ถํ์ง ์๊ณ ์ด๋ฅผ ๊ฑด๋๋ฐ์๊ธฐ ๋๋ฌธ์ ์ค์ OOB SKB๊ฐ dequeue๋์ด free๋์๋๋ฐ u->oob_skb๋ ์ฌ์ ํ ์ด๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์์ต๋๋ค.
์ต์ ํธ๋ฆฌ๊ฑฐ ์ํ์ค
char byte;
int socks[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, socks);
for (int i = 0; i < 2; ++i) {
send(socks[1], "A", 1, MSG_OOB);
recv(socks[0], &byte, 1, MSG_OOB);
}
send(socks[1], "A", 1, MSG_OOB); // SKB3, u->oob_skb = SKB3
recv(socks[0], &byte, 1, 0); // normal recv frees SKB3
recv(socks[0], &byte, 1, MSG_OOB); // dangling u->oob_skb
unix_stream_recv_urg()๊ฐ ๋
ธ์ถํ๋ ํ๋ฆฌ๋ฏธํฐ๋ธ
- 1-byte arbitrary read (repeatable):
state->recv_actor()๋ ๊ฒฐ๊ตญcopy_to_user(user, skb_sourced_addr, 1)์ ์ํํฉ๋๋ค. dangling SKB๊ฐ ๊ณต๊ฒฉ์๊ฐ ์ ์ดํ๋ ๋ฉ๋ชจ๋ฆฌ(๋๋ pipe ํ์ด์ง ๊ฐ์ ์ ์ด ๊ฐ๋ฅํ alias)๋ก ์ฌํ ๋น๋๋ฉด, ๋งค๋ฒrecv(MSG_OOB | MSG_PEEK)๊ฐ__check_object_size()๋ก ํ์ฉ๋๋ ์์์ ์ปค๋ ์ฃผ์์์ 1๋ฐ์ดํธ๋ฅผ ์ ์ ๊ณต๊ฐ์ผ๋ก ๋ณต์ฌํฉ๋๋ค(ํ๋ก์ธ์ค๊ฐ ์ฃฝ์ง ์์).MSG_PEEK์ ์ ์งํ๋ฉด dangling ํฌ์ธํฐ๋ฅผ ๋ณด์กดํ์ฌ ๋ฌด์ ํ์ผ๋ก ์ฝ์ ์ ์์ต๋๋ค. - Constrained write:
MSG_PEEK๊ฐ ๋นํ์ฑํ๋์ด ์์ ๋UNIXCB(oob_skb).consumed += 1์ ์คํ์ 0x44์ 32๋นํธ ํ๋๋ฅผ ์ฆ๊ฐ์ํต๋๋ค. 0x100 ์ ๋ ฌ๋ SKB ํ ๋น์์ ์ด๊ฒ์ 8๋ฐ์ดํธ ์ ๋ ฌ๋ ๋จ์ด๋ณด๋ค 4๋ฐ์ดํธ ์์ ์์นํ์ฌ, ์์ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์คํ์ 0x40์ ํธ์คํ ๋ ์๋์ +4 GiB ์ฆ๊ฐ๋ก ๋ณํํฉ๋๋ค. ์ด๋ฅผ ์ปค๋ ์ฐ๊ธฐ๋ก ๋ฐ๊พธ๋ ค๋ฉด ํด๋น ์คํ์ ์ ๋ฏผ๊ฐํ 64๋นํธ ๊ฐ์ ๋ฐฐ์นํด์ผ ํฉ๋๋ค.
Reallocating the SKB page for arbitrary read
- Drain order-0/1 unmovable freelists: ๊ฑฐ๋ํ ์ฝ๊ธฐ ์ ์ฉ anonymous VMA๋ฅผ ๋งคํํ๊ณ ๋ชจ๋ ํ์ด์ง๋ฅผ fault ์์ผ ํ์ด์ง ํ
์ด๋ธ ํ ๋น์ ๊ฐ์ ํฉ๋๋ค (order-0 unmovable). ๋๋ต RAM์ 10% ์ ๋๋ฅผ ํ์ด์ง ํ
์ด๋ธ๋ก ์ฑ์ฐ๋ฉด ์ดํ
skbuff_head_cacheํ ๋น์ด order-0 ๋ฆฌ์คํธ๊ฐ ๊ณ ๊ฐ๋ ํ ์ ๊ท buddy ํ์ด์ง๋ฅผ ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค. - Spray SKBs and isolate a slab page: ์ฌ๋ฌ ๊ฐ์ stream socketpair๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋น ์๋ฐฑ ๊ฐ์ ์์ ๋ฉ์์ง(~0x100 ๋ฐ์ดํธ per SKB)๋ฅผ ํ์ํ์ฌ
skbuff_head_cache๋ฅผ ์ฑ์๋๋ค. ์ ํํ SKB๋ค์ ํด์ ํด ๋ชฉํ ์ฌ๋ฉ ํ์ด์ง๋ฅผ ๊ณต๊ฒฉ์ ์ ์ด ํ์ ์์ ํ ๋๊ณ , ์ฝ๊ธฐ ํ๋ฆฌ๋ฏธํฐ๋ธ๋กstruct pagerefcount๋ฅผ ๋ชจ๋ํฐ๋งํฉ๋๋ค. - Return the slab page to the buddy allocator: ํ์ด์ง์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ํด์ ํ ๋ค ์ถ๊ฐ์ ์ธ ํ ๋น/ํด์ ๋ฅผ ์ถฉ๋ถํ ์ํํด SLUB per-CPU partial ๋ฆฌ์คํธ์ per-CPU ํ์ด์ง ๋ฆฌ์คํธ์์ ํ์ด์ง๊ฐ ๋ฐ๋ ค๋๋๋ก ํ์ฌ buddy freelist์ order-1 ํ์ด์ง๊ฐ ๋๊ฒ ํฉ๋๋ค.
- Reallocate as pipe buffer: ์๋ฐฑ ๊ฐ์ pipe๋ฅผ ์์ฑํฉ๋๋ค; ๊ฐ pipe๋ ์ต์ ๋ ๊ฐ์ 0x1000-๋ฐ์ดํธ ๋ฐ์ดํฐ ํ์ด์ง(
PIPE_MIN_DEF_BUFFERS)๋ฅผ ์์ฝํฉ๋๋ค. buddy allocator๊ฐ order-1 ํ์ด์ง๋ฅผ ๋ถํ ํ ๋, ํ ์ชฝ ์ ๋ฐ์ด ํด์ ๋ SKB ํ์ด์ง๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค. ์ด๋ค pipe์ ์ด๋ค ์คํ์ ์ดoob_skb์ alias ๋๋์ง ์ฐพ๊ธฐ ์ํด ํ์ดํ ํ์ด์ง ์ ์ญ์ ๊ฐ์ง SKB์ ๊ณ ์ ๋ง์ปค ๋ฐ์ดํธ๋ฅผ ์จ๋ฃ๊ณ ๋ฐ๋ณต์ ์ผ๋กrecv(MSG_OOB | MSG_PEEK)์ ํธ์ถํด ๋ง์ปค๊ฐ ๋ฐํ๋ ๋๊น์ง ํ์ธํฉ๋๋ค. - Forge a stable SKB layout: alias๋ pipe ํ์ด์ง๋ฅผ ๊ฐ์ง
struct sk_buff๋ก ์ฑ์ ๊ทธdata/headํฌ์ธํฐ์skb_shared_info๊ตฌ์กฐ๊ฐ ๊ด์ฌ ์๋ ์์์ ์ปค๋ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ํฉ๋๋ค. x86_64์์copy_to_user()๋ด๋ถ๋ก SMAP๊ฐ ๋นํ์ฑํ๋๋ฏ๋ก, ์ปค๋ ํฌ์ธํฐ๊ฐ ์๋ ค์ง ๋๊น์ง ์ ์ ๋ชจ๋ ์ฃผ์๋ฅผ ์คํ ์ด์ง ๋ฒํผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. - Respect usercopy hardening: ์ด ๋ณต์ฌ๋
.data/.bss, vmemmap ํญ๋ชฉ, per-CPU vmalloc ๋ฒ์, ๋ค๋ฅธ ์ค๋ ๋์ ์ปค๋ ์คํ ๋ฐ ๊ณ ์ฐจ์ folio ๊ฒฝ๊ณ๋ฅผ ๋์ง ์๋ direct-map ํ์ด์ง์ ๋ํด์๋ ์ฑ๊ณตํฉ๋๋ค..text๋__check_heap_object()๊ฐ ๊ฑฐ๋ถํ๋ ํน์ ์บ์๋ฅผ ๋์์ผ๋ก ํ๋ ์ฝ๊ธฐ๋ ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์ด์ง ์๊ณ ๋จ์ํ-EFAULT๋ฅผ ๋ฐํํฉ๋๋ค.
Introspecting allocators with the read primitive
- Break KASLR:
CPU_ENTRY_AREA_RO_IDT_VADDR(0xfffffe0000000000)์ ๊ณ ์ ๋งคํ์์ ์ด๋ค IDT ๋์คํฌ๋ฆฝํฐ๋ ์ฝ๊ณ ์๋ ค์ง ํธ๋ค๋ฌ ์คํ์ ์ ๋นผ๋ฉด ์ปค๋ ๋ฒ ์ด์ค๋ฅผ ๋ณต๊ตฌํ ์ ์์ต๋๋ค. - SLUB/buddy state: ๊ธ๋ก๋ฒ
.data์ฌ๋ณผ์kmem_cache๋ฒ ์ด์ค๋ฅผ ๋๋ฌ๋ด๊ณ , vmemmap ํญ๋ชฉ์ ๊ฐ ํ์ด์ง์ ํ์ ํ๋๊ทธ, freelist ํฌ์ธํฐ ๋ฐ ์์ ์บ์๋ฅผ ๋ ธ์ถํฉ๋๋ค. per-CPU vmalloc ์ธ๊ทธ๋จผํธ๋ฅผ ์ค์บํ๋ฉดstruct kmem_cache_cpu์ธ์คํด์ค๋ฅผ ์ฐพ์ ์ฃผ์ ์บ์(skbuff_head_cache,kmalloc-cg-192๋ฑ)์ ๋ค์ ํ ๋น ์ฃผ์๋ฅผ ์์ธกํ ์ ์์ต๋๋ค. - Page tables:
mm_struct๋ฅผ ์ง์ ์ฝ๋ ๋์ (์ ์ ์นดํผ๋ก ์ฐจ๋จ๋จ) ๊ธ๋ก๋ฒpgd_list(struct ptdesc)๋ฅผ ๋ฐ๋ผ ํ์ฌmm_struct๋ฅผcpu_tlbstate.loaded_mm์ผ๋ก ๋งค์นํฉ๋๋ค. ๋ฃจํธpgd๋ฅผ ์๊ฒ ๋๋ฉด, ์ด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก ๋ชจ๋ ํ์ด์ง ํ ์ด๋ธ์ ์ํํ์ฌ pipe ๋ฒํผ, ํ์ด์ง ํ ์ด๋ธ, ์ปค๋ ์คํ์ PFN์ ๋งคํํ ์ ์์ต๋๋ค.
Recycling the SKB page as the top kernel-stack page
- ์ ์ดํ๋ pipe ํ์ด์ง๋ฅผ ๋ค์ ํด์ ํ๊ณ vmemmap์ผ๋ก ๊ทธ refcount๊ฐ 0์ผ๋ก ๋์์ค๋์ง ํ์ธํฉ๋๋ค.
- ์ฆ์ ๋ค ๊ฐ์ ํฌํผ ํ์ดํ ํ์ด์ง๋ฅผ ํ ๋นํ ๋ค ์ญ์์ผ๋ก ํด์ ํด buddy allocator์ LIFO ๋์์ ๊ฒฐ์ ๋ก ์ ์ผ๋ก ๋ง๋ญ๋๋ค.
clone()์ผ๋ก ํฌํผ ์ค๋ ๋๋ฅผ ์์ฑํฉ๋๋ค; x86_64์์ ์คํ์ ๋ค ํ์ด์ง์ด๋ฏ๋ก ์ต๊ทผ์ ํด์ ๋ ๋ค ํ์ด์ง๊ฐ ๊ทธ ์ค๋ ๋์ ์คํ์ด ๋๋ฉฐ, ๋ง์ง๋ง์ผ๋ก ํด์ ๋ ํ์ด์ง(์ด์ ์ SKB ํ์ด์ง)๋ ๋์ ์ฃผ์์ ์์นํฉ๋๋ค.- ํ์ด์ง ํ ์ด๋ธ ์ํฌ๋ก ํฌํผ ์ค๋ ๋์ ์ต์์ ์คํ PFN์ด ์ฌํ์ฉ๋ SKB PFN๊ณผ ๊ฐ์์ง ํ์ธํฉ๋๋ค.
- arbitrary read๋ก ์คํ ๋ ์ด์์์ ๊ด์ฐฐํ๋ฉด์ ์ค๋ ๋๋ฅผ
pipe_write()๋ก ์ ๋ํฉ๋๋ค.CONFIG_RANDOMIZE_KSTACK_OFFSET๋ syscall๋ง๋คRSP์์ ์ ๋ ฌ๋ 0x0โ0x3f0 ๋ฒ์์ ๋๋ค ๊ฐ์ ๋นผ๋ฏ๋ก, ๋ค๋ฅธ ์ค๋ ๋์poll()/read()์ ๊ฒฐํฉํ ๋ฐ๋ณต์ ์ธ ์ฐ๊ธฐ๋ก ์์ฑ์๊ฐ ์ํ๋ ์คํ์ ์์ ๋ธ๋ก๋ ๋๋ฅผ ์ฐพ์๋ ๋๋ค. ์ด์ด ์ข์ผ๋ฉด, ํ๋ฌ๋์จcopy_page_from_iter()์bytes์ธ์(R14)๊ฐ ์ฌํ์ฉ๋ ํ์ด์ง ๋ด ์คํ์ 0x40์ ์์นํฉ๋๋ค.
Placing fake SKB metadata on the stack
- AF_UNIX datagram ์์ผ์์
sendmsg()๋ฅผ ์ฌ์ฉํ๋ฉด: ์ปค๋์ ์ ์ ์sockaddr_un์ ์ต๋ 108๋ฐ์ดํธ๊น์ง ์คํ ์์sockaddr_storage๋ก ๋ณต์ฌํ๊ณ , ๋ถ์ ๋ฐ์ดํฐ(ancillary data)๋ฅผ syscall์ด ํ ๊ณต๊ฐ์ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ๋ธ๋ก๋๊ธฐ ์ ์ ๋ ๋ค๋ฅธ ์จ-์คํ ๋ฒํผ๋ก ๋ณต์ฌํฉ๋๋ค. ์ด๋ฅผ ํตํด ์คํ ๋ฉ๋ชจ๋ฆฌ ์์ ์ ๋ฐํ ๊ฐ์ง SKB ๊ตฌ์กฐ๋ฅผ ์ฌ์ ์ ์์ต๋๋ค. - ๋ณต์ฌ๊ฐ ๋๋ ์์ ์ ๊ฐ์งํ๋ ค๋ฉด unmapped ์ ์ ํ์ด์ง์ ์์นํ 1๋ฐ์ดํธ ์ปจํธ๋กค ๋ฉ์์ง๋ฅผ ์ ๊ณตํ์ธ์;
____sys_sendmsg()๊ฐ ์ด๋ฅผ fault ์ํค๋ฏ๋ก ๊ทธ ์ฃผ์์ ๋ํดmincore()๋ฅผ ํด๋งํ๋ ํฌํผ ์ค๋ ๋๋ ๋ชฉ์ ์ง ํ์ด์ง๊ฐ ์ค๋น๋์ ๋๋ฅผ ์ ์ ์์ต๋๋ค. CONFIG_INIT_STACK_ALL_ZERO๋ก ์ธํ 0์ผ๋ก ์ด๊ธฐํ๋ ํจ๋ฉ์ ์ฌ์ฉ๋์ง ์์ ํ๋๋ฅผ ์ฑ์ ์ถ๊ฐ ์ฐ๊ธฐ ์์ด๋ ์ ํจํ SKB ํค๋๋ฅผ ์์ฑ์์ผ ์ค๋๋ค.
Timing the +4 GiB increment with a self-looping frag list
skb_shinfo(fakeskb)->frag_list๋ฅผ ๋ ๋ฒ์งธ ๊ฐ์ง SKB(๊ณต๊ฒฉ์ ์ ์ด ์ ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ)๋ก ๊ฐ๋ฆฌํค๋๋ก ์์กฐํ๊ณ , ๊ทธ SKB๊ฐlen = 0๋ฐnext = &self๊ฐ ๋๊ฒ ํฉ๋๋ค.__skb_datagram_iter()๋ด๋ถ์์skb_walk_frags()๊ฐ ์ด ๋ฆฌ์คํธ๋ฅผ ์ํํ ๋, ์ดํฐ๋ ์ดํฐ๊ฐ NULL์ ๋๋ฌํ์ง ์์ผ๋ฏ๋ก ์คํ์ ์์ํ ํ์ ํ๊ณ ๋ณต์ฌ ๋ฃจํ๋ ์งํํ์ง ์์ต๋๋ค.- ๋ ๋ฒ์งธ ๊ฐ์ง SKB๊ฐ self-loopํ๋ ํ recv syscall์ ์ปค๋ ์์์ ์ง์์ํต๋๋ค. ์ฆ๊ฐ๋ฅผ ๋ฐ์ฌํ ์์ ์๋ ๋ ๋ฒ์งธ SKB์
nextํฌ์ธํฐ๋ฅผ ์ ์ ๊ณต๊ฐ์์NULL๋ก ๋ฐ๊พธ๋ฉด ๋ฉ๋๋ค. ๋ฃจํ๊ฐ ์ข ๋ฃ๋๊ณunix_stream_recv_urg()๋ ์ฆ์UNIXCB(oob_skb).consumed += 1์ ์คํํ์ฌ ์ฌํ์ฉ๋ ์คํ ํ์ด์ง์ ์คํ์ 0x40์ ํ์ฌ ๋ฐฐ์น๋ ๊ฐ์ฒด์ ์ํฅ์ ์ค๋๋ค.
Stalling copy_from_iter() without userfaultfd
- ๊ฑฐ๋ํ anonymous RW VMA๋ฅผ ๋งคํํ๊ณ ์ ๋ถ fault ์ํต๋๋ค.
madvise(MADV_DONTNEED, hole, PAGE_SIZE)๋ก ๋จ์ผ ํ์ด์ง ํ์ ๋ง๋ค๊ณ ๊ทธ ์ฃผ์๋ฅผwrite(pipefd, user_buf, 0x3000)์ ์ฌ์ฉ๋๋iov_iter์ ๋ฃ์ต๋๋ค.- ๋ณ๋ ฌ๋ก ๋ค๋ฅธ ์ค๋ ๋์์ VMA ์ ์ฒด์ ๋ํด
mprotect()๋ฅผ ํธ์ถํ์ธ์. ํด๋น syscall์ mmap ์ฐ๊ธฐ ๋ฝ์ ์ก๊ณ ๋ชจ๋ PTE๋ฅผ ์ํํฉ๋๋ค. ํ์ดํ ์์ฑ์๊ฐ ํ์ ๋๋ฌํ๋ฉด ํ์ด์ง ํดํธ ํธ๋ค๋ฌ๋mprotect()๊ฐ ์ก๊ณ ์๋ mmap ๋ฝ์ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ์ฐจ๋จ๋๋ฏ๋กcopy_from_iter()๋ ๊ฒฐ์ ๋ก ์ ์ธ ์์ ์์ ๋ฉ์ถ๊ณ ํ๋ฌ๋์จbytes๊ฐ์ ์ฌํ์ฉ๋ SKB ํ์ด์ง๊ฐ ํธ์คํ ํ๋ ์คํ ์ธ๊ทธ๋จผํธ์ ๋จ์ต๋๋ค.
Turning the increment into arbitrary PTE writes
- Fire the increment: frag ๋ฃจํ๋ฅผ ํด์ ํ์ฌ
copy_from_iter()๊ฐ ๋ฉ์ถ ๋์ +4 GiB ์ฆ๊ฐ๊ฐbytes๋ณ์์ ์ ์ฉ๋๊ฒ ํฉ๋๋ค. - Overflow the copy: ๊ฒฐํจ์ด ์ฌ๊ฐ๋๋ฉด
copy_page_from_iter()๋ ํ์ฌ ํ์ดํ ํ์ด์ง๋ก >4 GiB๋ฅผ ๋ณต์ฌํ ์ ์๋ค๊ณ ํ๋จํฉ๋๋ค. ํฉ๋ฒ์ ์ธ 0x2000 ๋ฐ์ดํธ(๋ ํ์ดํ ๋ฒํผ)๋ฅผ ์ฑ์ด ๋ค ์ถ๊ฐ ๋ฐ๋ณต์ ์คํํด ๋จ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ํ์ดํ ๋ฒํผ PFN ๋ค์์ ์ค๋ ๋ฌผ๋ฆฌ ํ์ด์ง์ ์๋๋ค. - Arrange adjacency: ํ ๋น์ ํ ๋ ๋ฉํธ๋ฆฌ๋ฅผ ์ด์ฉํด buddy allocator๊ฐ ํ๋ก์ธ์ค ์์ ์ PTE ํ์ด์ง๋ฅผ ๋์ ํ์ดํ ๋ฒํผ ํ์ด์ง ๋ฐ๋ก ๋ค์์ ๋๋๋ก ๊ฐ์ ํฉ๋๋ค(์: ํ์ดํ ํ์ด์ง๋ฅผ ๋ฒ๊ฐ์ ํ ๋นํ๊ณ ์ ๊ฐ์ ๋ฒ์๋ฅผ ํฐ์นํด ํ์ด์ง-ํ ์ด๋ธ ํ ๋น์ ํธ๋ฆฌ๊ฑฐํด PFN๋ค์ด ๊ฐ์ 2 MiB ํ์ด์ง๋ธ๋ก์ ์ ๋ ฌ๋๋๋ก ํจ).
- Overwrite page tables: OOB
copy_from_iter()๊ฐ ์ด์ ํ์ด์ง๋ฅผ ๊ณต๊ฒฉ์๊ฐ ์ ํํ ์ํธ๋ฆฌ๋ก ์ฑ์ฐ๊ฒ ํ๋ ค๋ฉด ์ถ๊ฐ 0x1000 ๋ฐ์ดํธ์ ์ ์ ๋ฐ์ดํฐ์ ์ํ๋ PTE ์ํธ๋ฆฌ๋ค์ ์ธ์ฝ๋ฉํ์ธ์. ์ด๋ฅผ ํตํด ์ปค๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ๋ํ RW/RWX ์ ์ ๋งคํ์ ๋ถ์ฌํ๊ฑฐ๋ ๊ธฐ์กด ์ํธ๋ฆฌ๋ฅผ ๋ฎ์ด์จ SMEP/SMAP์ ๋นํ์ฑํํ ์ ์์ต๋๋ค.
Mitigations / hardening ideas
- Kernel:
32ca245464e1479bfea8592b9db227fdc1641705์ ์ฉ( SKB๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ๊ฒ์ฆ) ๋ฐCONFIG_AF_UNIX_OOB(5155cbcdbf03)๋ฅผ ํตํด ํ์ํ์ง ์๋ค๋ฉด AF_UNIX OOB๋ฅผ ๋นํ์ฑํํ๋ ๊ฒ์ ๊ณ ๋ คํ์ธ์.manage_oob()๋ฅผ ์ถ๊ฐ์ ์ธ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฌ(์:unix_skb_len() > 0๊ฐ ๋ ๋๊น์ง ๋ฃจํ)๋ก ๊ฐํํ๊ณ ์ ์ฌํ ๊ฐ์ ์ด ์กด์ฌํ๋ ๋ค๋ฅธ ์์ผ ํ๋กํ ์ฝ์ ๊ฐ์ฌํ์ธ์. - Sandboxing: seccomp ํ๋กํ์ด๋ ์์ ๋ธ๋ก์ปค API์์
MSG_OOB/MSG_PEEKํ๋๊ทธ๋ฅผ ํํฐ๋งํ์ธ์(Chrome ๋ณ๊ฒฝ6711812๋ ๋ ๋๋ฌ ์ธกMSG_OOB๋ฅผ ์ฐจ๋จํฉ๋๋ค). - Allocator defenses: SLUB freelist ๋ฌด์์ํ ๊ฐํ๋ ์บ์๋ณ ํ์ด์ง ์ปฌ๋ฌ๋ง ๊ฐ์ ๋ ๊ฒฐ์ ๋ก ์ ํ์ด์ง ์ฌํ์ฉ์ ๋ณต์กํ๊ฒ ํฉ๋๋ค; ํ์ดํ ๋ฒํผ ์๋ฅผ ์ ํํ๋ ๊ฒ๋ ์ฌํ ๋น ์ ๋ขฐ๋๋ฅผ ์ค์ ๋๋ค.
- Monitoring: ๋์ ๋น์จ์ ํ์ด์ง-ํ ์ด๋ธ ํ ๋น์ด๋ ๋น์ ์์ ์ธ ํ์ดํ ์ฌ์ฉ์ ํ ๋ ๋ฉํธ๋ฆฌ๋ก ๋ ธ์ถํ์ธ์โ์ด ์ต์คํ๋ก์์ ๋๋์ ํ์ด์ง ํ ์ด๋ธ๊ณผ ํ์ดํ ๋ฒํผ๋ฅผ ์๋ชจํฉ๋๋ค.
References
- Project Zero โ โFrom Chrome renderer code exec to kernel with MSG_OOBโ
- Linux fix for CVE-2025-38236 (
manage_oobrevalidation) - Chromium CL 6711812 โ block
MSG_OOBin renderers - Commit adding
CONFIG_AF_UNIX_OOBprompt
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


