PostgreSQL ปล่อย patch สำหรับ RCE แบบมีผู้ใช้อยู่แล้ว

ช่องโหว่ประเภท Type Confusion ใน PostgreSQL เปิดช่องให้ผู้ใช้ฐานข้อมูลที่สามารถสร้างออบเจ็กต์ (หรือพูดง่าย ผู้ที่มี user ในระบบไม่ว่าระดับใด) รันโค้ดบนเซิร์ฟเวอร์ได้ โดยการอัปเดตที่ปล่อยออกมาเมื่อวานนี้ได้แก้ไขปัญหานี้ พร้อมกับช่องโหว่ด้านความปลอดภัยอื่นๆ อีก 51 รายการ นอกจากนี้ การป้องกันช่องโหว่นี้อย่างสมบูรณ์ยังต้องมีการคอมไพล์ (Rebuild) ส่วนขยาย (Extensions) ด้วยภาษา C ที่ติดตั้งอยู่บนเซิร์ฟเวอร์ใหม่ด้วย

ช่องโหว่นี้ถูกระบุรหัสไว้ว่า CVE-2026-6460 และมีคะแนนความรุนแรง CVSS อยู่ที่ 8.8 โค้ดใดๆ ที่รันผ่านช่องโหว่นี้จะมีสิทธิ์เทียบเท่ากับผู้ใช้ระบบปฏิบัติการ (OS User) ที่รัน PostgreSQL อยู่ เวอร์ชันทั้งหมดก่อนหน้า 18.7, 17.12, 16.16, 15.20 และ 14.25 ล้วนมีช่องโหว่ดังกล่าวอยู่ หรือพูดง่ายๆ มันมีมานานกว่า 22 ปีแล้ว

PostgreSQL Global Development Group ซึ่งคือผู้เผยแพร่ซอฟต์แวร์ฐานข้อมูลดังกล่าว ยังไม่รายงานการโจมตีใดๆ ที่ใช้ช่องโหว่นี้ ขณะที่การประเมินของ CISA ในบันทึก CVE ก็ระบุว่ายังไม่มีการโจมตีเกิดขึ้น

ช่องโหว่นี้เกี่ยวข้องกับชนิดข้อมูลแบบคอมโพสิต (Composite Types) ซึ่งเป็นชนิดข้อมูลที่สร้างขึ้นจากฟิลด์ที่มีชื่อและมีชนิดข้อมูลเป็นของตัวเอง โดยชนิดข้อมูลของฟิลด์สามารถถูกเปลี่ยนแปลงได้ ในขณะที่ค่าเก่าของชนิดข้อมูลนั้นยังคงถูกเก็บไว้ในส่วนอื่นๆ ของเซิร์ฟเวอร์

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

Mehmet Ince นักวิจัยด้านความปลอดภัย ได้อธิบายตัวอย่างโค้ดโจมตี (Exploit) ที่ใช้งานได้จริงสำหรับช่องโหว่นี้ ซึ่งสาธิตบน PostgreSQL 18.6 ผ่านบทความทางเทคนิคที่เผยแพร่ในสัปดาห์นี้

วิธีการของเขาคือการเตรียมคิวรี (Query) ที่เก็บค่าหนึ่งไว้ เปลี่ยนชนิดข้อมูลของฟิลด์หนึ่งในค่านั้น แล้วจึงรันคิวรีดังกล่าว บทความดังกล่าวได้รวมคำสั่ง SQL ที่ทำให้เซิร์ฟเวอร์ที่ยังไม่ได้แพทช์เกิดการแครช (Crash) ด้วยวิธีนี้ และขั้นตอนที่สองที่ทำให้เกิด buffer overflow ของแอดเดรสหน่วยความจำ (Memory Addresses) แต่ไม่ได้รวมคำสั่ง SQL สำหรับขั้นตอนสุดท้ายที่จะทำให้เซิร์ฟเวอร์สั่งรันคำสั่งใดๆ

