1 คะแนน โดย GN⁺ 2024-07-02 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

สรุป

  • พบช่องโหว่ด้านความปลอดภัยใน OpenSSH: พบช่องโหว่การรันโค้ดจากระยะไกล (RCE) บนเซิร์ฟเวอร์ OpenSSH (sshd) ที่เกิดจาก race condition ในตัวจัดการสัญญาณ ช่องโหว่นี้ส่งผลต่อ sshd ในการตั้งค่าเริ่มต้น
  • ที่มาของช่องโหว่: ช่องโหว่นี้เป็นการกลับมาของ CVE-2006-5051 ที่เคยถูกรายงานในปี 2006 และเกิดขึ้นจากการเปลี่ยนแปลงโค้ดที่ถูกนำเข้าใน OpenSSH 8.5p1 เมื่อเดือนตุลาคม 2020
  • ผลกระทบของช่องโหว่: สามารถถูกโจมตีจากระยะไกลได้บนระบบ Linux ที่ใช้ glibc และส่งผลต่อโค้ดที่มีสิทธิพิเศษของ sshd ทำให้สามารถรันโค้ดจากระยะไกลด้วยสิทธิ์ root ได้
  • วิธีการใช้ประโยชน์จากช่องโหว่: การโจมตีช่องโหว่นี้จำเป็นต้องค้นหาเส้นทางโค้ดเฉพาะและขัดจังหวะในจังหวะที่เหมาะสม เพื่อทำเช่นนั้นจึงเริ่มจาก OpenSSH รุ่นเก่าและขยายไปสู่รุ่นใหม่
  • แพตช์และการบรรเทา: มีการจัดเตรียมแพตช์และวิธีบรรเทาเพื่อแก้ไขช่องโหว่นี้

SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, ปี 2005)

ภาคทฤษฎี

  • ตัวจัดการ SIGALRM: ตัวจัดการ SIGALRM ของเวอร์ชันนี้เรียก packet_close() ซึ่งจะเรียก buffer_free() และต่อเนื่องไปยัง xfree() กับ free() โดย free() ไม่ปลอดภัยต่อ asynchronous signal
  • การวิเคราะห์โค้ด malloc: จากการวิเคราะห์โค้ด malloc พบเส้นทางที่สามารถใช้ประโยชน์จากช่องโหว่ได้เมื่อการเรียก free() ถูกขัดจังหวะด้วย SIGALRM แล้วถูกเรียกซ้ำอีกครั้งภายในตัวจัดการ SIGALRM

ภาคปฏิบัติ

  • วิธีโจมตี: ขัดจังหวะการเรียก free() ในโค้ดที่แยกวิเคราะห์คีย์สาธารณะ DSA แล้วใช้ประโยชน์จากสิ่งนี้ภายในตัวจัดการ SIGALRM เพื่อให้บรรลุการรันโค้ดจากระยะไกล
  • การชนะ race condition: ต้องพยายามประมาณ 10,000 ครั้งเพื่อชนะ race condition นี้ และโดยเฉลี่ยใช้เวลาราว 1 สัปดาห์

จังหวะเวลา

  • กลยุทธ์ด้าน timing: เพื่อลด network latency ให้เหลือน้อยที่สุด จะส่งไบต์สุดท้ายในวินาทีสุดท้ายและติดตาม round-trip time เพื่อปรับ timing ซึ่งช่วยเพิ่มโอกาสชนะ race condition

SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, ปี 2006)

ภาคทฤษฎีรอบที่ 1

  • ตัวจัดการ SIGALRM: ตัวจัดการ SIGALRM ของเวอร์ชันนี้ไม่ได้เรียก packet_close() และเนื่องจากฟังก์ชัน malloc ล็อกเสมอ จึงต้องหาวิธีแก้แบบอื่น
  • การใช้ PAM: พบว่า pam_end() ของ PAM ไม่ปลอดภัยต่อ asynchronous signal และจึงสำรวจเส้นทางที่สามารถใช้ประโยชน์จากสิ่งนี้ได้

ภาคทฤษฎีรอบที่ 2

  • การวิเคราะห์ pam_start(): หาก pam_start() ถูกขัดจังหวะ โครงสร้าง PAM อาจค้างอยู่ในสถานะที่ไม่สอดคล้องกัน และสามารถนำไปใช้ประโยชน์ได้ภายในตัวจัดการ SIGALRM
  • เทคนิค House of Mind: ใช้เทคนิค House of Mind เพื่อบิดเบือนการจัดสรรหน่วยความจำในการโจมตี และทำให้สามารถรันโค้ดจากระยะไกลด้วยสิทธิ์ root ได้

ภาคปฏิบัติ

  • วิธีโจมตี: ใช้ชื่อผู้ใช้ที่ยาวเพื่อบิดเบือนการจัดสรรหน่วยความจำ และเพิ่มโอกาสชนะ race condition ด้วยการเรียก pam_start() หลายครั้ง

