Copy Fail – CVE-2026-31431
(copy.fail)- ผู้ใช้ภายในเครื่องที่ไม่มีสิทธิพิเศษ สามารถเชื่อม
authencesn,AF_ALG,splice()เพื่อสร้างการ เขียน 4 ไบต์ลง page cache ของไฟล์ที่อ่านได้ และยกระดับสิทธิ์ไปจนถึง root ได้ - ทำงานได้เหมือนกันบน Linux หลายดิสทริบิวชันด้วย สคริปต์ Python ขนาด 732 ไบต์ เพียงไฟล์เดียว โดยไม่ต้องพึ่ง offset เฉพาะเคอร์เนลหรือ race condition และใช้ exploit เดียวกันเพื่อให้ได้ root shell
- ขอบเขตผลกระทบครอบคลุม ดิสทริบิวชัน Linux หลักเกือบทั้งหมด ที่ยังไม่แพตช์ และเนื่องจาก
AF_ALGเปิดใช้งานในค่าตั้งต้น จึงเปิดช่องมาตั้งแต่ปี 2017 จนถึงช่วงที่ออกแพตช์ - ในโฮสต์แบบ multi-tenant, Kubernetes / คลัสเตอร์คอนเทนเนอร์, CI runner และ Cloud SaaS ที่รันโค้ดผู้ใช้ บัญชีธรรมดาหรือ pod เดียวอาจนำไปสู่สิทธิ์ root บนโฮสต์ได้ จึงควรเร่งแพตช์ก่อน
- วิธีรับมืออันดับแรกคือ แพตช์เคอร์เนล ที่มี mainline commit
a664bf3d603dและก่อนจะแพตช์ควรปิดalgif_aeadพร้อม บล็อกAF_ALGสำหรับ workload ที่ไม่น่าเชื่อถือ
ภาพรวมช่องโหว่
- ความผิดพลาดเชิงตรรกะแบบ เส้นตรงเพียงจุดเดียว เมื่อเชื่อมกับ
authencesn,AF_ALG,splice()สามารถนำไปสู่การ เขียน 4 ไบต์ลง page cache และทำให้เกิดการยกระดับสิทธิ์ภายในเครื่องได้ - ใช้งานได้เหมือนกันกับ Linux ดิสทริบิวชันจำนวนมากที่ออกตั้งแต่ปี 2017 เป็นต้นมา ด้วย สคริปต์ Python ขนาด 732 ไบต์ เพียงไฟล์เดียว โดยไม่ต้องมี offset เฉพาะเคอร์เนลหรือ race window
- exploit binary เดียวกันสามารถใช้เพื่อให้ได้ root shell บนหลายดิสทริบิวชันโดยไม่ต้องแก้ไข
- ต้องการเพียงบัญชี local ที่ไม่มีสิทธิพิเศษเท่านั้น ไม่ต้องเข้าถึงเครือข่าย ไม่ต้องมีความสามารถด้าน kernel debugging และไม่ต้องมี primitive อื่นติดตั้งไว้ล่วงหน้า
ขอบเขตผลกระทบ
- ดิสทริบิวชัน Linux หลักเกือบทั้งหมด ที่ใช้เคอร์เนลซึ่งยังไม่แพตช์อยู่ในขอบเขตผลกระทบ
- เพราะ
AF_ALGของ kernel crypto API ถูกเปิดไว้โดยปริยายในแทบทุกดิสทริบิวชันกระแสหลัก ระบบจึงเปิดรับช่องโหว่นี้โดยตรงตั้งแต่ปี 2017 จนถึงเวลาที่มีแพตช์ - ดิสทริบิวชันที่ตรวจสอบโดยตรงแล้วได้แก่ Ubuntu 24.04 LTS, Amazon Linux 2023, RHEL 14.3 และ SUSE 16
- Debian, Arch, Fedora, Rocky, Alma, Oracle รวมถึงสาย embedded ก็ได้รับผลกระทบเช่นกันหากใช้เคอร์เนลที่ได้รับผลกระทบ
สภาพแวดล้อมที่ควรเร่งแพตช์ก่อน
- บน โฮสต์ Linux แบบ multi-tenant ผู้ใช้หลายรายแชร์เคอร์เนลเดียวกัน ทำให้บัญชีผู้ใช้ธรรมดาสามารถกลายเป็น root ได้โดยตรง
- ใน Kubernetes / คลัสเตอร์คอนเทนเนอร์ page cache ถูกแชร์ทั้งโฮสต์ ดังนั้น pod เดียวอาจยึด node และข้ามขอบเขตผู้เช่าได้
- ใน CI runner และ build farm โค้ดจาก PR ที่ไม่น่าเชื่อถือซึ่งรันด้วยสิทธิ์ผู้ใช้ธรรมดา อาจยกระดับเป็น root บน runner ได้
- ใน Cloud SaaS ที่รันโค้ดผู้ใช้ คอนเทนเนอร์หรือสคริปต์ที่ผู้เช่าอัปโหลดอาจนำไปสู่ root บนโฮสต์ได้
- เซิร์ฟเวอร์แบบ single-tenant มีลักษณะเป็น LPE ภายในเป็นหลัก และอาจเชื่อมกับเว็บ RCE หรือ credential ที่ถูกขโมยมาได้
- โน้ตบุ๊กและเวิร์กสเตชันผู้ใช้คนเดียวมีความเร่งด่วนน้อยกว่า แต่การรันโค้ดในเครื่องก็ยังอาจนำไปสู่การยกระดับเป็น root ได้
PoC ที่เผยแพร่และวิธีใช้งาน
- มีการเผยแพร่ PoC เพื่อให้ฝั่งป้องกันใช้ตรวจสอบระบบและยืนยันแพตช์จากผู้จำหน่ายได้
copy_fail_exp.pyใช้เพียงไลบรารีมาตรฐานของ Python 3.10+ ได้แก่os,socket,zlib- เป้าหมายตั้งต้นคือ
/usr/bin/suและสามารถส่ง setuid binary อื่นผ่านargv[1]ได้ - มันแก้ไข setuid binary ภายใน page cache และแม้การเปลี่ยนแปลงจะไม่คงอยู่หลังรีบูต แต่ root shell ที่ได้มาสามารถใช้งานได้จริง
- Issue tracker
วิธีบรรเทา
- สิ่งสำคัญอันดับแรกคือ แพตช์เคอร์เนล โดยต้องอัปเดตไปใช้เคอร์เนลดิสทริบิวชันที่รวม mainline commit
a664bf3d603dแล้ว - แพตช์นี้ย้อนการเพิ่มประสิทธิภาพแบบ in-place ของ
algif_aeadที่ถูกนำเข้ามาตั้งแต่ปี 2017 เพื่อไม่ให้หน้า page cache เข้าไปอยู่ใน writable destination scatterlist - ก่อนมีแพตช์ แนะนำให้ ปิดโมดูล
algif_aeadecho "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.confrmmod algif_aead 2>/dev/null || true
- ในคอนเทนเนอร์ sandbox และ CI ที่รัน workload ที่ไม่น่าเชื่อถือ ควร บล็อกการสร้าง socket
AF_ALGด้วย seccomp ไม่ว่าจะมีแพตช์แล้วหรือไม่ก็ตาม
ผลกระทบเมื่อปิดใช้งาน
- สำหรับระบบส่วนใหญ่ แทบไม่มีผลกระทบที่วัดได้
dm-crypt / LUKS,kTLS,IPsec/XFRM, in-kernel TLS, OpenSSL/GnuTLS/NSS แบบ build ปกติ, SSH และ kernel keyring crypto ไม่ได้รับผลกระทบ- สิ่งเหล่านี้ใช้ kernel crypto API โดยตรงและไม่ได้ผ่านเส้นทาง
AF_ALG
- สิ่งเหล่านี้ใช้ kernel crypto API โดยตรงและไม่ได้ผ่านเส้นทาง
- หากเปิดใช้เอนจิน
afalgใน OpenSSL แบบชัดเจน, ใช้เส้นทาง embedded crypto offloading บางแบบ หรือมีแอปพลิเคชันที่ bind socketaead/skcipher/hashโดยตรง ก็อาจได้รับผลกระทบ- ตรวจสอบได้ด้วย
lsof | grep AF_ALGหรือss -xa
- ตรวจสอบได้ด้วย
- การปิด
AF_ALGจะไม่ทำให้เป้าหมายที่เดิมไม่ได้เรียกใช้งานมันช้าลง และเป้าหมายที่ใช้งานอยู่จะย้อนกลับไปใช้ไลบรารีเข้ารหัสใน userspace ตามปกติ
จุดที่ต่างจาก Linux LPE ทั่วไป
- ต่างจาก Linux LPE ทั่วไปตรงที่ ไม่มี race condition และไม่ต้องใช้ offset แยกตามดิสทริบิวชัน
- ยังระบุว่ามีความน่าเชื่อถือ ยิงครั้งเดียวสำเร็จ 100% และครอบคลุมช่วงเวลายาวตั้งแต่ปี 2017 ถึง 2026 ไม่ใช่แค่ช่วงเวอร์ชันเคอร์เนลแคบ ๆ
- ด้วยขนาดเพียง 732 ไบต์ และใช้แค่ไลบรารีมาตรฐานของ Python จึงไม่ต้องมี payload ที่คอมไพล์แล้วหรือ dependency เพิ่มเติม
- เส้นทางการเขียน ข้าม VFS และ page ที่ถูกทำให้เสียหายจะไม่ถูกทำเครื่องหมาย dirty จึงไม่มีการเขียนอะไรลงดิสก์
- เนื่องจาก page cache ถูกแชร์ทั้งโฮสต์ มันจึงทำงานได้มากกว่าแค่ LPE ธรรมดา แต่ยังเป็น primitive สำหรับ container escape ได้ด้วย
หลักการทำงานและลักษณะการตรวจจับ
- ผู้ใช้ภายในเครื่องที่ไม่มีสิทธิพิเศษสามารถเขียน 4 ไบต์ที่ควบคุมได้ลงใน page cache ของไฟล์ที่อ่านได้ บนระบบ Linux และนำไปใช้เพื่อให้ได้สิทธิ์ root
- เป้าหมายคือ page cache ในหน่วยความจำ ไม่ใช่ไฟล์จริงบนดิสก์ และถ้าแก้สำเนาในแคชของ
/usr/bin/suจากมุมมองของexecveก็เทียบเท่ากับการเปลี่ยนตัวไบนารีเอง - เพราะไม่มีการเปลี่ยนแปลงบนดิสก์
inotifyจึงไม่แจ้งเตือน และหลังรีบูตหรือเมื่อ cache ถูกขับออก ไฟล์ต้นฉบับจะถูกโหลดกลับมาใหม่ - เครื่องมือแฮชทั่วไปอย่าง
sha256sum, AIDE, Tripwire จะอ่าน page cache ผ่านread()ดังนั้น ตราบใดที่ความเสียหายยังคงอยู่ในแคช ค่าแฮชอาจไม่ตรงกับค่าอ้างอิง - เมื่อ cache ถูกขับออกหรือรีบูต ค่าแฮชจะกลับมาตรงกับต้นฉบับอีกครั้ง และใน forensic image ของดิสก์ก็จะเหลือเพียงไฟล์ที่ยังไม่ถูกแก้ไข
- ใน IMA appraisal enforcing mode หากเปิด every-read measurement ก็สามารถตรวจจับได้ที่จุด
execveก่อนที่ไบนารีที่เสียหายจะถูกรัน
ความต่างจากช่องโหว่อื่น
- อยู่ในตระกูลเดียวกับ Dirty Pipe ตรงที่ userspace ที่ไม่มีสิทธิพิเศษสามารถทำให้ page cache เสียหายและเขียนลง setuid binary เพื่อเอา root ได้โดยไม่เปลี่ยนข้อมูลบนดิสก์
- แต่กลไกต่างกัน โดย Dirty Pipe ใช้ประโยชน์จาก pipe buffer flags ส่วน Copy Fail ใช้ประโยชน์จาก AEAD scratch write ที่ข้ามขอบเขต chained scatterlist
- Dirty Pipe ต้องอาศัยเคอร์เนล 5.8 ขึ้นไปที่มีแพตช์บางตัวเข้าไปแล้ว แต่ Copy Fail ครอบคลุมช่วงตั้งแต่ปี 2017 ถึง 2026
- ต่างจาก Dirty Cow ตรงที่ไม่ต้องชนะ COW race แบบ TOCTOU ไม่ต้องลองหลายครั้ง และไม่ทำให้ระบบไม่เสถียร
รายละเอียดเพิ่มเติม
/usr/bin/suไม่ใช่ข้อบังคับ หากเป็น setuid-root binary ที่ผู้ใช้อ่านได้ ก็ใช้กับpasswd,chsh,chfn,mount,sudo,pkexecได้เช่นกัน- ไม่ใช่ช่องโหว่ระยะไกล และต้องมี การรันโค้ดในเครื่องด้วยสิทธิ์ผู้ใช้ทั่วไป ก่อน
- หากเว็บ RCE ตกมาที่บัญชีบริการที่ไม่มีสิทธิพิเศษ หรือเชื่อมกับ SSH foothold, PR อันตรายบน CI runner ก็สามารถนำไปสู่ root ได้
- แพตช์จะย้อนการเพิ่มประสิทธิภาพแบบ in-place ของ
algif_aeadทำให้req->srcและreq->dstกลับไปเป็น scatterlist ที่แยกกัน - หน้า page cache จะคงอยู่เฉพาะใน source แบบอ่านอย่างเดียว ส่วนปลายทางที่ crypto เขียนได้จะเหลือเพียง user buffer
กำหนดการเปิดเผยและข้อมูลติดตาม
- 2026-03-23 มีการรายงานไปยังทีมความปลอดภัยของ Linux kernel
- 2026-03-24 มีการยืนยันเบื้องต้น
- 2026-03-25 มีการเสนอและทบทวนแพตช์
- 2026-04-01 แพตช์ถูก commit เข้า mainline
- 2026-04-22 มีการกำหนด CVE-2026-31431
- 2026-04-29 เปิดเผยที่ https://copy.fail/
- บทวิเคราะห์ทางเทคนิคจาก Xint blog
- มี root cause, แผนภาพ scatterlist, ลำดับเหตุการณ์ปี 2011→2015→2017 และ walkthrough ของ exploit
- Part 2 ที่จะพูดถึงการหนีออกจากคอนเทนเนอร์ใน Kubernetes จะเผยแพร่ภายหลัง
ข้อมูลเกี่ยวกับ Xint Code
- ค้นพบด้วยวิธี AI-assisted โดยจุดตั้งต้นคือการวิจัยของมนุษย์ที่ตั้งข้อสังเกตว่า
splice()ส่งหน้า page cache เข้าไปยัง crypto subsystem และแหล่งที่มาของ page ใน scatterlist อาจเป็นคลาสบั๊กที่ยังถูกสำรวจไม่มาก - จากนั้น Xint Code ได้ขยายการตรวจสอบไปยัง subsystem
crypto/ทั้งหมดของ Linux ในระดับเวลาประมาณ 1 ชั่วโมง และรายการที่ ร้ายแรงที่สุด จากผลลัพธ์นั้นก็คือ Copy Fail - Xint Code
- Xint blog write-up
- จากการสแกนเดียวกันยังพบบั๊กความเสี่ยงสูงอื่น ๆ อีก ซึ่งยังอยู่ระหว่าง coordinated disclosure
ยังไม่มีความคิดเห็น