เขาเขียนระบุว่าเขาสามารถ “กระตุ้นให้เกิดการแครชนี้ได้ด้วยสิทธิ์การเข้าสู่ระบบแบบต่ำที่สุด (Lowest-privileged login role)” ส่วนคำประกาศด้านความปลอดภัยของโครงการอธิบายลักษณะของผู้โจมตีว่าเป็นเพียงผู้ที่สามารถสร้างออบเจ็กต์ได้ โดยไม่ได้ระบุว่าต้องใช้สิทธิ์ระดับใดบ้าง

Red Hat ซึ่งจัดแพ็กเกจ PostgreSQL ระบุในการประเมิน CVE ว่าผู้โจมตีจำเป็นต้องมีการเข้าสู่ระบบฐานข้อมูลที่มีความสามารถในการสร้างหรือแก้ไขออบเจ็กต์ได้ ซึ่งไม่มีแหล่งข้อมูลใดระบุว่าบัญชีที่มีเพียงสิทธิ์ค่าเริ่มต้น (Default Privileges) จะสามารถก้าวข้ามจากการทำให้แครชไปสู่การรันโค้ดได้หรือไม่

Ince ได้สืบย้อนรากเหง้าของช่องโหว่นี้ไปถึงวันที่ 5 พฤษภาคม 2004 ซึ่งเป็นวันที่ PostgreSQL เริ่มมีความสามารถในการเปลี่ยนชนิดข้อมูลของคอลัมน์ได้ ส่วนเทคนิคการรันโค้ดของเขานั้นพึ่งพาการเปลี่ยนแปลงที่เกิดขึ้นภายหลังในวันที่ 14 พฤษภาคม 2015

นอกจากนี้ เขายังได้ปรับแต่งช่องโหว่ดังกล่าวสำหรับบริการ PostgreSQL บนคลาวด์แบบจัดการ (Managed PostgreSQL Services) และได้แบ่งปันตัวอย่างแนวคิด (Proofs of Concept) ให้กับทีมรักษาความปลอดภัยของบริการเหล่านั้นเป็นการส่วนตัวในเดือนสิงหาคม ผู้ให้บริการที่เขาทำงานร่วมด้วยได้แก่ AWS (Aurora และ RDS), Microsoft (Azure PostgreSQL), Google (AlloyDB), Supabase, Databricks และ Ubicloud แต่บทความไม่ได้ระบุสถานะการแพทช์ปัจจุบันของแต่ละบริการ

ทางโครงการได้ให้เครดิตผู้แจ้งเบาะแสมากกว่าสิบราย สำหรับ CVE-2026-6460 ซึ่งรวมถึงตัวนักวิจัยรายนี้ด้วย และยังให้เครดิตเขาในช่องโหว่อีก 5 รายการในรุ่นเดียวกัน

โครงการจัดอันดับให้ 32 จาก 52 ช่องโหว่มีความรุนแรงอยู่ที่ 8.8 ซึ่งเป็นคะแนนสูงสุดในรุ่นนี้ เมื่ออิงตามคะแนนในดัชนีช่องโหว่ มีเพียงช่องโหว่เดียวเท่านั้นบนเซิร์ฟเวอร์ที่ไม่จำเป็นต้องใช้การเข้าสู่ระบบหรือการกระทำใดๆ ของผู้ใช้ ช่องโหว่นั้นคือ CVE-2026-116322 ซึ่งช่วยให้ไคลเอนต์ที่ไม่ได้ยืนยันตัวตนสามารถกระตุ้นการรีสตาร์ทเซิร์ฟเวอร์ PostgreSQL 18 ได้

