2 คะแนน โดย GN⁺ 2023-09-23 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การแก้ไขด้านความปลอดภัยเพียงรายการเดียว CVE-2023-4863 ที่รวมอยู่ในอัปเดตเสถียรของ Chrome คือช่องโหว่ heap buffer overflow ในไลบรารีภาพ WebP และ Google ระบุแล้วว่ามีเอ็กซ์พลอยต์ที่ถูกใช้งานจริงอยู่แล้ว
  • เมื่อพิจารณาร่วมกับรายงานของ Apple SEAR เมื่อวันที่ 6 กันยายน 2023, CVE-2023-41064 ของ Apple และร่องรอยของ BLASTPASS จาก Citizen Lab ก็มีความเป็นไปได้สูงว่าเป็นบั๊กเดียวกัน
  • มีการวิเคราะห์ว่าช่องโหว่นี้เกิดจากปัญหาที่สามารถเขียนเกินขนาดบัฟเฟอร์ที่คำนวณไว้ล่วงหน้าได้ ระหว่างกระบวนการสร้าง ตาราง Huffman ของ VP8L ซึ่งเป็นการบีบอัดแบบไม่สูญเสียข้อมูลของ WebP
  • เหตุผลที่ฟัซซิงทั่วไปอาจพลาดคือ ต้องสร้างทั้งตาราง Huffman ขนาดสูงสุดหลายชุดและตารางที่ไม่ถูกต้องเฉพาะแบบตามลำดับ จึงมี เงื่อนไขการทริกเกอร์ที่ซับซ้อนมาก
  • แพตช์ของ upstream libwebp ดูเพียงพอแล้ว แต่เนื่องจาก libwebp ถูกใช้อย่างกว้างขวางในเบราว์เซอร์ ระบบปฏิบัติการ และแอปต่าง ๆ การ กระจายแพตช์ และการทำ sandboxing จึงสำคัญ

เหตุใดแพตช์ของ Chrome จึงเชื่อมโยงกับ BLASTPASS

  • Google ได้แก้ไข CVE-2023-4863 ที่ Apple Security Engineering and Architecture (SEAR) รายงานไว้ ในอัปเดตเสถียรของ Chrome ช่วงต้นเดือนกันยายน 2023
    • ช่องโหว่นี้คือ heap buffer overflow ในไลบรารีภาพ WebP
    • Google ระบุว่าทราบว่า “มีเอ็กซ์พลอยต์ของ CVE-2023-4863 อยู่จริงในสภาพแวดล้อมการใช้งานจริง”
  • ในช่วงเวลาใกล้กัน Citizen Lab ตรวจพบพฤติกรรมน่าสงสัยใน iPhone ของบุคคลที่สังกัดองค์กรภาคประชาสังคมในกรุงวอชิงตัน ดี.ซี.
    • BLASTPASS เชื่อมโยงกับกรณีที่ใช้เอ็กซ์พลอยต์ zero-click zero-day ของ iMessage เพื่อแจกจ่ายสปายแวร์ Pegasus ของ NSO Group
    • หลังจาก Citizen Lab ส่งผลการวิเคราะห์ทางเทคนิคให้ Apple แล้ว Apple ก็เปิดเผย CVE สองรายการในประกาศความปลอดภัยวันที่ 7 กันยายน
  • CVE แรกของ Apple คือ CVE-2023-41061 ซึ่งสอดคล้องกับร่องรอยของการผูกเอ็กซ์พลอยต์ภาพเข้ากับไฟล์แนบ PassKit เพื่อข้าม sandbox BlastDoor ของ iMessage
    • ภาพอันตรายน่าจะถูกประมวลผลในอีกโปรเซสหนึ่งที่ไม่มี sandbox
  • CVE ที่สองคือ CVE-2023-41064 ซึ่งเป็นช่องโหว่ buffer overflow ใน Apple ImageIO
    • ImageIO คือเฟรมเวิร์กสำหรับพาร์สภาพของ Apple ที่ใช้ตรวจสอบรูปแบบภาพหลายชนิดและเชื่อมไปยังดีโคเดอร์ที่เหมาะสม
    • เนื่องจากไม่มีรายละเอียดทางเทคนิค จึงยังยืนยันไม่ได้ว่า CVE-2023-41064 กระทบกับรูปแบบภาพชนิดใด
  • เมื่อพิจารณาว่า Apple เพิ่งเพิ่มการรองรับ WebP ใน ImageIO, ทีมความปลอดภัยของ Apple รายงานช่องโหว่ WebP ให้ Chrome เมื่อวันที่ 6 กันยายน และ Google ออกแพตช์ฉุกเฉินภายใน 5 วันพร้อมระบุว่ามีการใช้งานจริง จึงมีความเป็นไปได้สูงว่า BLASTPASS และ CVE-2023-4863 เป็นบั๊กเดียวกัน

