สรุป
- พบช่องโหว่ด้านความปลอดภัยใน 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 ความคิดเห็น
ความเห็นจาก Hacker News
การแก้ไข RCE ถูกเผยแพร่แบบ "เงียบๆ" ต่อสาธารณะไปเกือบหนึ่งเดือนก่อนแล้ว
sshd(8)จะคอยติดตามสถานะการจบการทำงานของโปรเซสลูกในเซสชันก่อนยืนยันตัวตนsshdล่มใน diff ที่นำบั๊กเข้ามา ฟังก์ชันถูกรีแฟกเตอร์ดังนี้
sigdie(const char *fmt,...)sshsigdie(const char *file, const char *func, int line, const char *fmt, ...)#ifdefที่ตกหล่นไปมีคอมเมนต์ที่น่าสนใจในบันทึกประจำรุ่นของ OpenSSH
OpenBSD ไม่ได้รับผลกระทบจากช่องโหว่นี้ เพราะตัวจัดการ SIGALRM เรียก
syslog_r()syslog()เวอร์ชันที่ปลอดภัยสำหรับสัญญาณแบบอะซิงโครนัสจากการตรวจสอบ
syslog(3)ของ musl พบว่าไม่ถูกเอ็กซ์พลอยต์ได้ง่ายเหมือน glibcมีแพตช์สำหรับ FreeBSD ออกมาแล้ว และเนื่องจากไม่ได้ใช้ glibc จึงมีแนวโน้มว่าจะไม่ได้รับผลกระทบ
การตั้งค่า
LoginGraceTime 0ในไฟล์sshd_configสามารถช่วยบรรเทาปัญหาได้มีแพตช์สำหรับ Debian 12 ออกมาแล้ว ส่วน Debian 11 ไม่ได้รับผลกระทบ
มีการให้ลิงก์ไปยังบันทึกประจำรุ่นของ OpenSSH และแพตช์ขั้นต่ำ
ในมุมมองแบบอิสระ การพบช่องโหว่เพียงจุดเดียวก็น่าจะเพียงพอแล้ว