Chrome แก้ไขช่องโหว่ heap buffer overflow ของ WebP
(chromereleases.googleblog.com)- มีการปล่อยอัปเดต Chrome ช่อง Stable และ Extended Stable บนเดสก์ท็อป ซึ่งรวมการแก้ไขช่องโหว่ WebP heap buffer overflow
- บิลด์ใหม่คือ 116.0.5845.187 บน Mac และ Linux และ 116.0.5845.187/.188 บน Windows โดยจะทยอยปล่อยภายในช่วงตั้งแต่ไม่กี่วันถึงหลายสัปดาห์
- การแก้ไขด้านความปลอดภัยในรีลีสนี้มี 1 รายการ และ CVE-2023-4863 ถูกจัดเป็นระดับ Critical
- Apple SEAR และ The Citizen Lab แห่ง Munk School, University of Toronto รายงานช่องโหว่นี้เมื่อวันที่ 6 กันยายน 2023
- Google ระบุว่ามี กรณีการนำไปใช้โจมตีจริง และการเข้าถึงรายละเอียดบั๊กอาจถูกจำกัดจนกว่าจะติดตั้งเวอร์ชันที่แก้ไขแล้ว
อัปเดตช่อง Chrome บนเดสก์ท็อป
- ช่อง Stable และ Extended Stable ได้รับการอัปเดตเป็นบิลด์ใหม่สำหรับเดสก์ท็อป
- เวอร์ชันของช่อง Stable แยกตามแพลตฟอร์มมีดังนี้
- Mac: 116.0.5845.187
- Linux: 116.0.5845.187
- Windows: 116.0.5845.187/.188
- ช่อง Extended Stable ก็ถูกปล่อยเป็นเวอร์ชันแยกเช่นกัน
- Windows: 116.0.5845.188
- Mac: 116.0.5845.187
- อัปเดตจะทยอยปล่อย ภายในไม่กี่วันถึงหลายสัปดาห์
- ดูรายการการเปลี่ยนแปลงทั้งหมดของบิลด์นี้ได้ที่ log
การแก้ไขด้านความปลอดภัย: CVE-2023-4863
- รีลีสนี้มี การแก้ไขด้านความปลอดภัย 1 รายการ
- การแก้ไขสำคัญที่มีผู้วิจัยภายนอกมีส่วนร่วมคือช่องโหว่ต่อไปนี้
- Critical CVE-2023-4863: heap buffer overflow ใน WebP
- หมายเลขบั๊ก: 1479274
- ผู้รายงาน: Apple Security Engineering and Architecture(SEAR), The Citizen Lab แห่ง Munk School, University of Toronto
- วันที่รายงาน: 6 กันยายน 2023
- มูลค่ารางวัล: $NA
การโจมตีที่เกิดขึ้นจริงและข้อจำกัดการเปิดเผยข้อมูล
- Google ระบุว่ามี exploit ของ CVE-2023-4863 อยู่ในสภาพแวดล้อมจริง
- การเข้าถึงรายละเอียดบั๊กและลิงก์ที่เกี่ยวข้องอาจถูกจำกัดจนกว่าผู้ใช้ส่วนใหญ่จะอัปเดตเป็นเวอร์ชันที่แก้ไขแล้ว
- ข้อจำกัดนี้อาจยังคงอยู่ หากบั๊กเดียวกันนั้นอยู่ใน ไลบรารีของบุคคลที่สาม ที่โปรเจกต์อื่นพึ่งพาและยังไม่ได้รับการแก้ไข
ช่องทางตรวจพบและรายงานบั๊กความปลอดภัย
- บั๊กด้านความปลอดภัยจำนวนมากถูกตรวจพบด้วยเครื่องมือต่อไปนี้
- วิธีสลับช่องรีลีสดูได้จาก คู่มือ Chromium release channels
- สามารถรายงานประเด็นใหม่ได้ที่ crbug.com และขอความช่วยเหลือได้ที่ Chrome community help forum
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ใน Google Chrome รูปภาพ WebP จะถูกถอดรหัสใน โปรเซสเรนเดอร์เรอร์ ดังนั้นแม้ exploit จะสำเร็จ ก็ทำได้เพียงรันโค้ดของเรนเดอร์เรอร์ภายใน sandbox เท่านั้น
เรนเดอร์เรอร์มีความซับซ้อนมาก จึงพบ exploit จำนวนมากทุกปี แต่ถึงจะได้สิทธิ์รันโค้ดในเรนเดอร์เรอร์ ก็แทบไม่เกินสิทธิ์ที่เว็บเพจทั่วไปมีอยู่
โดยเฉพาะอย่างยิ่ง ไม่สามารถดูหรือทิ้งไฟล์ไว้ในไฟล์ซิสเต็มภายในเครื่องได้ และไม่สามารถอ่านคุกกี้ของโดเมนอื่นได้ด้วย
ไม่ได้เป็นเรื่องที่ต้องให้ความสำคัญสูงสุดทันที แต่ถ้า exploit แบบนั้นไม่ได้กำลังแพร่ระบาดอยู่จริง ก็ควรแพตช์ให้เร็วที่สุดเท่าที่ทำได้ในช่วงเวลาที่ไม่ทำให้ลำบากมากนัก
ในแง่ที่ไม่ได้ผูกติดกับไซต์หรือฟรอนต์เอนด์ใดไซต์หนึ่ง มันใกล้เคียงกับ XSS เวอร์ชันเสริมพลัง
อ้อ ผมตอบผิดเธรด ตั้งใจจะตอบข้อความ “jpeg is good enough” ใน https://news.ycombinator.com/item?id=37479576
แล้วถึงจะปิด JavaScript ไว้ อยู่ ๆ เว็บไซต์ก็ยังสามารถรันโค้ดได้อยู่ดีไม่ใช่หรือ?
เลยยิ่งเข้าใจมากขึ้นว่าทำไมนักพัฒนาเบราว์เซอร์ถึงช้าในการ นำฟอร์แมตใหม่มาใช้
WebP ไม่ได้มีข้อได้เปรียบเหนือ JPEG มากนัก ส่วนใหญ่ก็แค่เรื่องความโปร่งใส และความสำเร็จก็ยังจำกัด
แต่ตอนนี้กลับนำไปสู่ช่องโหว่ความปลอดภัยระดับความสำคัญสูงหลายรายการ และทุกที่ที่ลิงก์กับ libwebp คงต้องปล่อยแพตช์กันตลอดเดือนข้างหน้า
ไม่ได้หมายความว่าไม่ควรทำของใหม่ แต่ผมคิดว่านักพัฒนามักประเมินต้นทุนต่ำไปค่อนข้างมาก
จริงอยู่ที่ระบบนิเวศของ WebP ยังสุกงอมน้อยกว่ามาก แต่ผมมั่นใจว่าโค้ดที่จัดการฟอร์แมตเก่ากว่าก็มีปัญหาด้านความปลอดภัยอยู่ไม่น้อยเช่นกัน
ถึงอย่างนั้นตรรกะนี้ก็สมเหตุสมผล แค่ไม่กี่สัปดาห์ก่อน ชาวเน็ตยังมีบรรยากาศว่าควรนำ JPEG XL มาใช้ให้เร็วที่สุด และเพื่อให้ทำเช่นนั้น นักพัฒนาเบราว์เซอร์ก็แค่ “ใส่โค้ด reference decoder เข้าไปใน codebase” ซึ่ง “แทบไม่มีต้นทุน”
ฟอร์แมตรูปภาพและไลบรารีอื่น ๆ ก็น่าจะเต็มไปด้วยบั๊กเหมือนกัน แต่เพราะไม่ได้ถูกใช้ในซอฟต์แวร์หลัก ๆ จึงไม่มีใครสนใจ
โดยเฉพาะสำหรับคนที่มีความสามารถในการค้นหาและใช้ประโยชน์จากบั๊กแบบนี้ ผลตอบแทนเทียบกับเวลาที่ใช้ไม่คุ้ม
การไม่ได้ถูกใช้นาน ๆ ไม่ได้ทำให้บั๊กน้อยลง
ถ้า image encoder และ decoder รวมถึง encoder/decoder อื่น ๆ ไม่ใช้ภาษาที่ไม่ปลอดภัย โอกาสที่จะสร้างบั๊กแบบนี้ก็จะลดลง
นอกเหนือจากนั้น ผมคิดว่าวัฒนธรรมที่ทำให้โค้ดซับซ้อนเกินจำเป็น และนักพัฒนาที่ไม่เข้าใจรายละเอียดอย่างถูกต้องก็เป็นปัญหาด้วย
การแก้ไขนี้รวมอยู่ใน Firefox 117.0.1 และ Fenix 117.1.0 ของวันนี้: https://hg.mozilla.org/releases/mozilla-release/rev/e245ca21...
สำหรับข้อมูลเพิ่มเติม ใน image crate มี การใช้งานตัวถอดรหัส WebP ที่เขียนด้วย Rust ที่ปลอดภัย: https://github.com/image-rs/image
แม้จะค่อนข้างยังไม่สมบูรณ์มาเป็นเวลานาน แต่ปีที่แล้วมีการ implement ฟีเจอร์ของ WebP จำนวนมาก
ตอนนี้ Chromium มีนโยบายอนุญาตให้ใช้ dependency ของ Rust แล้ว บางที Chromium ก็น่าจะเริ่มนำมาใช้ได้ไม่ใช่หรือ?
คอมมิตต้นทางที่ก่อปัญหา: https://github.com/webmproject/libwebp/commit/f75dfbf23d1df1...
คอมมิตที่แก้บั๊กนี้: https://github.com/webmproject/libwebp/commit/902bc919033134...
คอมมิตต้นทางปรับแต่ง Huffman decoder ให้เหมาะสมขึ้น decoder นี้ใช้ optimization ที่เป็นที่รู้จักดี โดยอ่านล่วงหน้า N บิต แล้วตัดสินใจว่าจริง ๆ ต้อง consume กี่บิต และต้อง decode เป็น symbol ใด หรือถ้าเป็น prefix N บิตของหลาย symbol ก็จะตัดสินใจว่าต้องอ้างอิงตารางใดสำหรับบิตที่เหลือ
เวอร์ชันเก่าใช้ lookup table สำหรับ symbol สั้น ๆ แต่ symbol ยาว ๆ ต้อง traversal ในกราฟ เวอร์ชันใหม่ปรับปรุงโดยใช้อาร์เรย์ของ lookup table แต่ละรายการเก็บ
(nbits, value)โดยnbitsคือจำนวนบิตที่จะ consume และvalueโดยปกติคือ symbol แต่ถ้าnbitsเกิน N จะตีความvalueเป็น index ของตาราง และตีความnbitsใหม่เป็นความยาวโค้ดที่ยาวที่สุดใน subtree นั้น ดังนั้นตารางถัด ๆ ไปแต่ละตารางต้องมีรายการ2^(nbits - N)รายการ ส่วน root table จะถูกกำหนดตายตัวไว้ที่2^Nรายการเสมอเวอร์ชันใหม่คำนวณจำนวนรายการสูงสุด (
kTableSize) จากจำนวน symbol แน่นอนว่า Huffman tree มาจาก input ที่เชื่อถือไม่ได้ และจินตนาการได้ง่ายว่ามีกรณีที่nbitsใหญ่มาก โดยเฉพาะ VP8 Lossless อนุญาตได้สูงสุด 15 บิต ดังนั้นถ้า LUT ทั้งหมดถูก map ไปยังตารางเสริมแยกกันคนละชุด ตารางสูงสุดที่เป็นไปได้จะมี2^N + 2^15รายการ การสร้างแบบนี้ก็ไม่ได้ต้องใช้ symbol มากนัก แค่16-Nsymbol ต่อแต่ละตารางก็พอที่น่าสนใจคือในโค้ดเองมีโหมดที่คำนวณเฉพาะขนาดตาราง (เรียก
VP8LBuildHuffmanTableด้วยroot_table == NULL) แต่ไม่รู้ทำไมจึงไม่ได้ใช้ และสมมติขนาดสูงสุดแบบคงที่ไว้แทน ดังนั้นถ้าสร้าง Huffman tree เพื่อ maximize จำนวนรายการ ก็จะเขียนล้นพื้นที่ที่ allocate ไว้เข้าใจได้ว่าทำไมเรื่องนี้ถึงเกิดขึ้น ขั้นตอน Huffman decoding เป็นหนึ่งในส่วนที่ใช้การคำนวณมากที่สุดในหลาย ๆ format บีบอัด ดังนั้น improvement เล็ก ๆ ก็สำคัญ optimization ข้างต้นเป็นที่รู้จักดี แต่ code path ที่ยาวมักถูกมองว่าเกิดขึ้นไม่บ่อย จึงมีลำดับความสำคัญในการ optimize ต่ำ ข้อความคอมมิตต้นทางแย้งสมมติฐานนี้และจึงถูก merge ได้ ยากจะมั่นใจได้ว่า ภาษาที่ปลอดภัยด้านหน่วยความจำ จะป้องกันปัญหานี้ได้หรือไม่ เพราะนี่เป็นกรณีที่พบไม่บ่อยซึ่งทำให้อยากหลีกเลี่ยง overflow check อย่างจริงจัง
[1] อย่างไรก็ตาม memory corruption เกิดขึ้นระหว่างการสร้างตาราง ไม่ใช่ใน tight loop ดังนั้น overflow check บางส่วนก็น่าจะช่วยได้มาก การแก้ไขจริงไม่ได้เปลี่ยนฟังก์ชัน
ReadSymbolเลย ถึงอย่างนั้น ความปลอดภัยของ tight loop ก็ต้องมีเหตุผลรองรับ และเหตุผลที่ผิดอาจทำให้ทุกอย่างพังได้ถ้าการบอกว่าไม่จำเป็นต้องมี boundary check นั้นถูกต้อง ก็โอเค WUFFS จะไม่ emit runtime boundary check
แต่ถ้าซอฟต์แวร์ผิดพลาดจนออกนอกขอบเขตเหมือนครั้งนี้ ใน WUFFS จะ compile ไม่ผ่าน
คุณอาจคิดว่า “นั่นเป็นไปไม่ได้” และถ้า WUFFS เป็นภาษาโปรแกรมมิงทั่วไป คำพูดนั้นก็ถูก ตามทฤษฎีบทของ Rice แล้ว semantic property ที่ไม่ trivial นั้นตัดสินไม่ได้
โชคดีที่ WUFFS ไม่ใช่ภาษาทั่วไป ซอฟต์แวร์ส่วนใหญ่เขียนด้วย WUFFS ไม่ได้ แต่ image codec เขียนได้
แต่ก็สงสัยเหมือนกันว่าอาจสร้าง automated test ที่จับปัญหาประเภทนี้ได้หรือไม่
ในโค้ดที่ผมดูแลส่วนตัว สามารถแยก calculation บางส่วนออกเป็นฟังก์ชันต่างหากเพื่อทดสอบแยกได้ กรณีนี้อาจทำได้ยากเพราะ performance แต่ก็ไม่แน่ใจ
แก้ไข การเขียนนอกขอบเขต ใน
BuildHuffmanTablehttps://github.com/webmproject/libwebp/commit/902bc919033134...
อาจหมายความว่า Google พบ bug นี้แล้วจึง optimize fuzzer สำหรับ libwebp และจากนั้นก็พบ bug เพิ่มอีก
ดูเหมือนว่า Apple เป็นผู้รายงาน และดูคล้ายกับ security update นี้มาก: https://support.apple.com/en-us/HT213906
ดังนั้นจึงดูมีความเป็นไปได้ค่อนข้างสูง Apple อาจใช้ libwebp ภายใน ImageIO หรืออาจทำพลาดในลักษณะคล้ายกัน
image codec มี ประวัติช่องโหว่ที่ยาวนาน
การประมวลผลภาพจริง ๆ อาจเป็นโค้ดเชิงเส้นที่เรียบร้อยพอจะเขียนด้วย FORTRAN IV ที่ปลอดภัยด้านหน่วยความจำได้ แต่พอมีการบีบอัดเข้ามา ก็จะมีโครงสร้างข้อมูลความยาวแปรผัน การไล่ตาม pointer และอื่น ๆ มากขึ้น
แล้วยังมีแรงกดดันให้ต้องรันได้เร็วเพิ่มเข้ามาอีก
สิ่งนี้มีผลกระทบต่อ Electron ด้วยไหม? ถ้าใช่ เป็นเวอร์ชันไหน?
จุดที่น่าสนใจคือ Signal Desktop ซึ่งใช้ Electron ภายใน รันบน Linux โดยไม่มี sandbox [1][2]
[0] https://github.com/electron/electron/pull/39824
[1] https://github.com/signalapp/Signal-Desktop/issues/5195
[2] https://github.com/signalapp/Signal-Desktop/pull/4381
มีเส้นทางที่สามารถนำสิ่งนี้ไปใช้โจมตีจริงได้ไหม?
ได้ยินมาว่าใน 64 บิต heap spraying ไม่ค่อยใช้งานได้จริงแล้ว
มีอ็อบเจกต์ที่คาดเดาได้ในหน่วยความจำที่สามารถเขียนทับได้หรือเปล่า?
แม้บน 64 บิต heap spraying ก็ยังคงถูกใช้ใน kernel exploit อย่างชัดเจน ส่วนใน V8 exploit ผมไม่ค่อยรู้ว่าผู้คนใช้ primitive แบบไหนกัน