ตำแหน่งของช่องโหว่ที่แพตช์ libwebp ชี้ให้เห็น

  • เมื่อนำ bug ID ในประกาศความปลอดภัยของ Chrome มาเทียบกับคอมมิตโอเพนซอร์สของ libwebp จะพบว่าแพตช์ Fix OOB write in BuildHuffmanTable ตรงกับ CVE-2023-4863
    • แพตช์นี้ถูกสร้างขึ้นในวันที่ 7 กันยายน 2023 ซึ่งเป็นวันถัดจากที่ Apple รายงาน
  • ช่องโหว่อยู่ใน VP8L ซึ่งเป็นส่วนรองรับการบีบอัดแบบไม่สูญเสียข้อมูลของ WebP
    • การบีบอัดแบบไม่สูญเสียข้อมูลของ WebP ใช้ Huffman coding เพื่อเก็บและกู้คืนพิกเซลได้อย่างถูกต้อง 100%
    • อิมพลีเมนเทชันสมัยใหม่ใช้ตารางแทนโครงสร้างต้นไม้เชิงแนวคิดเพื่อเพิ่มประสิทธิภาพการดีโค้ด
  • เวอร์ชันที่มีช่องโหว่จะจองหน่วยความจำด้วย ขนาดบัฟเฟอร์ที่คำนวณไว้ล่วงหน้า จากตารางคงที่ แล้วสร้างตาราง Huffman ลงในพื้นที่นั้นโดยตรง
    • เวอร์ชันใหม่เปลี่ยนเป็นคำนวณขนาดรวมที่ต้องใช้สำหรับตารางผลลัพธ์ในพาสแรก โดยยังไม่เขียนจริง
    • หากขนาดรวมมากกว่าบัฟเฟอร์ที่คำนวณไว้ล่วงหน้า ก็จะสร้างการจัดสรรหน่วยความจำที่ใหญ่ขึ้น
  • โฟลว์หลักอยู่ที่ huffman_tables ซึ่งถูกจัดสรรใน ReadHuffmanCodes ของ src/dec/vp8l_dec.c และการเรียก VP8LBuildHuffmanTable/BuildHuffmanTable ภายใน ReadHuffmanCode
    • ตาราง Huffman ถูกแบ่งเป็น 5 เซกเมนต์ที่มีขนาด alphabet ต่างกัน
    • หากต้องการทำให้เกิด overflow จำเป็นต้องจัดรูปทั้ง 5 ตารางนี้อย่างละเอียด

กระบวนการสร้างไฟล์ทริกเกอร์

  • การบีบอัดแบบไม่สูญเสียข้อมูลของ WebP จะวิเคราะห์ความถี่ของพิกเซลอินพุต แล้วกำหนดบิตสตริงสั้นให้ค่าที่พบบ่อย และบิตสตริงยาวให้ค่าที่พบน้อย
    • โค้ดถูกจัดให้ดีโคเดอร์สามารถแยกความยาวของบิตสตริงได้เสมอ
    • ภาพที่ถูกบีบอัดจึงต้องมีข้อมูลสถิติและข้อมูลการกำหนดโค้ดเพื่อให้สามารถสร้างแมปปิงระหว่างโค้ดกับค่ากลับมาได้
  • WebP ยังบีบอัดตัวตาราง Huffman เองด้วย Huffman coding เพื่อลดขนาดไฟล์
    • โครงสร้างนี้ทำให้การวิเคราะห์และการทริกเกอร์ช่องโหว่ซับซ้อนขึ้น
  • @mistymntncop ได้จัดเตรียมโค้ดฮาร์เนสสำหรับสร้าง WebP รูปแบบถูกต้องที่มีข้อมูล Huffman coding ตามต้องการ หรือก็คือมี code lengths ตามต้องการ
    • ด้วยฮาร์เนสนี้จึงสามารถส่งอาร์เรย์ code_lengths ใดก็ได้ไปยังการเรียก BuildHuffmanTable เป้าหมาย
  • ในการทดลองด้วยมือ พบว่าปฏิสัมพันธ์ระหว่าง histogram ภายใน BuildHuffmanTable, num_open, num_nodes และค่า key ที่ใช้ติดตามตำแหน่งเริ่มของ ReplicateValue นั้นซับซ้อนมาก
    • root table ตั้งแต่ count[0] ถึง count[8] ไม่ได้ส่งผลโดยตรงมากนักต่อ total_size แต่สามารถเปลี่ยนสถานะภายในในภายหลังได้
    • second level tables ตั้งแต่ count[9] ถึง count[15] มีผลโดยตรงต่อ total_size สุดท้าย
  • enough.c ของ Mark Adler จะแสดง histogram ของ lookup table สำหรับต้นไม้ Huffman สูงสุดที่เป็นไปได้ ตามขนาด alphabet, ขนาด root table และความยาวโค้ดสูงสุด
    • มีคอมเมนต์ระบุว่า kTableSize ของ libwebp ถูกคำนวณจากเครื่องมือนี้
    • ด้วยเครื่องมือนี้สามารถสร้างขนาดบัฟเฟอร์ที่คำนวณไว้ล่วงหน้าขึ้นมาใหม่ได้ และยังยืนยันได้ด้วยเครื่องมือของ @mistymntncop ว่า code lengths ที่ “enough” สร้างขึ้นสามารถเติมการจัดสรร huffman_tables ได้ครบ 100%

เงื่อนไขที่ทำให้เกิด overflow จริง

  • เครื่องมือ enough คำนวณค่าสูงสุดสำหรับ โค้ดที่ถูกต้องและสมบูรณ์
    • สำหรับหนึ่งในตารางขนาดเล็กที่มีขนาดสัญลักษณ์ 40, root table 8 บิต และความยาวโค้ดสูงสุด 15 ขนาดสูงสุดคือ 410
    • ไม่พบกรณีที่โค้ดซึ่ง BuildHuffmanTable มองว่าถูกต้อง จะสร้างขนาดเกิน 410
  • overflow ไม่ได้เกิดจากการใช้ต้นไม้ Huffman ที่ถูกต้องล้วน ๆ แต่เกิดเมื่อใส่ต้นไม้ Huffman ที่ไม่ถูกต้องในขั้นตอนสุดท้าย
    • เริ่มจากสร้างตารางผลลัพธ์ขนาดสูงสุดก่อนด้วยต้นไม้ Huffman ที่ถูกต้อง 4 ต้น
    • เมื่อใส่ต้นไม้ Huffman ที่ไม่ถูกต้องลงในตารางสุดท้าย ReplicateValue จะสามารถเขียนออกนอกขอบเขตได้ก่อนถึงการตรวจสอบความสอดคล้องขั้นสุดท้าย
  • วิธีทำซ้ำคือ checkout คอมมิต libwebp ที่มีช่องโหว่ 7ba44f80f3b94fc0138db159afea770ef06532a0 เปิด AddressSanitizer แล้วใช้โค้ด PoC ของ @mistymntncop สร้าง bad.webp เพื่อดีโค้ดด้วย dwebp
    • AddressSanitizer รายงาน heap-buffer-overflow ใน BuildHuffmanTable
    • การเขียนที่รายงานเกิดขึ้นที่ตำแหน่งถัดจากพื้นที่ขนาด 11816 ไบต์ทันที
  • มีอินพุตหลายแบบที่สามารถทำให้ huffman_tables overflow ได้
    • ใน code lengths ที่ค้นพบ มีกรณีที่เขียนเลยท้ายการจัดสรร huffman_tables ไปได้ถึง 400 ไบต์
    • แม้การควบคุมค่าที่เขียนได้จะเป็นเพียงบางส่วน แต่ก็ดูยังสามารถเอ็กซ์พลอยต์ได้
  • ต้นไม้ Huffman ของอินพุตที่ไม่ถูกต้องมีความไม่สมดุลบางส่วน และในช่วงหนึ่งของกิ่งที่ไม่สมดุลมี internal node จำนวนมากที่ไม่มีลูก
    • โครงสร้างนี้ทำให้เกิดดัชนี key ที่ต้นไม้แบบถูกต้องไม่สามารถไปถึงได้