จังหวะเวลา

  • กลยุทธ์ด้าน timing: นำกลยุทธ์ timing ที่ใช้ใน Debian เวอร์ชันก่อนหน้ากลับมาใช้เพื่อเพิ่มโอกาสชนะ race condition โดยเฉลี่ยใช้เวลา 1-2 วัน

SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (Debian 12.5.0, ปี 2024)

ภาคทฤษฎี

  • ตัวจัดการ SIGALRM: ตัวจัดการ SIGALRM ของเวอร์ชันนี้เรียก syslog() ซึ่งจะเรียกฟังก์ชันที่ไม่ปลอดภัยต่อ asynchronous signal
  • การวิเคราะห์ glibc: syslog() ของ glibc เรียก malloc ซึ่งไม่ปลอดภัยต่อ asynchronous signal นอกจากนี้ ฟังก์ชัน malloc ของ glibc จะไม่ล็อกเมื่อทำงานแบบ single-threaded

แพตช์และการบรรเทา

  • แพตช์: ได้รายงานช่องโหว่นี้ต่อผู้พัฒนา OpenSSH และจัดเตรียมแพตช์สำหรับแก้ไขไว้แล้ว

ความเห็นของ GN⁺

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

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

 
GN⁺ 2024-07-02
ความเห็นจาก Hacker News
  • การแก้ไข RCE ถูกเผยแพร่แบบ "เงียบๆ" ต่อสาธารณะไปเกือบหนึ่งเดือนก่อนแล้ว

    • เมื่อเปิดใช้งาน PerSourcePenalties, sshd(8) จะคอยติดตามสถานะการจบการทำงานของโปรเซสลูกในเซสชันก่อนยืนยันตัวตน
    • จะบันทึกค่าปรับเมื่อไคลเอนต์พยายามยืนยันตัวตนซ้ำๆ หรือเมื่อ sshd ล่ม
    • แพตช์นี้เปลี่ยนสถาปัตยกรรมของไบนารีเพื่อลบช่องโหว่บางประเภทออก และบรรเทาคลาสของการเอ็กซ์พลอยต์ทั้งชุด
  • ใน diff ที่นำบั๊กเข้ามา ฟังก์ชันถูกรีแฟกเตอร์ดังนี้

    • ฟังก์ชันเดิม: sigdie(const char *fmt,...)
    • ฟังก์ชันหลังรีแฟกเตอร์: sshsigdie(const char *file, const char *func, int line, const char *fmt, ...)
    • มี #ifdef ที่ตกหล่นไป
    • ถ้ามีคนตรวจ pull request มากกว่านี้ก็น่าจะป้องกันได้
  • มีคอมเมนต์ที่น่าสนใจในบันทึกประจำรุ่นของ OpenSSH

    • มีการสาธิตการเอ็กซ์พลอยต์สำเร็จบนระบบ Linux/glibc แบบ 32 บิตที่เปิด ASLR
    • ดูเหมือนว่าจะเป็นไปได้บนระบบ 64 บิตด้วย
  • OpenBSD ไม่ได้รับผลกระทบจากช่องโหว่นี้ เพราะตัวจัดการ SIGALRM เรียก syslog_r()

    • ใช้ syslog() เวอร์ชันที่ปลอดภัยสำหรับสัญญาณแบบอะซิงโครนัส
    • ต้องมีการรีแฟกเตอร์เพื่อลดปริมาณโค้ดภายในตัวจัดการสัญญาณให้น้อยที่สุด
  • จากการตรวจสอบ syslog(3) ของ musl พบว่าไม่ถูกเอ็กซ์พลอยต์ได้ง่ายเหมือน glibc

    • ทุกอย่างอยู่บนสแตกหรืออยู่ในตัวแปรสแตติกที่ป้องกันการเรียกซ้ำ
  • มีแพตช์สำหรับ FreeBSD ออกมาแล้ว และเนื่องจากไม่ได้ใช้ glibc จึงมีแนวโน้มว่าจะไม่ได้รับผลกระทบ

  • การตั้งค่า LoginGraceTime 0 ในไฟล์ sshd_config สามารถช่วยบรรเทาปัญหาได้

    • แม้จะทำให้เสี่ยงต่อการโจมตีแบบปฏิเสธการให้บริการ แต่จะป้องกันการรันโค้ดจากระยะไกลได้
  • มีแพตช์สำหรับ Debian 12 ออกมาแล้ว ส่วน Debian 11 ไม่ได้รับผลกระทบ

  • มีการให้ลิงก์ไปยังบันทึกประจำรุ่นของ OpenSSH และแพตช์ขั้นต่ำ

  • ในมุมมองแบบอิสระ การพบช่องโหว่เพียงจุดเดียวก็น่าจะเพียงพอแล้ว

    • แต่คนมักจะจริงจังหรือยอมจ่ายค่าตอบแทนก็ต่อเมื่อพบเชนทั้งหมด