Cloudflare อธิบายเหตุล่ม Regular Expression ".*.*=.*" พาล่มทั้งระบบ

by lew
16 July 2019 - 17:39

หลังจาก Cloudflare ล่มเมื่อต้นเดือนที่ผ่านมา โดยได้ชี้แจงเหตุไปแล้วว่าเกิดจากกฎไฟร์วอลล์ข้อเดียว ทางบริษัทก็ยังเขียนบล็อกรายงานถึงสาเหตุการล่มเพิ่มเติม โดยกฎไฟร์วอลล์ที่ว่านั้นมีกฎเต็มๆ ว่า

(?:(?:\"|'|\]|\}|\\|\d|(?:nan|infinity|true|false|null|undefined|symbol|math)|\`|\-|\+)+[)]*;?((?:\s|-|~|!|{}|\|\||\+)*.*(?:.*=.*)))

ส่วนที่สำคัญที่สุดคือส่วนท้าย ที่มี non-capturing group (จัดกลุ่มโดยไม่ต้องการให้ regular expression (RE) ตัดสตริงในกลุ่มนี้แยกออกมาให้) โดยเขียนแบบไม่จัดกลุ่มเหลือได้ว่า .*.*=.* การเขียน RE เช่นนี้ทำให้ซีพียูเต็มได้ยาวนาน จากปัญหา backtrack ในเอนจิน RE บางตัว

เนื่องจากกฎสามารถเขียนเป็นภาษาบ้านๆ ได้ว่า อะไรก็ได้-ตามด้วยอะไรก็ได้-ตามด้วยเครื่องหมายเท่ากับ-ตามด้วยอะไรก็ได้ กฎเช่นนี้ทำให้กระบวนการตรวจสอบว่าสตริงตรงตามกฎหรือไม่ในเอนจิน RE ที่ใช้เทคนิค backtrack ใช้เวลานานกว่าปกติอย่างมาก โดยสตริงง่ายๆ แค่ x=x จะใช้การตรวจสอบถึง 23 ขั้นตอน และเมื่อสตริงยาวขึ้นเป็น 20 ตัวอักษร ก็ใช้การตรวจสอบถึง 555 ขั้นตอน หากสตริงไม่ตรงตามกฎเลย เช่น ไม่มีเครื่องหมายเท่ากับ จะใช้ถึง 4,067 ขั้นตอน

การเขียน RE ที่ดี ควรระมัดระวังให้ตรวจกฎได้แน่ชัด ไม่สร้างกฎที่กำกวมโดยไม่จำเป็น หรือเลือกใช้เอนจิน RE ที่ไม่ใช้เทคนิค backtrack แต่สร้าง finite automata ขึ้นมาตรวจสอบสตริง โดยทั่วไปแล้ว regular expression จะเทียบเท่า finite automata (จากวิชา Theory of Computation ที่บุกเบิกโดย Alan Turing)

ทาง Cloudflare ไม่ได้โทษคนเขียนกฎไฟร์วอลล์ข้อนี้เพียงอย่างเดียว แต่ยอมรับว่าปัญหาเกิดจากความผิดพลาดหลายๆ ส่วนประกอบกัน โดยก่อนหน้านี้มีโค้ดป้องกันกฎไฟร์วอลล์ใช้ซีพียูเกินกำหนดอยู่ แต่ถูกถอดออกไปด้วยความผิดพลาด, การเลือกใช้เอนจิน RE ที่ไม่เหมาะสม, การกู้คืนระบบที่ทำได้ช้าเพราะระบบภายในของบริษัทเองก็มีปัญหาไปด้วย ตอนนี้จึงเดินหน้าแก้ทุกปัญหาไปพร้อมๆ กัน

ที่มา - Cloudflare

Blognone Jobs Premium