วิธีที่แพตช์ป้องกัน overflow

  • ในตอนแรก แพตช์ดูเหมือนจะป้องกัน heap overflow ด้วยการขยายบัฟเฟอร์แบบไดนามิกให้พอดีกับขนาดที่ต้องใช้
  • แต่จริง ๆ แล้วพาสแรกของเวอร์ชันที่แพตช์แล้วจะรัน BuildHuffmanTable เพื่อคำนวณขนาดรวมที่ต้องใช้ โดยไม่เขียนลงตาราง
    • อินพุตที่ไม่ถูกต้องซึ่งเคยทำให้เกิด overflow จะทำให้ BuildHuffmanTable ล้มเหลวและคืนค่า 0 ในพาสแรกนี้
    • เนื่องจากพาสแรกไม่มีการเขียน แม้จะมีการประมวลผลต้นไม้ที่ไม่ถูกต้องเพียงบางส่วน ก็จะไม่เกิดการเขียนออกนอกขอบเขต
  • เพราะยังไม่พบกรณีของโค้ดที่ถูกต้องและสมบูรณ์ซึ่งทำให้เกิด overflow แบบเดียวกัน แพตช์นี้จึงดูเพียงพอ

เหตุผลที่ฟัซซิงอาจพลาดได้ง่าย

  • libwebp ถูกฟัซผ่าน Google OSS-Fuzz มานาน และส่วนรองรับ WebP แบบไม่สูญเสียข้อมูลก็ถูกฟัซอย่างกว้างขวางด้วย
  • ปัญหาหลักคือทั้งฟอร์แมตและเงื่อนไขการทริกเกอร์มีความซับซ้อน
    • จากความเป็นไปได้ระดับหลายหมื่นล้านแบบ ต้องสร้างตาราง Huffman ขนาดสูงสุด 4 ตารางก่อนสำหรับขนาด alphabet 280 และ 256
    • จากนั้นต้องสร้างตาราง Huffman ที่ไม่ถูกต้องซึ่งมีรูปแบบเฉพาะมาก สำหรับขนาด alphabet 40
    • หากผิดไปเพียง 1 บิตในขั้นตอนไหนก็ตาม ดีโคเดอร์ภาพจะเกิดข้อผิดพลาดและจบการทำงานอย่างปลอดภัย
  • หลังจากแก้ 0day ของ WebP แล้ว Google ได้ปล่อยฟัซเซอร์ใหม่ที่เจาะจงกับรูทีน Huffman ของ WebP
    • แต่แม้จะรันฟัซเซอร์ดังกล่าวก็ยังไม่พบ CVE-2023-4863
  • ทั้งการกลายพันธุ์แบบ bit flip มาตรฐาน ลูปป้อนกลับจาก code coverage และแนวทางอิงสถานะอินพุตอย่าง CmpLog ของ AFL++ ต่างก็ยากที่จะผ่านสถานะกึ่งกลางไปจนถึงสถานะสุดขั้วนี้ได้
    • เทคนิค dynamic symbolic execution อย่าง TritonDSE ของ Quarkslab อาจมีโอกาส แต่ยังไม่ได้รับการยืนยัน
  • ช่องโหว่ Load_SBit_Png ของ FreeType มีลักษณะต่างออกไป
    • ในกรณี Load_SBit_Png นั้น พลาดการค้นพบเพราะฟัซซิงฮาร์เนสไม่สะท้อนรูปแบบการใช้ API ได้เพียงพอ
    • ส่วน CVE-2023-4863 ใกล้เคียงกับกรณีที่ฟัซได้ยากเพราะข้อจำกัดของช่องโหว่เอง มากกว่าจะเป็นเพราะฮาร์เนสไม่เพียงพอ

ขอบเขตผลกระทบและสถานะการรับมือ

  • Citizen Lab จับเอ็กซ์พลอยต์ขั้นสูงที่ถูกใช้งานจริงได้ และดูเหมือนว่า Apple กับ Chrome จะกระจายอัปเดตไปยังผู้ใช้หลายพันล้านคนภายในไม่กี่วัน
  • ในเวลานั้น Android ยังมีโอกาสได้รับผลกระทบอยู่
    • BitmapFactory ของ Android ทำหน้าที่ดีโค้ดภาพคล้ายกับ Apple ImageIO และรองรับ libwebp
    • ในขณะนั้นประกาศความปลอดภัยของ Android ยังไม่รวมการแก้ CVE-2023-4863 แต่ตัวแก้ไขถูก merge เข้า AOSP แล้ว
    • หาก Android ได้รับผลกระทบ ก็อาจลามไปสู่การเอ็กซ์พลอยต์ระยะไกลในแอปอย่าง Signal หรือ WhatsApp ได้
    • คาดว่าจะมีการแก้ไขในประกาศความปลอดภัยเดือนตุลาคม
  • แพตช์ของ upstream libwebp ดูเหมือนถูกนำไปใช้ได้อย่างถูกต้อง และกำลังกระจายไปยังจุดที่จำเป็น
  • เนื่องจาก libwebp ถูกใช้งานในหลายแห่ง การกระจายแพตช์ให้ครอบคลุมเพียงพออาจต้องใช้เวลา
  • สำหรับโค้ดพาร์เซอร์ที่ซับซ้อนและอยู่ใกล้พื้นผิวการโจมตีแบบ zero-click remote exploit อย่างการดีโค้ดภาพ การพึ่งพาฟัซซิงอย่างเดียวอาจไม่สามารถรับประกันความปลอดภัยได้ จึงต้องลงทุนกับ การตรวจทานซอร์สโค้ดเชิงรุก และ sandboxing ที่เหมาะสม

