2 คะแนน โดย GN⁺ 2025-01-10 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

WorstFit: การเปิดเผยตัวแปลงที่ซ่อนอยู่ของ Windows ANSI

TL;DR

  • ค้นพบพื้นผิวการโจมตีใหม่โดยการใช้ประโยชน์จากฟีเจอร์การแปลงชุดอักขระภายในของ Windows ที่ชื่อ Best-Fit
  • แปลงฟีเจอร์นี้ให้กลายเป็นการโจมตีเชิงปฏิบัติจริง เช่น path traversal, การฉีดอาร์กิวเมนต์ และการรันโค้ดจากระยะไกล (RCE)
  • สาเหตุรากของปัญหาคือพฤติกรรมของคอมไพเลอร์, runtime ของ C/C++, และความผิดพลาดของนักพัฒนา
  • บทความยังอภิปรายถึงความยากของการนำการแก้ไขไปใช้ในระบบนิเวศโอเพ่นซอร์ส

การถอดรหัสการเข้ารหัสของ Windows

เริ่มต้น: ANSI และ code page

  • Windows ใช้การเข้ารหัส ANSI ในช่วงแรก ซึ่งมีประสิทธิภาพกับภาษาบางภาษา แต่ไม่สามารถจัดการชุดอักขระแบบผสมได้
  • มี code page หลายตัว และแต่ละหน้าโค้ดรองรับภาษาเฉพาะ

ยุค Unicode: UTF-16

  • Windows เปลี่ยนมาใช้ Unicode ในช่วงกลางทศวรรษ 1990 ทำให้สามารถแทนอักขระของแทบทุกภาษาได้ภายใต้มาตรฐานเดียว
  • ในตอนแรกใช้ UCS-2 จากนั้นจึงอัปเกรดเป็น UTF-16

ยุคการเข้ารหัสคู่

  • เพื่อรองรับ code page ANSI เดิม Windows จึงนำ API สองเวอร์ชันมาใช้งาน
  • มีทั้ง ANSI API และ Unicode API ซึ่งช่วยให้นักพัฒนาสามารถเลือกรูปแบบข้อมูลที่ต้องการได้

ข้อดีของ Best-Fit

  • การแปลงอักขระ "Best-Fit" ของ Windows คือวิธีจัดการตัวอักษรที่ไม่อยู่ในหน้าโค้ดเป้าหมายเมื่อแปลงจาก UTF-16 เป็น ANSI
  • ตัวอย่างเช่น สัญลักษณ์ ไม่มีใน code page Windows-1252 จึงถูกแมปเป็น 8 โดย Microsoft

WorstFit: พื้นผิวการโจมตีใหม่ของ Windows

🔥 ฝันร้ายเอเชียตะวันออก - CVE-2024-4577

  • CVE-2024-4577 คือช่องโหว่ที่ทำให้เซิร์ฟเวอร์ PHP-CGI ที่ตั้งค่าเป็น code page ภาษาจีนหรือญี่ปุ่นเสียหายได้ด้วยคำขอเพียง ?%ADs
  • การทำงานของ Best-Fit ทำให้ U+00AD (soft hyphen) ถูกแมปเป็นเครื่องหมายยัติภังค์ - และสามารถใช้เพื่อข้ามการป้องกันได้

🔥 การลักลอบชื่อไฟล์

  • ในการจัดการชื่อไฟล์สามารถใช้ WorstFit เพื่อแปลงให้เป็น payload สำหรับ path traversal ได้
  • ตัวอย่างเช่น Chrome V8 Developer Shell (d8.exe) ใช้ ANSI API เพื่อรับ working directory ปัจจุบัน

🔥 การแยกอาร์กิวเมนต์

  • โดยการดัดแปลงผลลัพธ์ของ GetCommandLineA อาจนำการทำงานของ WorstFit มาใช้กับการแยกวิเคราะห์บรรทัดคำสั่ง
  • ตัวอย่างเช่น การป้อน " --use-askpass=calc " สามารถทำให้ระบบรัน calc.exe ได้

