Xz: อักขระเพียงตัวเดียวที่ทำให้ Linux Landlock ใช้งานไม่ได้
(git.tukaani.org)- การเปลี่ยนแปลง CMakeLists.txt ของ xz.git เป็นกรณีที่มีอักขระ
.เดี่ยว ๆ อยู่ในโค้ดทดสอบ ระหว่างการเปลี่ยนการตรวจจับแซนด์บ็อกซ์ Landlock จากการตรวจว่ามีเฮดเดอร์อยู่หรือไม่ ไปเป็นการทดสอบคอมไพล์จริง - การตรวจสอบใหม่นี้เพิ่มเข้ามาเพื่อคัดกรองระบบที่แม้จะมี
linux/landlock.hแต่ก็อาจไม่มี นิยาม syscall ที่จำเป็น - การทดสอบคอมไพล์รวม
<linux/landlock.h>,<sys/syscall.h>,<sys/prctl.h>และอ้างอิงprctl,SYS_landlock_create_ruleset,SYS_landlock_restrict_self,LANDLOCK_CREATE_RULESET_VERSION - เกณฑ์เดิม
HAVE_LINUX_LANDLOCK_Hถูกเปลี่ยนเป็น HAVE_LINUX_LANDLOCK และการตั้งค่าSANDBOX_COMPILE_DEFINITIONกับSANDBOX_FOUNDก็เป็นไปตามผลลัพธ์นี้ด้วย - คอมมิตนี้เป็นการแก้ไข Linux Landlock feature test ของบิลด์ Autotools และ CMake โดย diff ที่ให้มาแสดงการเปลี่ยนแปลงฝั่ง CMake
การเปลี่ยนวิธีตรวจจับ Landlock ของ CMake
- ไฟล์เป้าหมายคือ CMakeLists.txt ของ xz.git และจุดที่เปลี่ยนแปลงอยู่ในบล็อก
# Sandboxing: Landlock - ลอจิก CMake เดิม เมื่อ
ENABLE_SANDBOXเป็นONหรือlandlockและยังไม่ใช่SANDBOX_FOUNDจะตรวจเฉพาะการมีอยู่ของเฮดเดอร์ด้วยcheck_include_file(linux/landlock.h HAVE_LINUX_LANDLOCK_H) - หลังการเปลี่ยนแปลง จะใช้
check_c_source_compilesเพื่อคอมไพล์โค้ด C ขนาดเล็กจริง ๆ และตรวจสอบว่า Landlock ใช้งานได้หรือไม่- บางระบบอาจมี
linux/landlock.hแต่ไม่มีนิยาม syscall ที่จำเป็นสำหรับ Linux Landlock - โค้ดทดสอบรวม
<linux/landlock.h>,<sys/syscall.h>,<sys/prctl.h> - ภายใน
my_sandbox()อ้างอิงprctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0),SYS_landlock_create_ruleset,SYS_landlock_restrict_self,LANDLOCK_CREATE_RULESET_VERSION
- บางระบบอาจมี
อักขระเดี่ยวและการเปลี่ยนชื่อตัวแปร
- มีบรรทัด
.เดี่ยว ๆ อยู่หลังบล็อก include ในโค้ดทดสอบคอมไพล์ที่ถูกแทรกเข้ามา - ตัวแปรผลลัพธ์ถูกเปลี่ยนจาก
HAVE_LINUX_LANDLOCK_Hเป็น HAVE_LINUX_LANDLOCK - เงื่อนไขก็เปลี่ยนจาก
if(HAVE_LINUX_LANDLOCK_H)เป็นif(HAVE_LINUX_LANDLOCK)ด้วย - ค่า
SANDBOX_COMPILE_DEFINITIONใช้"HAVE_LINUX_LANDLOCK"แทน"HAVE_LINUX_LANDLOCK_H" - หลังจากนั้น การตั้งค่า
SANDBOX_FOUND ONยังคงเดิม
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
คำตอบ: https://git.tukaani.org/?p=xz.git;a=commitdiff;h=f9cf4c05edd...
ถ้าไม่คุ้นกับ ระบบควบคุมการเข้าถึง Landlock ของ Linux มีคำอธิบายอยู่ที่นี่: https://docs.kernel.org/userspace-api/landlock.html
หน้าอย่างเป็นทางการของ xz สำหรับการรับมือเหตุการณ์นี้ (น่าจะ...): https://tukaani.org/xz-backdoor/
แต่เพราะมี จุดเล็ก ๆ เพียงจุดเดียว ติดอยู่ใกล้ขอบซ้ายของ diff จนสังเกตยาก ทำให้ C โค้ดใช้ไม่ได้เสมอ และสุดท้าย Landlock ก็ถูกปิดไว้ตลอดงั้นหรือ?
น่าประทับใจแบบชั่วร้าย และชั่วร้ายจนน่าประทับใจ ตอนอ่านครั้งแรกฉันก็ไม่เห็นเหมือนกัน
ถ้าจะซ่อนจริง ยังมีวิธีที่ดีกว่านี้ เช่นสลับเป็นอักขระ Unicode ที่หน้าตาคล้ายกัน บางตัวดูเหมือนกันถึงระดับพิกเซลขึ้นอยู่กับฟอนต์
ฉันอาจตามเรื่องไม่ทัน แต่ตอนนี้ยืนยันได้แล้วหรือว่านี่เป็นการจงใจ?
ฉันไล่อ่านอย่างระวัง แล้วเห็นจุดอยู่ในตำแหน่งที่ไม่ควรมี เลยคิดว่า “ไม่ยากอย่างที่คิดนี่นา”
จากนั้นก็แตะหน้าจอเบา ๆ แล้วจุดนั้นขยับ
ที่แท้เป็น ฝุ่นบนจอ บ้าจริง
ไม่น่าเชื่อว่าความปลอดภัยของระบบจะพึ่งพา ห่วงโซ่ความถูกต้อง ที่เปราะบางขนาดนี้ ทั้งที่มีหลายจุดที่น่าจะป้องกันได้
+ # A compile check is done here because some systems have+ # linux/landlock.h, but do not have the syscalls defined+ # in order to actually use Linux Landlock.ควรแก้ header ของระบบเหล่านั้นให้ถูกตัดออกอย่างชัดเจน ถ้า header ไม่ประกาศความสามารถของตัวเอง แล้วมันจะมีความหมายอะไร?
และฉันก็ไม่เข้าใจด้วยว่าทำไมหลังจากสร้าง binary blob แล้ว (แม้จะคอมไพล์จากโอเพนซอร์สก็ตาม) ถึงไม่มีการทดสอบเลยว่าความปลอดภัยยังสมบูรณ์อยู่
ต่อให้เป็นระบบจ่ายเงินบนเว็บไซต์ ก็คงไม่ปล่อยขึ้นใช้งานโดยไม่มีการทดสอบแบบ end-to-end สำหรับฟังก์ชันหลัก
ดูเหมือนมี ความไม่สอดคล้องของลำดับความสำคัญ ที่ให้ความสำคัญกับการเพิ่มฟีเจอร์มากกว่าความมั่นคง
หวังว่าการแก้ไขจะไม่ใช่แค่ลบ
.ออกไปเฉย ๆ เพิ่งเห็นอีกโพสต์ใน HN ที่แสดงการลบ.นั้นเองการแก้ header หรือเพิ่มการทดสอบก็คงกันไม่ได้อยู่ดี เพราะไม่มีสัญญาณว่า header พังตั้งแต่ต้น และการทดสอบเพิ่มก็อาจถูกทำให้เสียหายด้วยวิธีอื่น หรือถูกเพิกเฉยใน release tarball ได้
[1] https://git.tukaani.org/?p=xz.git;a=commit;h=328c52da8a2bbb8...
เพราะผู้ใช้อาจพยายามคอมไพล์ด้วย GCC 9.4.0 และฟีเจอร์ที่พึ่งพา header นั้นก็ไม่ใช่ส่วนสำคัญของแอปพลิเคชัน ถ้าระบบ build ตรวจพบว่า header พัง ก็แค่ปิดฟีเจอร์นั้นแล้วแสดงคำเตือน
กลับมาที่ xz ถ้าความปลอดภัยไม่ใช่ลำดับความสำคัญสูงสุด การเพิกเฉยต่อความล้มเหลวของฟีเจอร์ทางเลือกแล้วเดินหน้าต่อก็ดูสมเหตุสมผลอยู่ แน่นอนว่าหลังรู้ผลแล้วชี้นิ้วโทษกันเป็นเรื่องง่าย แต่ถ้าตัดบริบทนั้นออก การตัดสินใจนี้ก็ไม่ได้ไร้เหตุผลเสียทีเดียว
แย่ล่ะ คอมมิตสุดท้ายของเขากลับทำให้ รายงานด้านความปลอดภัย แย่ลงอีก: https://git.tukaani.org/?p=xz.git;a=commitdiff;h=af071ef7702...
Landlock ถูกออกแบบมาให้ใช้ที่ไหน/อย่างไร?
ในไลบรารีอเนกประสงค์อย่างพวกบีบอัด/คลายบีบอัด ดูเหมือนจะใช้งานจริงได้ยาก
ไลบรารีไม่สามารถรู้ได้ว่าโปรแกรมต้องทำอะไร และควรจำกัดอะไรบ้าง
ถ้าเป็นตัวโปรแกรมเอง เรื่องนี้อาจชัดเจนกว่า
การโจมตี sshd ใช้ liblzma เป็นไลบรารี ถ้าอย่างนั้นการปิด Landlock ก็ดูเหมือนไม่เกี่ยวกัน? หรือว่านี่เป็นสัญญาณว่ายังมีโค้ดไม่ดีอื่นที่ยังไม่ถูกพบ หรือเคยวางแผนจะใส่เพิ่มภายหลัง?
ถ้าเอา Landlock ออก เดมอนก็จะไม่ล็อกตัวเอง ทำให้รัน payload ได้ง่ายขึ้นเมื่อไปถึงขั้นตอนการโจมตี
ผมไม่คิดว่าสองเรื่องนี้ไม่เกี่ยวกัน ดูเหมือนว่ามีการคิดถึง payload ไว้แล้ว และรู้ว่านี่จะเป็นอุปสรรค
ได้ประโยชน์น้อย แต่กลับเพิ่มความเสี่ยงที่จะถูกจับได้อย่างมาก
เหตุการณ์นี้ชวนสับสนมาก บางส่วนประณีตจนน่าไม่เชื่อ แต่อีกหลายส่วนกลับดูค่อนข้างหลวม
แนวคิดคือให้ไลบรารีเริ่มงานที่ซับซ้อนในเธรดแยก แล้วให้โค้ดฝั่งผู้ใช้รอเธรดนั้นภายใน API ที่เรียกใช้
เธรดนั้นจะบังคับใช้ Landlock กับตัวเองก่อนเริ่มงาน ถ้ามีอะไรผิดพลาด โค้ดก็จะถูกกักไว้
แน่นอนว่าในกรณีนี้ใช้ไม่ได้ เพราะ sandbox อยู่ภายใต้การควบคุมของผู้โจมตี เขาจึงปิดมันหรือทำให้มันอ่อนแอกว่าเดิมได้ แต่ก็ยังมีวิธีอื่นที่ทำได้
ตกลงแล้วที่นี่ตั้งใจจะทำอะไรกันแน่? หรือว่าจะใส่แบ็กดอร์เพิ่มทีหลัง ใส่แบบที่ปฏิเสธได้แนบเนียนกว่านี้? ในมุมมองผม ทั้ง oss-fuzz และการเปลี่ยนแปลงนี้ก็คงไม่สามารถค้นหาแบ็กดอร์ที่ถูกพบจริงได้อยู่ดี
แล้วทำไมถึงเอาไข่แบ็กดอร์ทั้งหมดใส่ไว้ในตะกร้าใบเดียว คือในไลบรารีตัวเดียว?
อีกอย่างคือเป้าหมายไม่ใช่ทำแบ็กดอร์ที่ตัวไลบรารีเอง แต่ใช้มันเป็นทางไปเล่นงานเครื่องมือที่นำมันไปใช้
เป็นสไตล์ “Reflections on trusting trust”
ฟังดูเหมือนแผนที่สมบูรณ์แบบ จนกระทั่งมันล้มเหลว
สงสัยว่าทำไมการกันไม่ให้ Landlock ถูกเปิดใช้ใน xz ถึงมีประโยชน์ อาจตั้งใจจะฉีดเนื้อหามุ่งร้ายเข้าไปในอาร์ไคฟ์ xz ในขั้นหลังหรือเปล่า? ถ้าอย่างนั้นทำไมไม่ใส่พฤติกรรมมุ่งร้ายลงใน xz ไปตรงๆ เลย?
การแอบใส่บัฟเฟอร์โอเวอร์โฟลว์หรือ use-after-free ในโปรเจ็กต์ C ที่ดูแลอยู่อาจทำได้โดยไม่ถูกจับได้
แต่การปล่อยโทรจันจริงนั้นยากกว่ามาก และกรณีแบ็กดอร์ xz-to-sshd ก็แสดงให้เห็นแบบนั้น
เห็นได้ชัดว่าเป้าหมายคือ ความลับแนบเนียน
อันนี้กลับเด่นเกินคาด เทคนิคปิดฟีเจอร์ถือว่าฉลาด และคอมมิตก็ดูน่าเชื่อถือพอสมควร แต่ทำไมถึงเลือก ข้อผิดพลาดทางไวยากรณ์ ที่ชัดเจน แทนที่จะสะกดผิดธรรมดา? เช่น ถ้าพลาดเป็น
PR_SET_NO_NEW_PRIVคนจะสังเกตไหม?แบบนั้นก็ดูปฏิเสธความตั้งใจได้มากกว่าด้วย
อีกเรื่องหนึ่ง ทีมมัลแวร์ นี้ได้สร้างชุดข้อมูลชั้นยอดสำหรับฝึก AI ให้ระบุปัญหาความปลอดภัย
ทุกคอมมิตมีปัญหาด้านความปลอดภัย และชุมชนโอเพนซอร์สก็กำลังไล่ตรวจทีละอันเพื่อหามัน
ขอบคุณผู้ดูแลที่กำลังทำงานเก็บกวาดอยู่ คงไม่ใช่งานที่สนุกแน่
เพราะแบบนี้เองผมถึงไม่ชอบ ระบบ build แบบ configure ที่เปิดปิดฟีเจอร์อัตโนมัติเท่าไร ถ้าต้องการอะไร ผมอยากเปิดมันอย่างชัดเจน
ถ้ามีเหตุผลดีพอที่จะให้ฟีเจอร์เปิดเป็นค่าเริ่มต้น ก็ควรให้ปิดมันได้อย่างชัดเจนแทน
ก็ต้องย้อนกลับไปเพิ่มใหม่ แล้วจากนั้นผู้ใช้ก็มารายงานว่าไม่มีฟีเจอร์ Z อีก
แค่มีชุดฟีเจอร์พื้นฐาน แล้วเปิดทางให้ใช้
--enable-a --disable-bตามต้องการก็น่าจะพอการกลืนข้อผิดพลาดในขั้นตรวจสอบไปแบบเงียบๆ ก็เป็นอีกปัญหาหนึ่ง