การแก้ไขอื่นๆ อีกหลายรายการอยู่ในเครื่องมือฝั่งไคลเอนต์ (Client Tools) โดยไฟล์อาร์ไพร์ที่ถูกสร้างขึ้นมาเป็นพิเศษสามารถทำให้ `pg_restore` รันโค้ดในฐานะผู้ใช้ที่กำลังรันมันอยู่ได้ และเซิร์ฟเวอร์ต้นทางที่ถูกเจาะระบบ (Compromised Source Server) ก็สามารถทำให้ `psql` รันโค้ดผ่านสคริปต์กู้คืนในผลลัพธ์ไฟล์ tar ของ `pg_dump` ได้

สิ่งที่ผู้ดูแลระบบควรทำ

  1. อัปเดตเซิร์ฟเวอร์เป็นเวอร์ชัน 18.7, 17.12, 16.16, 15.20 หรือ 14.25 ให้ตรงกับเวอร์ชันหลัก (Major Version) ของคุณ
  2. คอมไพล์ใหม่ (Rebuild) หรืออัปเดตส่วนขยาย (Extensions) ภาษา C ทุกตัวในเวลาเดียวกันกับการอัปเดตเซิร์ฟเวอร์ ส่วนขยายที่คอมไพล์จากรุ่นเก่ายังคงโหลดได้ แต่อาจ “ไม่ได้รับการปกป้องจากช่องโหว่ที่ได้รับการแก้ไขในรุ่นนี้” ตามประกาศจากผู้ดูแลแพ็กเกจ RPM ของโครงการ ส่วนขยายบางตัวอาจต้องมีการเปลี่ยนแปลงซอร์สโค้ดด้วย
  3. ส่วนขยายที่คอมไพล์ใหม่สำหรับรุ่นใหม่อาจไม่สามารถโหลดบนเซิร์ฟเวอร์รุ่นเก่าได้ โดยแพ็กเกจส่วนขยายในคลัง RPM ของโครงการตอนนี้จำเป็นต้องใช้รุ่นย่อย (Minor Release) ใหม่
  4. หาก PostgreSQL รันอยู่นอกเหนือจากเซอร์วิสยูนิต (Service Unit) ของแพ็กเกจเอง เช่น รันภายใต้ Patroni ให้รีสตาร์ททันทีหลังจากอัปเดต ตามที่ผู้ดูแลแพ็กเกจ RPM ระบุไว้ในบล็อกโพสต์การจัดทำแพ็กเกจ
  5. อัปเดตเครื่องมือฝั่งไคลเอนต์ เช่น `pg_dump`, `pg_restore`, `reindexdb` และ `vacuumdb` บนทุกเครื่องที่รันเครื่องมือเหล่านี้
  6. อย่าใช้การตั้งค่า `composite_type_mismatch` แบบใหม่เพื่อปิดการใช้งานการตรวจสอบ ทางโครงการระบุว่าการทำเช่นนั้นมีความเสี่ยงด้านความปลอดภัย
  7. คำประกาศและบันทึกประจำรุ่นของโครงการไม่มีวิธีแก้ปัญหาชั่วคราว (Workaround) สำหรับเซิร์ฟเวอร์ที่ไม่สามารถอัปเดตได้ในขณะนี้
  8. PostgreSQL 14 ได้สิ้นสุดอายุการใช้งาน (End-of-life) แล้ว และ 14.25 คือรุ่นสุดท้ายของมัน ส่วนเวอร์ชันหลักที่เก่ากว่าก็ได้รับผลกระทบเช่นกันแต่จะไม่ได้รับการอัปเดตใดๆ
  9. หลังจากอัปเดตแล้ว ให้ทำตามขั้นตอนการสร้างดัชนีใหม่ (Reindexing) ในประกาศการปล่อยรุ่น หากคุณใช้การสำรองข้อมูลแบบเพิ่ม (Incremental Backups) ให้ทำการสำรองข้อมูลแบบเต็ม (Full Backup) ครั้งใหม่ และใช้เป็นฐานสำหรับการสำรองข้อมูลแบบเพิ่มในครั้งต่อๆ ไป

 

By admin