Cacti: การรันโค้ดระยะไกลที่ไม่ได้รับการตรวจสอบความถูกต้อง
Cacti เป็นโซลูชันการเฝ้าระวังบนเว็บแบบ open-source ที่มีประวัติย้อนหลังไปถึงการเปิดตัวครั้งแรกใน 2001 ปัจจุบันได้มีการจัดตั้ง บำรุงรักษา และปรับใช้ทั่วโลก การค้นหาอย่างรวดเร็วของ Shodan แสดงให้เห็นว่าองค์กรหลายพันแห่งเปิดเผยตัวอย่างของพวกเขาบนอินเทอร์เน็ต
เพื่อปรับปรุงเทคโนโลยีที่อยู่เบื้องหลังโซลูชัน Clean Code ของเราอย่างต่อเนื่อง เราสแกนโครงการ open-source และประเมินผลอย่างสม่ำเสมอ ในกรณีของ Cacti เครื่องยนต์ของเรารายงานคำสั่งที่มีแนวโน้มที่จะโจมตีช่องโหว่ การวิเคราะห์การค้นพบนี้พบว่าผู้โจมตีที่ไม่ได้รับการตรวจสอบสิทธิ์สามารถใช้การตรวจสอบสิทธิ์เพื่อหลีกเลี่ยงช่องโหว่ได้
บทความนี้ จะสรุปผลกระทบของช่องโหว่ที่พบและเจาะลึกในรายละเอียดทางเทคนิค นอกจากนี้เราจะระบุสาเหตุหลักของช่องโหว่และอธิบายว่าแพตช์ของแอปพลิเคชันสามารถลดช่องโหว่ได้อย่างไร
ผลกระทบ
ช่องโหว่เหล่านี้ส่งผลกระทบต่อ Cacti version 1.2.22 และที่ต่ำกว่าจะถูกติดตามเป็น CVE-2022-46169 ด้วยคะแนน CVSS 9.8. หากอุปกรณ์ตรวจสอบใดๆ ใช้แหล่งข้อมูลเฉพาะผู้โจมตีที่ไม่ผ่านการตรวจสอบสามารถโจมตีโดยใช้อินสแตนซ์ Cacti ที่เสี่ยงต่อการถูกโจมตี การใช้ประโยชน์จากช่องโหว่นี้ผู้โจมตีสามารถเรียกใช้คําสั่งโดยพลการภายใต้ผู้ใช้คนเดียวกันที่เรียกใช้กระบวนการเว็บเซิร์ฟเวอร์
วิดีโอต่อไปนี้แสดงให้เห็นถึงการโจมตีเซิร์ฟเวอร์ที่ใช้ Cacti เวอร์ชันที่มีช่องโหว่:
ที่ปรึกษาด้านความปลอดภัยมีแพตช์ที่ผู้ดูแลระบบต้องนำไปใช้กับ Cacti versions 1.2.22 และต่ำกว่าแพตช์จะได้รับการปล่อยตัวเป็นส่วนหนึ่งของเวอร์ชัน 1.2.23 และ 1.3.0.
เราขอแนะนำให้ใช้แพตช์ที่มีให้และอัปเดตเป็นเวอร์ชันใหม่เมื่อพร้อมใช้งาน
รายละเอียดทางเทคนิค (Technical Details)
ในส่วนนี้ เราจะดูช่องโหว่ที่รายงานโดย SonarCloud และพิจารณาว่าผู้โจมตีสามารถใช้ประโยชน์จากช่องโหว่นั้นได้อย่างไร การโจมตีที่เราสาธิตประกอบด้วยช่องโหว่ของโค้ดที่แตกต่างกันสองช่อง:
- ข้ามการตรวจสอบสิทธิ์ความถูกต้อง: การตรวจสอบสิทธิ์ตามชื่อโฮสต์ไม่สามารถดำเนินการได้อย่างปลอดภัยสำหรับการติดตั้ง Cacti ส่วนใหญ่
- การโจมตีคำสั่ง การป้อนข้อมูลของผู้ใช้ที่ไม่ได้เริ่มใช้งานจะแพร่กระจายไปยังสตริงที่ใช้ในการประมวลผลคำสั่งภายนอก
ข้ามการตรวจสอบสิทธิ์ความถูกต้อง
สคริปต์ remote_agent.php ควรเข้าถึงได้โดยลูกค้าที่ได้รับอนุญาตเท่านั้น ด้วยเหตุนี้จึงมีการตรวจสอบการอนุญาตในตอนต้นของเอกสาร
cacti/remote_agent.php
ฟังก์ชัน remote_client_authorized ดึงข้อมูลที่อยู่ IP ของลูกค้า ($client_addr) แก้ไขเป็นชื่อโฮสต์ที่เกี่ยวข้อง ($client_name) และตรวจสอบว่าตาราง poller มีรายการที่มีชื่อโฮสต์นี้หรือไม่:
cacti/lib/html_utility.php
ส่วนของโค้ดด้านบนแสดงให้เห็นฟังก์ชัน get_client_addr เพื่อดึงที่อยู่ IP ของลูกค้า ฟังก์ชันนี้พิจารณาส่วนหัว HTTP ที่ผู้โจมตีต่างๆ สามารถควบคุมได้เมื่อกำหนดที่อยู่ IP:
cacti/lib/functions.php
ในขณะที่ตัวแปร REMOTE_ADDR ถูกตั้งค่าเป็นที่อยู่ IP ต้นทางจากการเชื่อมต่อกับเว็บเซิร์ฟเวอร์ ตัวแปรที่ขึ้นต้นด้วย HTTP_ จะถูกเติมด้วยส่วนหัว HTTP ที่สอดคล้องกันที่ได้รับจากลูกค้า หากไม่มีอินสแตนซ์กรองส่วนหัว HTTP เหล่านี้ระหว่างลูกค้าและเว็บเซิร์ฟเวอร์ (เช่น พร็อกซี่ย้อนกลับ) ผู้โจมตีสามารถควบคุมค่าเหล่านี้ได้อย่างสมบูรณ์
กลับไปที่ส่วนของโค้ดเดิมก่อนหน้านี้ ตาราง poller มีรายการเริ่มต้นที่มีชื่อโฮสต์ของเซิร์ฟเวอร์ที่ใช้ Cacti ด้วยเหตุนี้ผู้โจมตีจึงสามารถข้ามการตรวจสอบ remote_client_authorized โดยระบุส่วนหัว HTTP X-Forwarded: <TARGET-IP> : ด้วยวิธีนี้ฟังก์ชัน get_client_addr จะส่งคืนค่ากลับมาเป็นค่าที่อยู่ IP ของเซิร์ฟเวอร์ที่ใช้ Cacti การเรียกใช้ gethostbyaddr จะแก้ไขที่อยู่ IP นี้เป็นชื่อโฮสต์ของเซิร์ฟเวอร์ซึ่งจะผ่านการตรวจสอบโดยชื่อโฮสต์ poller เนื่องจากรายการเริ่มต้น
สิ่งนี้อนุญาตให้ผู้โจมตีที่ไม่ได้รับการตรวจสอบความถูกต้องสามารถเข้าถึงฟังก์ชันการทำงานของ remote_agent.php
คำสั่งการโจมตีช่องโหว่
ค้นพบช่องโหว่การโจมตีคำสั่งที่น่าสนใจใน remote_agent.php เมื่อสแกน Cacti ด้วย SonarCloud. คุณสามารถตรวจสอบการค้นพบได้โดยตรงบน SonarCloud:
ตามกระบวนการโจมตีที่ระบุไว้ พารามิเตอร์ poller_id ที่ให้โดยผู้ใช้จะแพร่กระจายไปยังพารามิเตอร์แรกของ proc_open โดยไม่ผ่านการฆ่าเชื้อหรือเปลี่ยนแปลงใดๆ สิ่งนี้แนะนำช่องโหว่การโจมตีคำสั่งในฟังก์ชัน poll_for_data
ผู้โจมตีสามารถเรียกใช้ฟังก์ชันที่มีช่องโหว่ได้โดยการตั้งค่าพารามิเตอร์ action เป็น polldata :
cacti/remote_agent.php
ในตอนต้นฟังก์ชัน poll_for_data จะเรียกค่าพารามิเตอร์ host_id และ poller_id อย่างไรก็ตามมีความแตกต่างที่สำคัญ: พารามิเตอร์ host_id มาจาก get_filter_request_var ในขณะที่พารามิเตอร์ poller_id มาจาก get_nfilter_request_var; สังเกตตัวอักษร n เพิ่มเติมที่นี่:
cacti/remote_agent.php
ในขณะที่ฟังก์ชัน get_filter_request_var สำหรับการดึงพารามิเตอร์ poller_id อนุญาตให้ใช้สตริงใดๆ เมื่อฟังก์ชัน get_nfilter_request_var ตรวจสอบว่าพารามิเตอร์ที่ดึงเป็นจำนวนเต็มหรือไม่
ต่อไปตามกระแสการโจมตี เราจะเห็นการดึงรายการ poller จากฐานข้อมูล หากการกระทำของรายการใดรายการหนึ่งถูกตั้งค่าเป็น POLLER_ACTION_SCRIPT_PHP การเรียกร้องที่มีช่องโหว่ proc_open จะออก:
cacti/remote_agent.php
ซึ่งหมายความว่าเมื่อมีโครงการที่มีการดำเนินการ POLLER_ACTION_SCRIPT_PHP ผู้โจมตีสามารถโจมตีคำสั่งโดยพลการโดยการใช้พารามิเตอร์ poller_id สิ่งนี้อาจเกิดขึ้นกับตัวอย่างการผลิต เนื่องจากการดำเนินการนี้ถูกเพิ่มโดยเทมเพลตที่กำหนดไว้ล่วงหน้า เช่น “Device – Uptime” หรือ “Device – Polling Time”
ผู้โจมตีจะต้องระบุไอดีที่สอดคล้องกัน เพื่อให้การสืบค้นฐานข้อมูลส่งคืนรายการดังกล่าว เนื่องจากหมายเลขไอดีตามลำดับจากน้อยไปมากและหลายร้อยไอดีสามารถส่งได้ในคำขอเดียวโดยการระบุอาร์เรย์ ผู้โจมตีสามารถค้นหาตัวระบุที่ถูกต้องได้อย่างง่ายดาย
แพตช์ (Patches)
ข้ามการตรวจสอบสิทธิ์ความถูกต้อง
การหลีกเลี่ยงการตรวจสอบสิทธิ์สามารถทำได้โดยอนุญาตให้ผู้ดูแลระบบกำหนดค่าส่วนหัวพร็อกซี HTTP ที่ควรปฏิบัติตามในการกำหนดที่อยู่ IP ของลูกค้า โดยค่าเริ่มต้นจะใช้เฉพาะตัวแปรเซิร์ฟเวอร์ REMOTE_ADDR เพื่อให้แน่ใจว่าการกำหนดค่าเริ่มต้นที่ปลอดภัย
นอกจากนี้ แพตช์นี้อนุญาตให้ผู้ดูแลระบบใช้ส่วนหัวพร็อกซี HTTP ตัวอย่างเช่น ในสถานการณ์ที่อินสแตนซ์ Cacti ตั้งอยู่หลังจากพร็อกซีย้อนกลับ
การโจมตีคำสั่ง
ลดช่องโหว่การโจมตีคำสั่งโดยการใช้การแก้ไขสองแหล่งที่มา (ดึงข้อมูลผู้ใช้) และตัวรับสัญญาณ (เรียก proc_open) ในซอร์สโค้ดฟังก์ชัน get_nfilter_request_var จะถูกแทนที่ด้วย get_filter_request_var เพื่อให้แน่ใจว่าพารามิเตอร์ poller_id เป็นจำนวนเต็ม:
cacti/remote_agent.php
ที่ Sink ตัวแปร $poller_id จะหมายถึงการผ่าน cacti_escapeshellarg ก่อนที่จะแทรกสตริงคำสั่งสำหรับ proc_open :
cacti/remote_agent.php
การแก้ไขครั้งที่สองอาจดูเหมือนไม่จำเป็น เนื่องจากการตรวจสอบที่ซอร์สโค้ดได้ตรวจสอบให้แน่ใจว่าตัวแปรมีจำนวนเต็ม อย่างไรก็ตาม การปรับซอร์สโค้ดอาจเปลี่ยนสมมติฐานนี้ในอนาคต โดยนําช่องโหว่ที่สําคัญกลับมาใช้ใหม่
ดังนั้นการแก้ไขทั้งสองนี้จึงเป็นสิ่งจำเป็น: การป้อนข้อมูลของผู้ใช้ควรได้รับการตรวจสอบและ จำกัด ภายในค่าสมมติฐาน (ในกรณีนี้เป็นจำนวนเต็ม) นอกจากนี้คุณควรเปลี่ยนค่าก่อนที่จะส่งไปยังฟังก์ชันที่มีช่องโหว่ เช่น proc_open
Timeline
วันที่ | การดำเนินการ |
---|---|
2022-12-02 | เรารายงานปัญหาทั้งหมดไปยังผู้ขาย |
2022-12-02 | ผู้ขายยืนยันปัญหา |
2022-12-02 | ผู้ขายเสนอแพตช์ผ่านที่ปรึกษาด้านความปลอดภัย |
ตามข้อมูลของเรา @stevenseeley ค้นพบช่องโหว่เดียวกันอย่างอิสระและรายงานผ่าน ZDI ในปี 2022-11-25 ในขณะที่เขียนบทความนี้ยังไม่สามารถรับรายละเอียดเพิ่มเติมได้
สรุป
ในบทความนี้เรามีรายละเอียดเกี่ยวกับการโจมตีช่องโหว่ของคำสั่งที่สำคัญในโซลูชันการตรวจสอบไอที Cacti เครื่องมือสแกนของเราจะตรวจจับช่องโหว่ของรหัสนี้โดยอัตโนมัติ เรายังพบช่องโหว่ในกลไกการพิสูจน์อัตลักษณ์ที่เปิดโอกาสให้มีการใช้ประโยชน์จากตำแหน่งที่ไม่เคยผ่านการพิสูจน์อัตลักษณ์ เรายังดูแพตช์ที่ใช้ในการแก้ไขช่องโหว่
ความจริงที่ว่าแพทช์เช่นเดียวกับหนึ่งในสองโปรแกรมแก้ไขที่มุ่งเป้าไปที่การโจมตีคำสั่งช่องโหว่ บล็อกช่องโหว่ เน้นความสำคัญของการใช้ความปลอดภัยในทุกระดับ ดังนั้นส่วนสำคัญของวิธีการคลีนโค้ดของเรา คือ การใช้ความปลอดภัยเป็นส่วนสำคัญในการพัฒนา ซึ่งทำให้มั่นใจได้ว่าการพิจารณาเรื่องความปลอดภัยไม่เพียงใช้กับสถานะปัจจุบันของซอร์สโค้ด ลดความเสี่ยงในการแนะนำช่องโหว่ใหม่
อ้างอิง Sonar
สอบถามเพิ่มเติม
💬Line: @monsterconnect https://lin.ee/cCTeKBE
☎️Tel: 02-026-6664
📩Email: [email protected]
📝 Price List สินค้า https://bit.ly/3mSpuQY
🛍 Lazada Shop https://www.lazada.co.th/shop/monsteronline/
🛒 Shopee Online https://shopee.co.th/shop/849304465/
🏷 LINE SHOPPING https://shop.line.me/@monsterconnect
🏢 Linkedin : https://www.linkedin.com/company/monster-connect-co-ltd/
📺 YouTube : https://www.youtube.com/c/MonsterConnectOfficial
📲 TikTok : https://www.tiktok.com/@monsteronlines
🌍 Website : www.monsterconnect.co.th