สรุป

  • การทำงานของ Best-Fit ช่วยเปิดพื้นผิวการโจมตีในขั้นตอนการแปลงระดับระบบ ซึ่งอาจทำให้เกิดช่องโหว่ได้ในเครื่องมือต่างๆ
  • ฟังก์ชันจากไลบรารีมาตรฐานหรือภาษาการเขียนโปรแกรมไม่สามารถป้องกันการโจมตีเหล่านี้ได้อย่างสมบูรณ์

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

 
GN⁺ 2025-01-10
ความคิดเห็นจาก Hacker News
  • Microsoft รู้จักปัญหานี้มาอย่างน้อยหนึ่งปีแล้วผ่านกฎการวิเคราะห์โค้ดพิเศษชื่อ CA2101 ที่ไม่แนะนำให้ใช้การแมปแบบ best-fit โดยเฉพาะ โดยได้พูดถึงความเสี่ยงด้านความปลอดภัยไว้แล้ว แต่รายละเอียดยังคงคลุมเครือ

  • ปัญหานี้เป็นเชิงระบบ Microsoft มีการให้บริการการแมปโค้ด "best fit" เพื่อแปลง Unicode เป็น ASCII การแมปนี้ถูกใช้ในหลายพื้นที่ และจำเป็นต้องมีอยู่ต่อไปเพราะ Microsoft ยึดความเข้ากันได้ย้อนหลังเป็นหลัก ซึ่งจะแตกต่างจากค่าเริ่มต้นว่าเชื่อมต่อกับทุกอย่าง

    • มักถูกใช้เพื่อแปลงโค้ดพอยต์ที่ผิดปกติเป็นเครื่องหมายทับ (slash), ขีดกลาง (hyphen), และเครื่องหมายอัญประกาศ ซึ่งสามารถถูกใช้ในทางที่ผิดได้ ในภาษาการเขียนโปรแกรมสมัยใหม่จะถูกประมวลผลอย่างถูกต้อง แต่จะมีปัญหาเมื่อส่งต่อไปยังคำสั่งเชลล์หรือ Win32 API

    • ผู้ดูแลโปรเจกต์ curl กล่าวว่าความผิดพลาดอยู่ที่ "curl เป็นเหยื่อ" แต่ต้นตอของปัญหานี้อยู่ที่อื่น ปัญหาจะเกิดขึ้นเมื่อมีการตรวจสอบ input ของผู้ใช้และจัดการกับมันในไลบรารีระบบด้วยวิธีที่ต่างกัน

    • การปิดการทำงานการแปลง "best fit" ในพื้นที่ Win32 แบบเลือกได้อาจเป็นทางออกได้ และผู้ให้บริการโอเพนซอร์สอาจเพิ่มสิ่งนี้เป็นแนวทางปฏิบัติที่ดี

  • Windows เหมือนเกมการ์ด Munchkin ที่ฟังก์ชันต่างๆ หลายอย่างบังเอิญมารวมกันจนเกิดช่องโหว่รุนแรง การแปลงระบบย่อย ANSI เป็น UTF-8 อาจช่วยบรรเทาปัญหานี้ได้

  • ตั้งแต่ NT 3.5 Microsoft ค่อยๆ เลิกใช้ ANSI และส่งเสริมการใช้ Wide Character API มาอย่างต่อเนื่อง อย่างไรก็ตาม การใช้งานไลบรารีรันไทม์ C/C++ ของ Microsoft คืออุปสรรคหลัก

    • ฟังก์ชันมาตรฐานใช้ฟังก์ชัน A-เพื่อแปลง Unicode โดยไม่รายงานการล้มเหลว และใช้แนวทาง best-fit
  • ความเป็นไปได้ที่ Microsoft จะเปิดใช้ UTF-8 โดยค่าเริ่มต้นใน Windows ทั้งหมดนั้นค่อนข้างต่ำ เพราะแอปที่เก่าบางตัวยังพึ่งพา code page เฉพาะหรืออักขระ 1 ไบต์

    • การลบตรรกะ Best-Fit ออกจาก Win32 xxxA API คิดว่าจะก่อให้เกิดความเสี่ยงน้อยกว่า
  • มีสองวิธีในการบังคับให้แอปพลิเคชันตั้งค่า code page "Ansi" เป็น UTF-8 วิธีแรกคือใช้ไฟล์ Manifest และอีกวิธีคือเครื่องมือ "App Locale"

  • ที่คอมพิวเตอร์ Windows ส่วนตัว ผมตั้งโหมด UTF-8 เพื่อความปลอดภัยจากบั๊กนี้ และตั้งค่าดังกล่าวเพราะมีเกมต่างชาติสมัยเก่าๆ แสดงผลข้อความผิดเพี้ยน

  • การแก้ปัญหาจะไม่สามารถทำได้แค่ด้วยการแทนที่ main() ด้วยเวอร์ชัน wide-character อย่างเดียว ทุกตัวแปรต้องถูกเปลี่ยนเป็น wchar_t * ซึ่งเป็นงานที่เจ็บปวดและเกิดข้อผิดพลาดได้ง่าย

    • ทางเลือกคือแปลง wide characters ที่ได้รับและยังคงใช้ "char" ต่อได้ แต่ต้องระวังอย่าให้มีการปะปนกันระหว่างสตริง ANSI/OEMCP กับสตริง UTF-8
  • รู้ว่า Windows API มีการแปลง best-fit แต่นึกไม่ถึงว่าเป็นพฤติกรรมเริ่มต้น ลักษณะการทำงานนี้ควรได้รับการห้าม

  • สงสัยว่าเช็กบ็อกซ์ Beta มีลักษณะเหมือนการตั้ง ActiveCodePage เป็น UTF-8 หรือไม่ แต่ GDI จะยึด code page ระดับโกลบอล ไม่ยอมรับการตั้งระดับโปรเซส ทำให้ไม่สามารถเลือก UTF-8 ได้ทั้งหมด