OpenSSL Weak Key
ไม่ได้ blog เสียนานด้วยเหตุผลหลาย ๆ อย่าง การสลับงานไปมาหลาย ๆ อย่างก็ส่วนหนึ่ง กิจกรรมของครอบครัวก็อีกส่วนหนึ่ง ขี้เกียจเขียนก็อีกส่วนหนึ่ง เอิ๊ก
ได้ข่าว DSA 1571-1 จากนิวตรอนเมื่อวันก่อน เล่นเอาวุ่น เมื่อมีการพบความหละหลวมของกุญแจที่สร้างโดย openssl ของ Debian/Ubuntu ตั้งแต่รุ่น 0.9.8c-1 เป็นต้นมา โดยเป็นแพตช์เฉพาะของ Debian มีผลตั้งแต่ etch เป็นต้นมา
ก่อนหน้านั้นไม่กี่ชั่วโมง ก็ได้รับแจ้งจาก alioth admin ว่าจะลบ SSH public key ทั้งหมดออกจากเซิร์ฟเวอร์ เพราะปัญหานี้
อีกไม่กี่ชั่วโมงถัดมา บล็อกโนเนะก็ ออกข่าว นี้เหมือนกัน
พอรู้ว่าอะไรเป็นอะไร ก็รีบนึกทันที ว่ามีการสร้างกุญแจไว้ที่ไหนบ้างในช่วงที่ผ่านมา แต่เพื่อความแน่ใจ ก็ตรวจสอบแก้ไขตาม คำแนะนำ เสีย แล้วก็เขียน สรุปขั้นตอนสำคัญ ไว้ที่ debianclub ด้วย
อาการของปัญหาคือ กุญแจที่สร้างจาก openssl รุ่นที่มีปัญหา มีความเป็นไปได้ในการสุ่มเพียง 32767 หรือ 2^15 แบบ ซึ่งอยู่ในวิสัยของการโจมตีแบบ brute force ได้ ดังนั้น ระบบใด ๆ ก็ตาม ที่ผู้ใช้เอากุญแจสาธารณะ SSH ดังกล่าวไปติดตั้งไว้ ก็มีสิทธิ์ถูกเจาะระบบในลักษณะการเดารหัสผ่านได้
ดังนั้น อย่างที่ Erich Schubert (DD คนหนึ่ง) ได้ blog ไว้ ปัญหานี้จึงไม่ได้กระทบแค่ผู้ใช้ Debian/Ubuntu เท่านั้น แต่ระบบ Linux, FreeBSD หรือ Unix ใด ๆ ที่ผู้ใช้ Debian/Ubuntu มีบัญชีอยู่ และเอากุญแจสาธารณะไปติดตั้งไว้ ก็มีสิทธิ์ถูกเจาะได้ทั้งนั้น จึงขอฝากเตือน admin ทั่วไปที่ไม่ได้ใช้ Debian/Ubuntu ด้วย ว่าอย่านิ่งนอนใจ
ล่าสุด Debian ได้ออกแพกเกจ openssh-blacklist เพื่อปิดกั้นการเข้าระบบผ่านกุญแจที่หละหลวมทั้งหมดแล้ว เป็นมาตรการอีกขั้นหนึ่ง ที่ distro อื่นสามารถใช้ช่วยแก้ปัญหาได้ แต่สำหรับผู้ใช้ Debian/Ubuntu คุณควรเปลี่ยนกุญแจก่อนที่จะอัปเกรด openssh (คืออัปเกรดแค่ openssl/libssl เพื่อสร้างกุญแจใหม่ก่อน แล้วเปลี่ยนกุญแจให้เรียบร้อย แล้วค่อยอัปเกรด openssh เพราะไม่งั้น กุญแจของคุณจะโดน blacklist ก่อนจะทันได้เปลี่ยน)
สำหรับรายละเอียดของปัญหา Daniel Leidert ซึ่งเป็น DD คนหนึ่ง เขียนอธิบาย ไว้ค่อนข้างดี คือผู้ดูแลแพกเกจ openssl ได้พยายามแก้ปัญหาการใช้ uninitialized memory ใน openssl ตามที่ตรวจพบโดย valgrind โดยไม่รู้ตัวว่า ได้ตัดแหล่งข้อมูลสุ่มสำคัญของ openssl ไป คือในการสุ่มกุญแจ openssl จะใช้ข้อมูลสุ่มจากหลาย ๆ แหล่ง เพื่อเพิ่ม entropy โดยแหล่งหนึ่งที่ใช้ คือบัฟเฟอร์หน่วยความจำที่ไม่มีการกำหนดค่า (uninitialized memory) นี้เอง พอถูกตัดออกไป ก็เหลือข้อมูลสุ่มอื่นอยู่บ้าง แต่อัตราการสุ่มได้ต่ำลงจนอยู่ในวิสัยที่จะเจาะแบบ brute force ได้ (คนที่พบบั๊กนี้คือ Luciano Bello)
อ่านแล้วก็สงสัยเหมือนกัน ว่ามีการใช้วิธีนี้ในโปรแกรมด้วย.. จำได้ว่าตอนสร้างกุญแจ gpg จะต้องเก็บข้อมูลจาก event ต่าง ๆ ด้วย เช่น ให้ขยับเมาส์มั่ว ๆ หรือสลับหน้าต่าง/หน้าจอไปมา ทำไม openssl ไม่ใช้วิธีนั้นบ้าง?
ว่าแต่ว่า คุณได้ตรวจสอบหรือยัง ว่าคุณโดนปัญหานี้ด้วยหรือเปล่า?
7 ความเห็น:
ณ 15 พฤษภาคม 2551 เวลา 15:11 , bact' แถลง…
openssl ถูกใช้โดยหลายโปรแกรม - บางอันไม่ได้มี user interaction ?
ณ 15 พฤษภาคม 2551 เวลา 16:15 , Unknown แถลง…
รอดตัวไป, เราใช้ warty กะ dapper ซึ่งเป็น 0.9.8a
ณ 16 พฤษภาคม 2551 เวลา 07:19 , Thep แถลง…
Update: กลับไปอ่าน อีก blog หนึ่ง ของ Erich Schubert ปรากฏว่าโค้ดส่วนที่ valgrind ฟ้อง uninitialized data มีอยู่สองแห่ง ผมดูจากโค้ดแล้ว เป็นฟังก์ชันที่รับ buffer argument โดยจะใช้ค่าจาก buffer ที่ส่งมานี้เป็นค่าเริ่มต้นในการคำนวณ MD5 hash แต่คงมีการเรียกจากหลายแห่ง แห่งหนึ่งส่ง uninitialized data แต่อีกแห่งหนึ่งส่งข้อมูลจาก /dev/random ซึ่งการลบโค้ดบรรทัดที่มีปัญหา ทำให้ข้อมูลจาก /dev/random นี่แหละที่หายไป คงเหลือแต่ข้อมูลอื่นเล็ก ๆ น้อย ๆ ทำให้อัตราการสุ่มลดฮวบฮาบ
สรุปว่า การใช้ uninitialized buffer ไม่ได้เป็นสาเหตุสำคัญ ซึ่งอันที่จริง ในบางระบบอาจมีการ fill buffer ขณะ allocate ด้วยซ้ำ การใช้ uninitialized buffer จึงไม่น่าจะช่วยในการสุ่มข้อมูลมากถึงขนาดนั้น และไม่ควรพึ่งพามากนัก
คิดตามแล้วก็เห็นด้วยน่ะครับ ว่าการพยายาม clean โค้ดส่วนนี้ เป็นสิ่งที่ถูกต้องอยู่แล้ว เพียงแต่อาจจะต้องหาวิธีอื่น
ณ 16 พฤษภาคม 2551 เวลา 07:35 , Thep แถลง…
bact', หมายถึงตอนเก็บข้อมูลสุ่มเหรอครับ? ถ้าในกรณีนั้นก็ยังเก็บข้อมูลอื่นได้ เช่น network packet, อุณหภูมิ CPU, realtime clock tick ขณะนั้น ฯลฯ
ณ 17 พฤษภาคม 2551 เวลา 23:44 , ไม่ระบุชื่อ แถลง…
ทีม debian ssl maintainer เชื่อถือได้แค่ไหน, ทำไม patch อะไรเสี่ยงๆ
คราวก่อนก็เจอ bug ของ grep, เป็น bug เพราะ patch ของ debian เอง. แบบว่าทำให้ output ของ grep ผิดไปเลยครับ.
$ (echo a; echo aa; echo a) | grep -wnF a
1:a
$ (echo a; sleep 1; echo aa; sleep 1; echo a) | grep -wnF a
1:a
3:a
ดูสิครับ, แค่มี sleep กะไม่มี sleep ให้ผลลัพธ์ต่างกัน.
----
อานนท์
ณ 18 พฤษภาคม 2551 เวลา 09:40 , Thep แถลง…
กรณี grep นั้นผมไม่มีข้อมูล แต่สำหรับกรณี openssl นี้ ผมมองว่าเป็นเรื่องสุดวิสัย ถ้าจะโทษ ก็โทษที่โค้ดของ upstream openssl ที่ฝืนธรรมเนียมการเขียนโปรแกรม
การเขียนโปรแกรมโดยอาศัย uninitialized data ในกรณีนี้ ผลที่ได้คือ entropy ที่เพิ่มขึ้นเล็กน้อย คือจะมีผลในระบบที่ loader/allocator ไม่มีการ initialize memory แต่ในระบบที่ initialize ก็จะขาดข้อมูลสุ่มตรงนี้ไป
แต่ผลเสียกลับใหญ่โต คือทำให้เครื่องมือ debug อย่าง valgrind ฟ้องเรื่องการใช้ uninitialized data ทำให้ใครก็ตามที่อ่านโค้ด มีโอกาสสูงมากที่จะเห็นว่าเป็นบั๊ก แล้วก็แก้บั๊กนั้น เพราะมันเป็นความผิดพื้นฐานของโปรแกรมทั่วไป
และที่สำคัญ โค้ดที่อาศัยพฤติกรรมผิดปกติในการทำงานแบบนี้ ไม่มี comment อธิบายเลยสักนิด
ตามที่ได้ตามอ่านหลักฐานต่าง ๆ ที่พูดถึงกันใน planet debian ก็ปรากฏว่า debian maintainer คนนั้นก็ไม่ได้แพตช์โดยพลการ แต่ได้สอบถามใน mailing list ของ upstream แล้ว และได้คำตอบมาทำนองว่า "ถ้ามันทำให้ดีบั๊กง่ายขึ้นก็โอเค"
สรุปว่า ไม่ว่าจะมองยังไง ก็ยังเห็นว่าโค้ดส่วนนั้นของ upstream ควรได้รับการปรับปรุงแก้ไข ปัญหาของ debian ครั้งนี้ เป็นหลักฐานสนับสนุนที่สำคัญ
แต่ขณะเดียวกัน debian ก็ได้รับบทเรียนครั้งสำคัญ ตอนนี้ก็มีการอภิปรายกัน ถึง วิธีการจัดการ patch ที่รัดกุมขึ้น มีข้อเสนอต่าง ๆ ที่น่าสนใจ เช่น blog นี้ ของ Josselin Mouette และ blog ตอบ ของ Simon Richter
ณ 19 พฤษภาคม 2551 เวลา 00:08 , ไม่ระบุชื่อ แถลง…
bug ของ grep, เป็น bug เพราะ patch ของ debian เอง. <-- ขอยกเลิกคำพูดนี้ก่อนครับ, ผมลืมไปแล้วว่าได้ข้อมูลจากไหน.
----
อานนท์
แสดงความเห็น (มีการกลั่นกรองสำหรับ blog ที่เก่ากว่า 14 วัน)
<< กลับหน้าแรก