ปลดล็อกความปลอดภัย: เจาะลึกช่องโหว่ HTTP/2 ใน SwiftNIO

ปลดล็อกความปลอดภัย: เจาะลึกช่องโหว่ HTTP/2 ใน SwiftNIO

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

บทความนี้จะพาคุณไปสำรวจการค้นพบและแก้ไขช่องโหว่สำคัญใน SwiftNIO ซึ่งเป็นกรอบการทำงานสำหรับแอปพลิเคชันเครือข่ายแบบไม่บล็อกที่ Apple พัฒนาขึ้น โดยเน้นวิธีการตรวจสอบโค้ดด้วยตนเองและการวิเคราะห์แบบคงที่ เพื่อทำความเข้าใจถึงอันตรายที่ซ่อนอยู่และวิธีที่เราสามารถทำให้โลกออนไลน์ปลอดภัยยิ่งขึ้น

ทำความเข้าใจช่องโหว่: ระเบิดหน่วยความจำด้วย HPACK

ช่องโหว่ที่ถูกค้นพบครั้งนี้คือ HTTP/2 denial-of-service (DoS) หรือการโจมตีเพื่อทำให้บริการไม่สามารถใช้งานได้ โดยเฉพาะอย่างยิ่ง มันคือรูปแบบที่เรียกว่า HPACK decompression bombing

HTTP/2 มีกลไกการบีบอัดส่วนหัวที่เรียกว่า HPACK เพื่อลดขนาดข้อมูลที่ต้องส่งผ่านเครือข่าย ทำให้การสื่อสารเร็วขึ้นและมีประสิทธิภาพมากขึ้น

แต่ปัญหากลับอยู่ที่กระบวนการคลายการบีบอัดนี่เอง

จินตนาการว่าผู้โจมตีสามารถส่งข้อมูลที่ถูกบีบอัดเพียงเล็กน้อย แต่เมื่อเซิร์ฟเวอร์รับไปและพยายามคลายการบีบอัด ข้อมูลนั้นกลับขยายตัวออกมาอย่างมหาศาล กิน หน่วยความจำ และ ซีพียู ของเซิร์ฟเวอร์จนหมดสิ้นในพริบตา

ผลลัพธ์คือ เซิร์ฟเวอร์ไม่สามารถประมวลผลคำขอใดๆ ได้อีกต่อไป กลายเป็นบริการที่ถูกปฏิเสธ หรือที่รู้จักกันในชื่อ DoS นั่นเอง

ตามรอยบั๊ก: พบต้นตอในโค้ด

การค้นหาช่องโหว่นี้เริ่มต้นจากการตรวจสอบโค้ดของ SwiftNIO อย่างละเอียด โดยเฉพาะในส่วนที่จัดการกับเฟรม HTTP/2 และการบีบอัด HPACK

นักวิจัยได้มุ่งความสนใจไปที่ไฟล์ HTTP2FrameDecoder.swift ซึ่งเป็นส่วนที่รับผิดชอบการถอดรหัสข้อมูล HTTP/2

จากการไล่ดูโค้ด พบว่า HPACKDecoder ซึ่งเป็นตัวจัดการการคลายการบีบอัด HPACK ถูกสร้างขึ้นโดย ไม่มีการกำหนดค่า maxDynamicTableSize

HPACK ใช้สิ่งที่เรียกว่า Dynamic Table เพื่อเก็บสถานะการบีบอัดข้อมูลส่วนหัวที่ใช้บ่อย เพื่อเพิ่มประสิทธิภาพ

เมื่อไม่มีการตั้งค่า maxDynamicTableSize เท่ากับว่า Dynamic Table นี้สามารถขยายขนาดได้เรื่อยๆ ไม่มีที่สิ้นสุด

การโจมตีจะเกิดขึ้นได้เมื่อผู้โจมตีส่งส่วนหัว HPACK ที่ออกแบบมาเป็นพิเศษ เพื่อทำให้ Dynamic Table บนเซิร์ฟเวอร์ขยายตัวอย่างต่อเนื่องและกิน หน่วยความจำ จนหมด

นี่คือช่องโหว่ระดับไลบรารี ซึ่งหมายความว่าแอปพลิเคชันใดๆ ที่ใช้ SwiftNIO โดยไม่ระมัดระวัง อาจเสี่ยงต่อการถูกโจมตีได้

การแก้ไขที่เรียบง่ายแต่ทรงพลัง

การแก้ไขช่องโหว่นี้ทำได้ไม่ยาก แต่กลับสำคัญอย่างยิ่ง

แนวทางคือการกำหนดค่า maxDynamicTableSize ให้กับ HPACKDecoder เพื่อจำกัดขนาดของ Dynamic Table ไม่ให้เติบโตมากเกินไป

ค่าเริ่มต้นที่เหมาะสมที่ถูกเลือกคือ 4KB ซึ่งเป็นมาตรฐานที่พบในไลบรารี HTTP/2 อื่นๆ เช่น Node.js และ Go

การกำหนดขีดจำกัดนี้ช่วยป้องกันไม่ให้ Dynamic Table ถูกใช้เป็นช่องทางในการโจมตีแบบ Memory Exhaustion หรือการใช้หน่วยความจำจนหมดนั่นเอง

หลังจากที่มีการเสนอโค้ดแก้ไขนี้ไปยังโครงการ SwiftNIO ก็ได้รับการยอมรับและรวมเข้ากับโค้ดหลักในเวลาต่อมา เพื่อเพิ่มความปลอดภัยให้กับผู้ใช้งานทุกคน

ช่องโหว่นี้ได้รับการกำหนดรหัสเป็น CVE-2022-32766 เพื่อให้เป็นที่รับรู้และสามารถติดตามสถานะความปลอดภัยได้

เหตุการณ์นี้แสดงให้เห็นถึงความสำคัญของการ ตรวจสอบโค้ด อย่างสม่ำเสมอ และความเข้าใจอย่างลึกซึ้งในโปรโตคอลพื้นฐานที่เราใช้งาน

แม้แต่โครงการขนาดใหญ่และดูแลอย่างดีเยี่ยม ก็ยังอาจมีช่องโหว่ที่ซ่อนอยู่ได้จากการขาดการตั้งค่าหรือข้อจำกัดเล็กๆ น้อยๆ

การทำงานร่วมกันในชุมชน โอเพนซอร์ส คือกุญแจสำคัญที่ทำให้ระบบนิเวศซอฟต์แวร์ของเราปลอดภัยและแข็งแกร่งยิ่งขึ้นอย่างต่อเนื่อง