ความไม่สมดุลของการเปิดเผยข้อมูลทางเทคนิค

  • หากผู้ขายไม่เปิดเผยรายละเอียดทางเทคนิคอย่างเพียงพอ ผู้ป้องกันจะตรวจสอบผลกระทบของช่องโหว่ได้ยากขึ้น
  • ผู้โจมตีมีแรงจูงใจสูงในการติดตามและเอ็กซ์พลอยต์ช่องโหว่ N-day และการไม่เปิดเผยรายละเอียดก็ไม่ได้ทำให้พวกเขาช้าลงมากนัก
  • ฝ่ายป้องกันมักไม่มีทรัพยากรเพียงพอที่จะทำการวิเคราะห์ทางเทคนิคระดับนี้
  • หากปกปิดแม้แต่ข้อมูลพื้นฐานของพฤติกรรมการโจมตี ก็จะเกิดความไม่สมดุลที่ทำให้ผู้โจมตีมีความเข้าใจเกี่ยวกับช่องโหว่และเอ็กซ์พลอยต์มากกว่าฝ่ายป้องกัน

1 ความคิดเห็น

 
GN⁺ 2023-09-23
ความคิดเห็นจาก Hacker News
  • บั๊กนี้ดูคล้ายกับ บั๊ก Timsort เมื่อปี 2015 มากที่สุด [1]
    Timsort เป็นอัลกอริทึมเรียงลำดับแบบไฮบริดที่ชาญฉลาดซึ่งมาจาก CPython และ implementation หลายตัวรวมถึง OpenJDK ก็นำไปใช้ในลักษณะแทบจะเป็นการแปลโค้ดต้นฉบับระดับซอร์ส มันรักษา stack ของ run ที่เรียงลำดับแล้ว และมีการพิสูจน์ว่าตามโครงสร้างแล้วมีขอบเขตบนแบบจำกัดที่เล็กพอสำหรับขนาด stack สูงสุดที่เป็นไปได้ แต่ implementation ดั้งเดิมของ CPython ไม่ตรงกับการพิสูจน์อย่างพอดี ทำให้เกิด stack overflow ได้ในกรณีหายาก ดังนั้นใน CPython จึงเป็นบั๊กความปลอดภัยร้ายแรง แต่ใน Java กรณีนั้นจะ throw exception จึงไม่ใช่ปัญหาความปลอดภัยแบบเดียวกันใน OpenJDK
    ในทำนองเดียวกัน บั๊ก WebP ครั้งนี้ก็เกิดจากการที่ขนาดตารางสูงสุดถูกพิสูจน์อย่างเป็นทางการแล้ว แต่ไม่ตรงกับค่าที่อยู่ในซอร์สโค้ดจริง บั๊กแบบนี้ทั้งตรวจสอบและรีวิวยาก มีการพิสูจน์อยู่ และซอร์สก็ดูเหมือนจะตรงกับการพิสูจน์ จึงคิดได้ง่ายว่าไม่น่ามีปัญหา เรื่องนี้ดูเป็นสัญญาณชัดว่าจำเป็นต้องมี formal verification ที่เข้าถึงได้มากกว่าการรีวิวโดยคน และต้องใช้ภาษาที่ memory-safe มากขึ้น type system ก็ถือได้ว่าเป็น formal verification รูปแบบอ่อนอย่างหนึ่ง
    [1] http://envisage-project.eu/wp-content/uploads/2015/02/sortin...

    • งานแบบนี้ให้ความสำคัญกับ performance จึงควรเขียนด้วย WUFFS เป็นพิเศษ WUFFS ไม่ได้ปล่อย boundary check ออกมาแบบ Java หรือทำแบบ Rust ที่จะตรวจตอน runtime เมื่อไม่ชัดว่า index อยู่ในช่วงหรือไม่ แต่ถ้าเครื่องมือยืนยันไม่ได้ว่า index อยู่ในช่วง โปรแกรมนั้นจะถูกปฏิเสธตั้งแต่แรก
      https://github.com/google/wuffs
      อาจเขียน check แบบเดียวกันอย่างชัดเจนเพื่อให้ผ่านข้อกำหนดนี้ก็ได้ แต่ถ้าเคยเชื่อว่าเป็นซอฟต์แวร์ประสิทธิภาพสูงเลยไม่จำเป็นต้องมี check จุดที่เครื่องมือ WUFFS ไม่ยอมรับโค้ดก็น่าจะทำให้พบว่าความเชื่อนั้นผิด แม้จะอ่อนกว่า formal verification แบบสมบูรณ์ แต่ในแง่เป้าหมายเรื่องความปลอดภัยของโปรแกรมถือว่าดีขึ้นมาก และดีกว่าการที่คนบอก “LGTM” มาก
    • ประโยคว่า “type system ถือได้ว่าเป็น formal verification แบบอ่อน” ขึ้นอยู่กับ ประเภทของ type system ด้วย ช่วงนี้ได้ดู Idris และดูเหมือนจะเป็นภาษาโปรแกรมมิงอเนกประสงค์ที่ใช้กับการพิสูจน์ได้ด้วย
  • ในบทความนี้มีหลายส่วนที่น่าสนใจนอกเหนือจากคำถามว่า “ตอนนี้ต้องแพตช์อะไร” แม้จะรู้ตำแหน่งช่องโหว่และสิ่งที่แก้ไขแล้ว การทำซ้ำ exploit PoC ก็อาจต้องใช้ความพยายามไม่น้อย และตัวคลายการบีบอัดแบบ lossless ใน image decoder ก็อาจทนต่อ fuzzing ได้ค่อนข้างมาก สำหรับคนสายความปลอดภัยอาจเป็นเรื่องปกติ แต่ในฐานะคนนอกวงการ อ่านแล้วสนุกดี

    • ทางแก้ของปัญหาแบบนี้ไม่ใช่ fuzzing แต่คือการ ตัดโค้ดส่วนนั้นทิ้ง เหมือนตัดเนื้องอก ถ้า OS หรือ browser หลายจุดพังเพราะอย่างนั้น ก็เขียนตัวแปลงฟอร์แมตที่ memory-safe และถูก sandbox อย่างแน่นหนาสักตัวเพื่อจัดการฟอร์แมตที่เป็นปัญหาได้เลย ผมมองว่า iPhone หรือ browser ที่อาจไม่สะดวกใน edge case บางอย่าง ยังดีกว่าโค้ดแบบนี้ที่แทบจะรับประกันว่ามีช่องโหว่ ไม่ว่าจะ fuzz หรือไม่ก็ตาม อาจเป็นคำพูดเชิงมองโลกในแง่ดี แต่ผมมั่นใจว่าเรื่องนี้จะไม่จบแค่นี้
  • มีคำถามอยู่สองสามข้อที่หาคำตอบชัดเจนไม่ได้ 1) เบราว์เซอร์ที่ใช้ Chrome เป็นฐาน ตัวอื่นอย่าง Brave ได้รับผลกระทบด้วยหรือไม่? 2) Chrome บนเดสก์ท็อปได้รับผลกระทบด้วยหรือเปล่า หรือเป็นปัญหาเฉพาะมือถือ? 3) ทำไมผมถึงไม่เคยได้ยินชื่อ WebP เลย? สงสัยว่าผมตัดขาดจากโลกไปเอง หรือมันเป็นเทคโนโลยีที่เน้นมือถือเป็นหลัก

    • เป็นคำถามที่ดี เบราว์เซอร์ที่ใช้ Chromium เป็นฐาน ตัวอื่นก็น่าจะได้รับผลกระทบจากบั๊กนี้สูง มีเบราว์เซอร์จำนวนมากที่ตามอัปเดตความปลอดภัยของ Chromium ได้ดีอย่าง Brave แต่ก็มีกรณีที่ตามหลังค่อนข้างมากอย่าง Samsung SBrowser
      Chrome บนเดสก์ท็อปก็ได้รับผลกระทบทั้งบน Linux และ Windows Chrome bundle libwebp ของตัวเอง ดังนั้นแม้ Linux distribution จะยังไม่ได้แพตช์ แต่ถ้า Chrome เป็นเวอร์ชันล่าสุด อย่างน้อยในแง่การโจมตีผ่านเบราว์เซอร์ก็ถือว่าโอเค
      เบราว์เซอร์และระบบปฏิบัติการหลัก ๆ รองรับฟอร์แมตรูปภาพที่ไม่คุ้นชื่อจำนวนมากอย่างน่าประหลาดใจ เช่น บน MacOS สามารถโหลด KTX2(Khronos Texture Container) ได้ และบน Android สามารถโหลด DNG(Adobe Digital Negative) ได้ มี attack surface ที่น่าสนใจและเปิดเผยต่อผู้ใช้จำนวนมากให้ผู้โจมตีสำรวจไม่น้อย
    • ทุกอย่างที่รองรับ WebP ได้รับผลกระทบ ไม่ใช่แค่ Chrome หรือ Electron แต่รวมถึงทุกเบราว์เซอร์ ทั้งเดสก์ท็อปและมือถือ รวมถึงซอฟต์แวร์ที่ไม่ใช่เบราว์เซอร์ด้วย เช่น image viewer, โปรแกรมกราฟิก, email client ไปจนถึง file manager ที่แสดง thumbnail
      บั๊กอยู่ในไลบรารี codec และ WebP เป็น ecosystem ที่ implementation แทบจะรวมศูนย์อยู่ตัวเดียว ทุกคนจึงใช้ไลบรารีเดียวกันและต้องแพตช์ทั้งหมด
      Google ผลักดัน WebP เมื่อ 10 ปีก่อน แต่เพราะเป็นของ Chrome เท่านั้นอยู่นาน จึงไม่ได้แรงส่งมากนัก แม้ไม่ได้ถูกทำให้เป็นมาตรฐานอย่างถูกต้องนัก แต่ก็เป็นโอเพนซอร์ส รูปภาพคุณภาพต่ำบีบอัดได้ดีกว่า JPEG แต่ในรูปภาพคุณภาพสูงมักมีสีเลอะและดูเบลอ น่าขันที่ตอน WebP เริ่มได้รับการรองรับอย่างกว้างขวาง ก็เริ่มล้าสมัยทางเทคนิคไปแล้วเพราะ AVIF และ JPEG XL
    • เกือบแน่นอนว่าคุณเคยดาวน์โหลด รูปภาพ WebP มาแล้ว เพียงแต่อาจไม่ทันสังเกต เพราะเว็บไซต์จำนวนมากให้บริการหลายฟอร์แมตจาก URL เดียวกัน โดยปกติ HTTP reverse proxy จะแปลงฟอร์แมตให้อัตโนมัติ ดังนั้นถ้าเป็นเบราว์เซอร์ในช่วง 10 ปีล่าสุด แม้ไฟล์ที่ดาวน์โหลดจะดูเหมือนมีนามสกุล “.png” ก็อาจได้รับ WebP ได้ โปรแกรมแก้ไขภาพสมัยใหม่ทั้งหมดรองรับ WebP จึงสังเกตความต่างได้ยาก
    • WebP รองรับบน Chrome เดสก์ท็อปมานานแล้ว ฟอร์แมตทดแทน JPEG มีออกมาและหายไปหลายสิบตัว และจุดเด่นของ WebP คือมี อิทธิพลของ Google หนุนอยู่เป็นหลัก ตอน Google ซื้อ Duck/On2 ก็ได้เทคโนโลยีบีบอัดวิดีโอจำนวนมากมา และบางส่วนเข้าไปอยู่ใน WebP
    • ทุกเบราว์เซอร์ได้รับผลกระทบ และ Firefox ก็ออกอัปเดตความปลอดภัย แล้ว WebP กำลังได้รับความนิยมเพิ่มขึ้นในฐานะตัวแทน JPEG ดังนั้นถ้าเห็นว่ารูปภาพที่ดาวน์โหลดจากเว็บออกมาเป็น WebP มากขึ้นเรื่อย ๆ ก็น่าแปลกใจที่ยังไม่เคยเจอเลย
  • หากอุปกรณ์ Android อยู่ในสถานะหมดการสนับสนุน เท่ากับว่าตอนนี้มันเสี่ยงต่อ 0-click exploit ที่กำลังถูกใช้จริงอยู่หรือเปล่า? หรือแค่อัปเดตแอป SMS, Chrome, WhatsApp, Signal ฯลฯ ก็เพียงพอที่จะปิดช่องทางอินพุตหลัก ๆ ได้แล้ว?

    • ยังไม่แน่ชัดว่ามี Android exploit สำหรับบั๊กนี้อยู่แล้วหรือไม่ exploit เดิมเป็นของ iOS ผ่าน iMessage แต่ก็มีความเป็นไปได้ค่อนข้างสูงว่ามันถูกพัฒนาแล้ว ทุกวันนี้ความต้องการ exploit แบบนี้สำหรับ Android สูงมาก และได้ยินว่าช่วงหลังมีการพูดถึงราคาที่สูงจนน่าเหลือเชื่อ
      ถ้าอัปเดต Chrome บนอุปกรณ์ที่หมดการสนับสนุน ปัญหาใน Chrome ก็จะถูกแก้ แต่การแก้แอปอย่าง Signal หรือ WhatsApp จำเป็นต้องอัปเกรด Android OS Chrome bundle libwebp ของตัวเอง แต่แอปที่มีการเปิดรับสูงอย่างแอปแชตและ Gmail ใช้อินเทอร์เฟซที่ OS จัดให้เพื่อแสดงภาพ คาดว่าอุปกรณ์ Android ที่ยังอยู่ในช่วงสนับสนุนด้านความปลอดภัยจะเริ่มมีอัปเดตออกมาตั้งแต่ต้นเดือนตุลาคม
    • ไลบรารีถอดรหัสภาพ ของแพลตฟอร์มควรเป็นหนึ่งใน system modules ที่อัปเดตผ่าน Play Store ได้ สงสัยว่ามีใครยืนยันได้ไหมว่าจริง ๆ แล้วเป็นแบบนั้นหรือเปล่า
    • แอปแชตบางตัวมีตัวเลือกไม่ให้ดาวน์โหลดภาพที่ได้รับโดยอัตโนมัติหรือไม่แสดงพรีวิว การเปิดค่านี้อาจเป็นมาตรการที่ดี Google Messages มีฟีเจอร์นี้
    • ถ้า Android หลุดจากการได้รับอัปเดตความปลอดภัยแล้ว สิ่งที่ต้องกังวลไม่ได้มีแค่นี้อย่างเดียว ผมน่าจะเริ่มกังวลจากช่องโหว่ที่ถูกใช้โจมตีได้ง่ายกว่านี้ก่อน
    • บน iOS เรื่องนี้เป็นปัญหาใหญ่มากเป็นพิเศษ เพราะ iMessage มีสิทธิ์สูง บน Android แอปพวกนั้นทั้งหมดอยู่ใน sandbox
  • ประโยคที่ว่า “มีอินพุตจำนวนมากที่ทำให้ huffman_tables overflow ได้จริง” ดูเหมือนเป็นปัญหาที่ทั่วไปกว่านั้น เป็นโครงสร้างที่ซอฟต์แวร์ A สร้าง lookup table B แล้วตารางนั้นถูกใช้ประมวลผลสตรีมข้อมูลอินพุต
    ต่อจากนี้ ถ้าเป็นนักพัฒนาที่ใส่ใจเรื่องความปลอดภัยหรือความถูกต้องแม้แต่นิดเดียว ก็ควรต้องรับประกันอย่างใดอย่างหนึ่ง: A) ซอฟต์แวร์ถูกเขียนมาให้ไม่มีข้อมูลอินพุตใดทำให้ lookup table ถูกใช้ผิดหรือทำงานล้มเหลวได้ หรือ B) ใช้เฉพาะในสภาพแวดล้อมที่ควบคุมได้ เช่น การสื่อสารแบบจุดต่อจุดที่ทั้งสองฝ่ายเชื่อถือได้ จึงรับประกันได้ว่าสตรีมจะไม่มีวันใช้ lookup table ผิดหรือทำให้เกิดความผิดปกติ
    B แทบเป็นไปไม่ได้ยกเว้นในกลุ่มเล็ก ๆ หรือสำนักงาน และในระดับอินเทอร์เน็ตยิ่งเป็นไปไม่ได้จริง ๆ สุดท้ายจึงเหลือแค่ A แนวปฏิบัติที่ดีแบบทั่วไปของวิศวกรรมซอฟต์แวร์ในอนาคตคือ ถ้าใช้ lookup table ด้วยเหตุผลใดก็ตาม นักพัฒนาต้องรับประกันว่าตารางนั้นทำงานถูกต้องกับข้อมูลทุกประเภท หรือไม่ก็ต้องตรวจจับข้อมูลที่ผิดก่อนจะไปถึงตาราง และจัดการอย่างเหมาะสม
    ถ้าเป็นนักวิจัยความปลอดภัยที่จริงจังและมีเวลา ผมคงรวบรวมรายการช่องโหว่ด้านความปลอดภัยทั้งหมดในอดีตที่เกี่ยวข้องกับ lookup table ไม่ทางใดก็ทางหนึ่ง แล้วอ่านทีละรายการเพื่อเทียบจุดร่วมกัน น่าจะมีแพตเทิร์นอยู่ จากนั้นค่อยไล่ดูซอฟต์แวร์ทั้งหมดที่ใช้ lookup table กับสตรีมข้อมูลและ audit หาช่องโหว่ แต่นี่ไม่ใช่งานที่คนคนเดียวทำได้ตลอดชีวิต เป็นกีฬาประเภททีมมากกว่า

  • การที่ การเปิดเผยซอร์สโค้ด ช่วยให้ NSO เจอบั๊กนี้มากน้อยแค่ไหนกันนะ? ถ้าโค้ดมีแต่ binary blob สงสัยว่า decompiler สมัยใหม่จะเพียงพอให้เข้าใจโค้ดและหาบั๊กที่เข้าใจยากแบบนี้ได้หรือไม่

    • blob หยุดผู้โจมตีไม่ได้ หากจะเขียน exploit ให้สำเร็จ ยังไงก็ต้องเข้าใจ ไบนารีที่คอมไพล์แล้ว อยู่ดี
  • น่าแปลกที่มันไม่ใช่ส่วน “ใหม่” ของฟอร์แมตภาพเลย Huffman compression มีมานานกว่า 70 ปีแล้ว canonical Huffman ก็เพียงแค่น้อยกว่านั้นไม่กี่สิบปี และแม้แต่ JPEG ก็ใช้ Huffman เป็นเทคโนโลยีเก่าแก่หลายสิบปี มีบทความอธิบายวิธี implement นับไม่ถ้วน ดูเหมือนควรเป็นเทคโนโลยีที่บั๊กใน implementation ต่าง ๆ ถูกสะสางไปแล้ว
    เมื่อก่อนเคยอ่านสเปก JPEG และเคยเขียน decoder เลยลองดูสเปก WebP: https://developers.google.com/speed/webp/docs/webp_lossless_...
    ส่วนสำคัญอยู่ในหัวข้อ 6 สิ่งแรกที่สะดุดตาคือวิธีประกอบโค้ดไม่ชัดเจน ต่างจากสเปก JPEG JPEG มี flowchart ที่อ่านเข้าใจง่ายจำนวนมากเกี่ยวกับกระบวนการ WebP ดูคล้าย LZH/deflate(zlib) และให้ความรู้สึกเหมือนชุดเศษ source code บางส่วนพร้อมคำอธิบายมากกว่า “สเปก”
    หลังจาก GIF, JPEG, PNG ก็คิดอยากลองเขียน WebP decoder ดู แต่ดูแค่ “สเปก” ข้างต้นแล้วรู้สึกเหมือนมันแทบจะบอกว่าอย่าเขียนเลย

    • เห็นด้วยว่าสเปกขาดตัวอย่างอย่างมาก แต่ก็ระบุว่าใช้ canonical Huffman tree จึงต้องส่งแค่ความยาวของโค้ด ผมว่าชัดเจนพอที่จะกำหนด tree จริงได้ ไม่น่ามี implementation ของ canonical Huffman ที่ใช้ลำดับพจนานุกรมแบบย้อนกลับ
      implementation ของ Huffman tree มี trade-off ที่แตกต่างกันมากมาย ดังนั้นแค่เป็นเทคโนโลยีเก่าก็ไม่ได้หมายความว่าบั๊กถูกสะสางหมดแล้ว Charles Bloom เคยบอกว่าแม้แต่งานวิจัยสำคัญเชิงตัดสินเรื่องการ optimize Huffman จากปี 1997 [1] ก็ยังไม่เป็นที่รู้จักมากนักจนถึงปี 2010 และ optimization จำนวนมากถูกค้นพบซ้ำแล้วก็ถูกลืมไป ดังนั้นจึงมีความเป็นไปได้สูงว่าจะมี implementation ที่ไม่มีประสิทธิภาพอยู่มาก
      [1] https://cbloomrants.blogspot.com/2010/08/08-12-10-lost-huffm...
    • ถ้าต้องการโค้ดอ้างอิง มี WebP-Lossless decoder ที่น้อยกว่า 1200 บรรทัดอยู่ที่ https://github.com/golang/image/tree/master/vp8l
  • เดี๋ยวนี้ดูเหมือนแม้แต่การดูภาพก็ทำไม่ได้โดยไม่ต้องกังวลเรื่องความปลอดภัย

    • ถ้าผู้ผลิตซอฟต์แวร์ใช้ไลบรารีที่ช้าลงเล็กน้อยในการ render ภาพ ก็จะหลีกเลี่ยงข้อกังวลด้านความปลอดภัยที่ร้ายแรงที่สุดอย่าง remote code execution ได้ ถ้าหลีกเลี่ยงไลบรารีที่เขียนด้วย C ก็แทบจะกำจัด remote code execution ได้ และผู้ใช้ก็จะปลอดภัยขึ้น
    • ผมอาจจำผิดก็ได้ แต่เหมือนว่า PNG กับ JPG ก็เคยมีเรื่องคล้ายกันอย่างน้อยครั้งหนึ่ง
      ฟังดูเหมือนความเจ็บปวดในการเติบโตแบบคลาสสิกจากการใช้ C ซึ่งเป็นภาษาที่ไม่ปลอดภัย ผมเข้าใจว่ามันน่าดึงดูดเพราะความเร็วของเบราว์เซอร์ แต่ก็อยากให้อุตสาหกรรมเลิกแนวทางที่คอยส่งเสริมให้ทำผิดซ้ำแบบเดิม ๆ มาตั้งแต่เริ่มใช้ C
      ให้ความรู้สึกเหมือนสร้างสะพานด้วย สกรูปลายสว่าน แทนหมุดย้ำเพราะมันเร็วกว่า พอสะพานเริ่มแอ่นก็แค่ขันสกรูเพิ่มเข้าไป
  • “ข่าวดีก็คือ Apple และ Chrome ตอบสนองได้ยอดเยี่ยมสมกับความเร่งด่วนของปัญหานี้” แบบนี้ยอมรับได้ยากนะ คนที่จัดปัญหานี้เป็นของ Chrome เท่านั้น คือ Google เอง แค่ดู 7 วันที่ผ่านมาก็เห็นแล้วว่า Linux distribution รายใหญ่ทั้งหมดต้องเร่งปล่อยอัปเดต และ Red Hat ให้คะแนน 9.6 ด้วย Python Docker image ที่ถูก pull ไปมากกว่า 1 พันล้านครั้ง, Puppeteer, WordPress, Node.js ฯลฯ ก็ได้รับผลกระทบ แต่ CRBug ก็ยังเป็น private อยู่
    เว็บไซต์อย่าง BleepingComputer ก็รายงานไปตามที่เห็นโดยไม่ได้ตรวจสอบ และบริษัทรักษาความปลอดภัยจำนวนมากที่ปฏิบัติต่อ issue นี้เหมือนเป็นบุคคลที่สามก็เหมือนกัน ถ้ารู้ว่าอีกฝ่ายไม่ได้ทำ due diligence ก็สร้างความเชื่อใจกันได้ยากจริง ๆ
    Adam Caudill เขียนบทความดี ๆ ชื่อ “Whose CVE is it anyway?”[0] พร้อมยกกรณีที่ 1Password แพตช์ตั้งแต่ช่วงแรก และชี้ประเด็นที่พูดถึงตรงนี้ได้ดี Citizen Lab ปฏิเสธที่จะตอบว่าสอง issue นี้เกี่ยวข้องกันหรือไม่ แต่มีบางอย่างที่ไม่ต้องเป็นอัจฉริยะก็พอมองออก
    [0]: https://adamcaudill.com/2023/09/14/whose-cve-is-it-anyway/

    • เหตุผลที่ Apple และ Chrome สำคัญเป็นพิเศษตรงนี้คือ เป้าหมายที่ถูกโจมตีจริงในโลกภายนอกคือฝั่งนั้น และมีพื้นผิวการโจมตีโดยตรงที่มีผู้ใช้มากที่สุด
      ผู้เขียนก็พูดว่าระบบอื่น ๆ อีกมากต้องแพตช์เช่นกัน เพียงแต่ว่าใน Python Docker image ที่ถูก pull ไป 1 พันล้านครั้งนั้น มีสักกี่ตัวที่เรนเดอร์ภาพ WebP ที่ไม่น่าเชื่อถือ? Node และอื่น ๆ ก็เช่นกัน แน่นอนว่าต้องแพตช์อย่างรวดเร็ว แต่ไม่ใช่ระดับเดียวกับ iOS/Android/Chrome
  • ผู้คนนับล้านทั่วโลกได้รับผลกระทบจากไลบรารีนี้ และผลกระทบก็ทวีคูณไปตามอุปกรณ์และแอปที่แต่ละคนใช้
    ผมชอบ C นะ แต่คิดว่าไลบรารีที่ผู้คนนับล้านทั่วโลกใช้ ไม่ควรใช้ C สัดส่วนความเสี่ยงในไลบรารีแกนหลักแบบนี้สูงเกินไป ต่อให้เป็นผู้เชี่ยวชาญ C สักวันก็ต้องพลาด
    นี่น่าจะเป็นการแก้ไข https://github.com/webmproject/libwebp/commit/dce8397fec159c...
    “malloc fail” นี่ชวนหงุดหงิด Slack, Discord, Teams ไปจนถึง OS สมัยใหม่ทั้งหมดล้วนได้รับผลกระทบ

    • การแก้ไขจริงอยู่ทางนี้: https://github.com/webmproject/libwebp/commit/902bc919033134...
    • คิดเหมือนกัน Rust ควรกลายเป็น C ตัวใหม่ การที่เขียนโค้ดด้วย C ได้ไม่ได้หมายความว่าจะผลิตโค้ดซับซ้อนจำนวนมากโดยอ้างเหตุผลอย่าง “ประสิทธิภาพ”, “ความพกพา”, “ความเข้ากันได้กับ legacy” ได้
      C/C++ และภาษาไดนามิกทำให้พื้นผิวของ undefined behavior และบั๊กละเอียดอ่อนขยายใหญ่ขึ้น และแม้แต่นักพัฒนาที่ฉลาดที่สุดก็ยัง lint ได้ยากและเป็นภาระ ไลบรารีพื้นฐานควรถูกตรวจสอบความถูกต้องเชิงรูปแบบในลักษณะคล้ายกับ seL4
      อีกปัญหาหนึ่งคือความไม่เป็นมืออาชีพที่แพร่ไปทั่ว FOSS รวมถึงการไม่ให้ความสำคัญกับความเข้มงวด คุณภาพ ความถูกต้อง และความปลอดภัย วิธีสร้างจักรวรรดิบนผืนทรายอย่างทุกวันนี้เป็นเรื่องโง่เขลา
    • ไม่ว่าจะ commit นี้หรือ commit ใกล้เคียง ไม่มี test เลยสักตัว น่าขันจริง ๆ