มีการค้นพบช่องโหว่ของ SQL Injection ในปลายปี 2021 โดยช่องโหว่ SQL Injection ถูกค้นพบจากคลาสที่ทาง WordPress จัดเตรียมไว้สำหรับการสืบค้นข้อมูล DB:WP_Query และทาง WordPress มีการออกแพตช์สำหรับแก้ไขข้อผิดพลาดนี้เรียบร้อยแล้วในเวอร์ชั่นล่าสุด 5.8.3
การวิเคราะห์ข้อผิดพลาด
ใน wordpress 5.8.3 ที่ได้มีการแก้ไขข้อผิดพลาดเรียบร้อยแล้ว เมื่อเปรียบเทียบกับเวอร์ชั่นก่อนหน้า คุณสามารถเห็นได้ใน function clean_query ที่มีการเพิ่มการตรวจสอบ $query[‘field’] ก่อนที่จะมีการประมวลผลของตัวแปร $query[‘terms’]
Function clean_query ถูกเรียกใช้งานจาก Function get_sql_for_clause เมื่อไปดูรายละเอียดในส่วนของโค้ดของ function จะเห็นว่างานของ function คือการรวมข้อมูลนั้นเป็นเงื่อนไขใน query SQL และ กลับไปยัง function หลัก
ดังนั้นเราจึงสามารถควบคุมข้อมูลที่ส่งคืนของฟังก์ชันนี้ได้ ซึ่งหมายความว่าเราสามารถควบคุมการสืบค้น SQL และดำเนินการ SQL Injection ได้
กลับไปที่ฟังก์ชัน clean_query ของเวอร์ชั่นก่อนหน้าที่มีการแก้ไขข้อผิดพลาด โดยค่าเริ่มต้น ค่าใน $query[‘terms’] จะถูกยกเลิกการทำซ้ำ จากนั้นเรียก $this->transform_query( $query, ‘term_taxonomy_id’ ) ;
เพื่อหลีกเลี่ยง if $query[‘taxonomy’] จะต้องว่างเปล่าหรือค่าสำหรับ is_taxonomy_hierarchical ให้คืนค่าเท็จ
ในฟังก์ชัน transform_query จะตรวจสอบ $query[‘field’] == $resulting_field หาก true จะกลับมาและไม่มีการประมวลผลเพิ่มเติม ดังนั้นหากตัวแปร $query[‘field’] เป็น term_taxonomy_id เราสามารถออกจากฟังก์ชันได้โดยไม่ต้องเปลี่ยน $query [‘เงื่อนไข’] ค่าตัวแปร
(การเปรียบเทียบในที่นี้ใช้ == และได้รับผลกระทบจากช่องโหว่ของ Loose comparisons ในบางกรณี ข้อผิดพลาดนี้สามารถใช้เพื่อสร้างประโยคแบบมีเงื่อนไขได้ตามต้องการ)
เมื่อเข้าเงื่อนไขและออกจาก function โค้ดจะกลับไปยังตำแหน่งที่เรียกใช้ function clean_query ในที่นี้กรณีถ้า function clean_query มาจาก function get_sql_for_clause ค่าในตัวแปร $query[‘terms’] จะถูกใช้สำหรับประกอบ query SQL และเป็นเป้าหมายโดยตรงเพื่อใช้ในการทำ SQL Injection
โดยสรุป เพื่อให้ SQL Injection เกิดขึ้น จะต้องเป็นไปตามสองเงื่อนไข:
- $query[‘field’] คือ term_taxonomy_id
- $query[‘taxonomy’] ว่างเปล่าหรือ is_taxonomy_hierarchical($query[‘taxonomy’]) === false
เมื่อใส่ค่าตามนี้จะส่งผลให้เกิดข้อผิดพลาดดังต่อไปนี้:
Exploit
แม้ว่าสิ่งนี้จะเป็นข้อผิดพลาดของ core wordpress แต่ถ้าเรียกใช้งานตามปกติผ่าน core wordpress จะไม่ทำให้เกิดข้อผิดพลาด ดังนั้นเพื่อเป็นการทดสอบข้อผิดพลาดนี้เราจะทำการค้นหาข้อผิดพลาดนี้ผ่านใน plugin และ theme ผ่านการเรียกใช้งาน WP_Query เพื่อใช้ในการสืบค้นข้อมูล วิธีที่จะทราบว่าข้อผิดพลาดนี้เกิดขึ้นเมื่อใช้ WP_Query($data) และ $data เป็นสิ่งที่คุณสามารถควบคุมได้
ตัวอย่างเช่น WP_Query(json_decode($_POST[‘query_vars’])) จากนั้นส่วนของข้อมูลจะมีลักษณะดังนี้
query_vars={“tax_query”:{“0”:{“field”:”term_taxonomy_id”,”terms”:[“<inject>”]}}}
หรือ
query_vars={“tax_query”:{“0”:{“taxonomy”:”nav_menu”,”field”:true,”terms”:[“<inject>”]}}}
เมื่อสร้างสภาพแวดล้อมสำหรับการทดสอบข้อผิดพลาด การเปิดใช้งานฟังก์ชัน DEBUG จะทำให้สามารถตรวจจับ SQL Injection ผ่านการอิงจากข้อผิดพลาดได้:
ข้อมูลอ้างอิงจาก
https://cognn.medium.com/sql-injection-in-wordpress-core-zdi-can-15541-a451c492897