- MongoBleed (CVE-2025-14847) เป็นช่องโหว่การรั่วไหลของหน่วยความจำร้ายแรงที่มีอยู่ใน MongoDB ทุกเวอร์ชัน ตั้งแต่ปี 2017 ทำให้ผู้โจมตีสามารถอ่าน ข้อมูลใด ๆ ใน heap memory ของฐานข้อมูล ได้
- ช่องโหว่นี้เกิดจาก บั๊กในเส้นทางการบีบอัด zlib และสามารถถูกใช้โจมตีได้เพียงแค่เชื่อมต่อกับฐานข้อมูล โดยไม่ต้องยืนยันตัวตน
- ผู้โจมตีสามารถส่ง คำขอแบบบีบอัดที่ถูกดัดแปลง เพื่อหลอกให้เซิร์ฟเวอร์จัดสรรบัฟเฟอร์ผิดขนาด และเปิดเผย หน่วยความจำจากงานก่อนหน้า (เช่น รหัสผ่าน, API key) ที่อยู่ภายในได้
- MongoDB ปล่อยแพตช์เมื่อวันที่ 19 ธันวาคม 2025 แต่ เวอร์ชัน EOL (3.6, 4.0, 4.2) ไม่ได้รับการแก้ไข
- ช่องโหว่นี้มีอยู่มานาน 8 ปีและส่งผลต่อ อินสแตนซ์ MongoDB ที่เปิดเผยบนอินเทอร์เน็ตมากกว่า 210,000 ตัว จึงจำเป็นต้อง อัปเดตแพตช์ทันทีหรือปิดการบีบอัด ทั้งในสภาพแวดล้อมคลาวด์และออนพรีเมส
ภาพรวมของ MongoBleed
- MongoBleed (CVE-2025-14847) เป็นช่องโหว่ที่พบใน เส้นทางการบีบอัดข้อความ zlib 1 ของ MongoDB และส่งผลกระทบต่อทุกเวอร์ชันตั้งแต่ปี 2017
- ผู้โจมตีเพียงแค่เชื่อมต่อกับฐานข้อมูลโดยไม่ต้องยืนยันตัวตน ก็สามารถอ่าน ข้อมูลใด ๆ ใน heap memory ได้
- เวอร์ชันที่ หมดระยะซัพพอร์ต (EOL) เช่น MongoDB 3.6, 4.0, 4.2 จะไม่ได้รับการแก้ไข
- บั๊กนี้ถูกนำเข้ามาจาก PR เมื่อเดือนพฤษภาคม 2017 และถูกเปิดเผยอย่างเป็นทางการในวันที่ 19 ธันวาคม 2025
- MongoDB ระบุว่าได้ใช้แพตช์กับทุกอินสแตนซ์แล้ว รวมถึง บริการคลาวด์ Atlas
โครงสร้างการสื่อสารของ MongoDB
- MongoDB ใช้ โปรโตคอล TCP ของตนเองแทน HTTP และส่งข้อความในรูปแบบ BSON (Binary JSON)
- คำขอทั้งหมดประกอบด้วยคำสั่ง OP_MSG และเมื่อมีการบีบอัดจะถูกห่อด้วยข้อความ OP_COMPRESSED
- ภายในข้อความมีฟิลด์อย่าง
uncompressedSize, originalOpcode, compressorId
uncompressedSize หมายถึงขนาดที่คาดไว้หลังการคลายการบีบอัด
ขั้นตอน exploit ที่ 1 — การจัดสรรบัฟเฟอร์ผิดพลาด
- ผู้โจมตีตั้งค่า
uncompressedSize ให้เป็น ค่าที่ใหญ่เกินจริง เพื่อให้เซิร์ฟเวอร์จัดสรรบัฟเฟอร์ขนาดใหญ่
- ตัวอย่าง: ประกาศข้อความจริงขนาด 1KB ให้เป็น 1MB
- เซิร์ฟเวอร์ MongoDB หลังคลายการบีบอัดแล้วจะ ไม่ตรวจสอบขนาดจริง แต่เชื่อค่าที่ผู้ใช้ระบุ
- ส่งผลให้หน่วยความจำคงอยู่ในรูปแบบ
[ข้อมูลจริง | heap garbage ที่ไม่ได้อ้างอิง]
- MongoDB ที่พัฒนาด้วย C++ ไม่มีการ initialize หน่วยความจำในส่วนนี้ จึงอาจมี ข้อมูลอ่อนไหวจากงานก่อนหน้า อยู่ภายใน
- เช่น รหัสผ่าน, session token, API key, ข้อมูลลูกค้า, การตั้งค่าระบบ
ขั้นตอน exploit ที่ 2 — การรั่วไหลของข้อมูล
- ผู้โจมตีส่ง อินพุต BSON ที่ไม่ถูกต้อง เพื่อชักนำให้เซิร์ฟเวอร์ parse ข้อมูลขยะในหน่วยความจำเป็นสตริง
- ฟิลด์แรกของ BSON เป็นสตริง และเป็นไปตามกฎของ C ว่าด้วย สตริงแบบ null-terminated
- หากผู้โจมตีส่ง สตริงที่ไม่มีอักขระจบ null เซิร์ฟเวอร์จะอ่านข้อมูลอื่นในหน่วยความจำต่อไปด้วย
- ตัวอย่าง:
[ { "a | password: 123\0 | apiKey: jA2sa | ip: 219.117.127.202 ]
- จากนั้นเซิร์ฟเวอร์จะมองว่านี่เป็นฟิลด์ BSON ที่ไม่ถูกต้อง และตอบกลับพร้อมข้อความผิดพลาดที่มีเนื้อหาดังกล่าว
"errmsg": "invalid BSON field name 'a | password: 123'"
- เมื่อทำซ้ำกระบวนการนี้ ผู้โจมตีสามารถ สแกน heap memory ทั้งหมด และรวบรวมข้อมูลอ่อนไหวได้
ผลกระทบและความเสี่ยง
- ช่องโหว่นี้เกิดขึ้นในขั้นตอน ก่อนการยืนยันตัวตน (pre-auth) ทำให้ผู้โจมตีเข้าถึงข้อมูลได้โดยไม่ต้องล็อกอิน
- อินสแตนซ์ MongoDB ที่เปิดเผยบนอินเทอร์เน็ต จึงตกอยู่ในความเสี่ยงทันที
- จากการค้นหาผ่าน Shodan พบอินสแตนซ์ MongoDB ที่เปิดเผยมากกว่า 213,000 ตัว
- ช่องโหว่นี้มีอยู่ตั้งแต่ ปี 2017 ถึง 2025 รวมราว 8 ปี และด้วยโครงสร้างที่เรียบง่ายจึงมีโอกาสถูกใช้โจมตีจริงสูง
- MongoDB ระบุว่า “ยังไม่มีหลักฐานการถูกใช้โจมตีจนถึงตอนนี้” แต่ ไม่ได้เผยคำขอโทษอย่างเป็นทางการหรือไทม์ไลน์โดยละเอียด
วิธีบรรเทา
- อัปเดตเป็น เวอร์ชันที่มีแพตช์ล่าสุด (8.0.17 ขึ้นไป)
- ในระยะสั้นสามารถบรรเทาได้ด้วยการ ปิดการบีบอัดเครือข่าย zlib
- ผู้ใช้ MongoDB Atlas ได้รับแพตช์เรียบร้อยแล้ว
ข้อมูลเพิ่มเติมและประเด็นที่เกี่ยวข้อง
- หัวหน้าทีมความปลอดภัยของ Elastic ตั้งชื่อช่องโหว่นี้ว่า ‘MongoBleed’ และเผยแพร่ PoC (สคริปต์ Python)
- MongoDB และ Elastic เป็นคู่แข่งกันในด้าน ฟังก์ชันการค้นหาและการวิเคราะห์
- แหล่งข้อมูลที่เกี่ยวข้อง:
สรุป
- MongoBleed คือ ช่องโหว่การรั่วไหลของหน่วยความจำ ที่เกิดจาก บั๊กในการจัดการการบีบอัด zlib
- ผู้โจมตีสามารถใช้ คำขอแบบบีบอัดที่ถูกดัดแปลง เพื่อดึง ข้อมูลหน่วยความจำก่อนหน้า (เช่น รหัสผ่าน, API key) ออกมาได้
- MongoDB ทุกเวอร์ชันในช่วงปี 2017–2025 ได้รับผลกระทบ และจำเป็นต้อง อัปเดตแพตช์หรือปิดการบีบอัด
- อินสแตนซ์ที่เปิดเผยบนอินเทอร์เน็ตมากกว่า 210,000 ตัว อาจตกเป็นเป้าหมาย
- แม้ MongoDB จะปล่อยแพตช์แล้ว แต่ก็มีข้อวิจารณ์เรื่อง ไม่รองรับเวอร์ชัน EOL และการเปิดเผยการตอบสนองล่าช้า
1 ความคิดเห็น
ความเห็นจาก Hacker News
แบบนี้จะทำให้ไม่มีข้อมูลที่มีความหมายหลงเหลืออยู่ในหน่วยความจำที่ยังไม่ได้ initialize
ตอนแรกคิดว่าน่าจะมีผลด้านประสิทธิภาพ แต่ในความเป็นจริงคือ ไม่มีผลที่วัดได้เลย
ผมคิดว่าทุกคนที่ใช้ภาษาซึ่งไม่ปลอดภัยด้านหน่วยความจำควรทำแบบนี้ และบั๊กของ Mongo ครั้งนี้ก็น่าจะบรรเทาได้ด้วยวิธีนี้
สิ่งนี้ช่วยให้การบีบอัดหน่วยความจำมีประสิทธิภาพขึ้น และโดยเฉลี่ยกลับทำให้ประสิทธิภาพดีขึ้นด้วยซ้ำ
MALLOC_CONF=opt.junk=freemalloc ก็จะทำงานแบบเดียวกันกล่าวคือมี implementation จำนวนมากที่มีฟีเจอร์นี้ให้ใช้งานเป็นตัวเลือกอยู่แล้ว
ถ้าต้องการประสิทธิภาพมากกว่านี้ก็เขียน custom allocator ให้เหมาะกับงานเฉพาะไปเลย
และยังสามารถทำ optimization อย่างอื่นที่ system allocator ทำไม่ได้อีกด้วย
0xdbและหน่วยความจำที่ free แล้วด้วย0xdfทำให้จับบั๊กแบบ use-before-initialization หรือ use-after-free ได้อย่างรวดเร็ว
และนี่เป็นค่าตั้งต้นอยู่แล้ว
init_on_free=1ของเคอร์เนลหรือเปล่าMongo พัฒนาใน private repository ภายในก่อน แล้วค่อยย้าย commit ไปยัง repository สาธารณะผ่าน Copybara
ความสับสนเรื่องวันที่เกิดขึ้นจากกระบวนการนี้เอง
กำลังจะอัปเดตบทความเพื่ออธิบายเรื่องนี้กับความต่างของวันที่
Atlas cluster ของเราอัปเกรดเสร็จไปแล้วหลายวันก่อนมีการประกาศ CVE
ทุกวันนี้ allocator ส่วนใหญ่ควรทำแบบนี้เป็นค่าเริ่มต้น
Chris เคยปรับปรุงจุดนี้ใน Blink และผลลัพธ์ก็ขยายไปทั่วทั้ง Chromium
เอกสารที่เกี่ยวข้องก็น่าสนใจเช่นกัน
โพสต์บนบล็อก Chromium
เอกสาร PartitionAlloc
ฝั่ง SQL พบไม่บ่อยแต่ก็มีบ้างเป็นครั้งคราว
ปรัชญาคือไม่ต้องใส่ใจทั้ง schema, durability, การอ่าน/เขียน, การเชื่อมต่อ หรืออะไรเลย
เพราะงั้นจะไม่ใส่ใจเรื่องความปลอดภัยด้วยก็ไม่น่าแปลก
ทัศนคติแบบนี้จะนำไปสู่แนวคิดว่า “ขอให้สะดวกตอนนี้ก่อน” และสุดท้ายก็โยงไปถึงปัญหาความปลอดภัยอย่าง DB instance ที่เปิดสาธารณะ
ในความเป็นจริงการใช้ SQL กับ NoSQL ร่วมกัน เป็นเรื่องปกติ
NoSQL เด่นเรื่องความพร้อมใช้งานสูงสำหรับข้อมูลขนาดใหญ่ ส่วน SQL เหมาะกับการเก็บข้อมูลเชิงสัมพันธ์
เช่น iMessage หรือระบบ matchmaking ของ EA ก็ใช้ NoSQL
สุดท้ายแล้วทั้งคู่จำเป็น ไม่ใช่คู่แข่งกันแต่เป็น ความสัมพันธ์แบบเสริมกัน
เช่น PostgreSQL สามารถมีสิทธิ์ระดับทั้งระบบได้แม้เป็นการตั้งค่าพื้นฐาน
เพราะแบบนี้คนส่วนใหญ่จึงรู้ดีถึงความเสี่ยงของการเปิด SQL server สาธารณะ
ส่วนตัวผมไม่อยากใช้ แต่ก็มีกรณีที่ DynamoDB หรือ MongoDB เหมาะสมในเชิงเทคนิคจริง ๆ
วิดีโอที่เกี่ยวข้อง
แต่ buffer overflow ก็ยังคงมีอยู่มาตั้งแต่ปี 2003
ปัญหาแบบนี้จะเกิดซ้ำไปเรื่อย ๆ ตราบใดที่ไม่ได้ป้องกันในระดับภาษา
ขอส่งกำลังใจให้ทีมพัฒนา Mongo
ผมว่าหันไปใช้ ToroDB หรือ JSONB ของ PostgreSQL จะดีกว่า