NOCTURA JOURNAL / PHP

PHP2Shell: เจาะลึกช่องโหว่ PHP ร้ายแรง CVE-2026-109618 และ CVE-2026-109619 พร้อมวิธีแก้ไข

ทำความเข้าใจ PHP2Shell สองช่องโหว่ร้ายแรงในตัว PHP ที่อาจทำให้ผู้โจมตีรันโค้ดบนเซิร์ฟเวอร์ได้โดยไม่ต้องล็อกอิน พร้อมรายละเอียดผลกระทบ เวอร์ชันที่แก้ไขแล้ว และแนวทางอัปเดตสำหรับเว็บไซต์ WordPress, PHP-FPM และ Docker

เผยแพร่โดย Noctura Digital Studio
THE TAKEAWAY

ช่องโหว่นี้อยู่ใน PHP runtime จึงต้องตรวจและอัปเดต PHP ที่เว็บไซต์ใช้งานจริง การอัปเดต WordPress หรือปลั๊กอินอย่างเดียวไม่เพียงพอ หลังติดตั้งแพตช์ต้อง restart worker หรือสร้าง container ใหม่ และตรวจเลขแพ็กเกจเต็มในกรณีที่ผู้ให้บริการใช้แพตช์ backport

01

PHP2Shell คืออะไร และเหตุใดเจ้าของเว็บไซต์ต้องรีบตรวจสอบ

PHP2Shell เป็นชื่อเรียกกลุ่มช่องโหว่ CVE-2026-109618 และ CVE-2026-109619 ซึ่งเกี่ยวข้องกับการจัดการหน่วยความจำและสถานะภายในของ PHP ทั้งสองมีระดับความรุนแรง Critical คะแนน CVSS v4.0 9.2 และมีแพตช์เผยแพร่เมื่อวันที่ 21 ตุลาคม 2026 หากเข้าเงื่อนไขโจมตี ผู้โจมตีอาจรันโค้ดจากระยะไกลโดยไม่ต้องยืนยันตัวตน หรือเข้าถึงข้อมูลในหน่วยความจำของ PHP worker ผลกระทบที่เป็นไปได้จึงรวมถึงข้อมูลรั่วไหล การแก้ไขไฟล์เว็บไซต์ และการใช้สิทธิ์ของ process เว็บเพื่อดำเนินการต่อ เนื่องจากปัญหาอยู่ใน runtime เว็บไซต์จึงอาจได้รับผลกระทบแม้โค้ดแอปพลิเคชันจะเขียนอย่างปลอดภัย อย่างไรก็ตาม ความสามารถในการโจมตีขึ้นอยู่กับรูปแบบการติดตั้ง การตั้งค่า และเส้นทางการทำงานของแต่ละแอป ไม่ได้หมายความว่าทุกเว็บไซต์ถูกเจาะแล้ว

02

CVE-2026-109618: หน่วยความจำเสียหายระหว่างจัดการ Out of Memory

เมื่อ PHP ไม่สามารถจัดสรรหน่วยความจำเพิ่มได้ ระบบจะเข้าสู่ภาวะ Out of Memory หรือ OOM กลไกเดิมใช้ longjmp() เพื่อหยุดการทำงาน แต่หากหยุดระหว่างสร้างข้อมูลภายใน request ข้อมูลบางส่วนอาจยังไม่สมบูรณ์ ขั้นตอน cleanup อาจนำสถานะที่ไม่สมบูรณ์นั้นไปใช้งาน ทำให้หน่วยความจำเสียหายและอาจนำไปสู่การรันโค้ดได้ ปัญหาจึงไม่ได้จำกัดอยู่ที่การอัปโหลดไฟล์ขนาดใหญ่เท่านั้น แพตช์เปลี่ยนวิธีจัดการ OOM ให้หยุดในจุดที่ปลอดภัย หรือจบ process ทันทีเมื่อถึงเงื่อนไขที่กำหนด เพื่อลดโอกาสที่ cleanup จะใช้สถานะผิดปกติ

03

CVE-2026-109619: ข้อมูลเก่าค้างข้าม Request และปัญหา Use-After-Free

PHP worker สามารถประมวลผลหลาย request ต่อเนื่องกัน ช่องโหว่นี้เกิดเมื่อ worker ยังเก็บตัวอ้างอิงถึงข้อมูลของ request เก่า แม้หน่วยความจำของข้อมูลนั้นถูกคืนแล้ว หาก request ถัดไปบน worker เดิมเข้าถึงสถานะดังกล่าวก่อนระบบรีเซ็ต อาจเกิด Use-After-Free ส่งผลให้ข้อมูลรั่วไหลหรือรันโค้ดได้ โดยต้องมีทั้งการสร้างสถานะค้างและการนำสถานะนั้นกลับมาใช้ การเพิ่มจำนวน worker หรือหมุนเวียน worker อาจเปลี่ยนโอกาสสำเร็จต่อ request แต่ไม่ได้แก้สาเหตุ จึงยังต้องติดตั้งแพตช์ที่รีเซ็ตสถานะอย่างครบถ้วน

04

ระบบที่ได้รับผลกระทบและเวอร์ชัน PHP ที่แก้ไขแล้ว

ทีม PHP ระบุให้ตรวจสอบระบบที่รับ web request รวมถึง Apache mod_php, PHP-FPM, CGI, FrankenPHP และ LiteSpeed โดยมีเงื่อนไขโจมตีแตกต่างกัน การใช้ Nginx คู่กับ PHP-FPM จึงไม่เพียงพอให้สรุปว่าปลอดภัย เวอร์ชัน upstream ที่แก้ไขแล้วขั้นต่ำ ได้แก่ PHP 8.2.35, 8.3.36, 8.4.27 และ 8.5.12 ให้เลือกสายที่แอปรองรับ หรือรุ่นใหม่กว่าที่รวมแพตช์แล้ว สำหรับแพ็กเกจ Linux ต้องตรวจเลขแพ็กเกจเต็ม เพราะผู้ให้บริการอาจ backport แพตช์โดยยังแสดงเลข PHP เดิม ตัวอย่าง Ubuntu 24.04 ระบุแพ็กเกจ 8.3.6-0ubuntu0.24.04.13 ว่าแก้ไขแล้ว ข้อสรุปนี้ใช้กับแพ็กเกจ Ubuntu ดังกล่าว ไม่ใช่ PHP 8.3.6 ทุกแหล่ง

05

วิธีตรวจสอบและอัปเดต PHP บนเซิร์ฟเวอร์

เริ่มจากตรวจ PHP ของ CLI ด้วยคำสั่ง php -v และ php --ini จากนั้นตรวจ PHP ที่เว็บไซต์ใช้งานจริงผ่าน configuration ของเว็บ, FPM pool หรือแผงควบคุม เพราะ CLI และเว็บอาจใช้คนละเวอร์ชัน ก่อนอัปเดต ให้สำรองฐานข้อมูล ไฟล์เว็บ และ configuration พร้อมบันทึก extension ที่ใช้งาน สำหรับ Ubuntu/Debian ที่ติดตั้ง PHP 8.3 FPM ผ่าน APT สามารถตรวจแพ็กเกจด้วย apt-cache policy php8.3-fpm หลัง sudo apt update แล้วอัปเดตด้วย sudo apt install --only-upgrade php8.3-fpm php8.3-cli php8.3-common รวมถึง extension ที่ติดตั้งเพิ่มเติมตามความจำเป็น ตรวจ configuration ด้วย sudo php-fpm8.3 -t แล้ว restart ผ่าน sudo systemctl restart php8.3-fpm ชื่อแพ็กเกจและ service ต้องตรงกับเครื่องจริง หากใช้ aaPanel ให้ตรวจทุกเว็บไซต์และทุก PHP ที่ติดตั้ง การอัปเดตผ่าน APT อาจไม่ครอบคลุม PHP ที่แผงควบคุมติดตั้งแยกไว้

06

วิธีอัปเดต PHP สำหรับ Docker และ WordPress

สำหรับ Docker การอัปเดต PHP บน host ไม่เปลี่ยน runtime ใน container ให้เปลี่ยน base image หรือ image ของผู้ผลิตเป็นรุ่นที่ยืนยันว่ามีแพตช์ หาก service ชื่อ php ใช้ Dockerfile ของตนเอง เช่น FROM php:8.3.36-fpm ให้ rebuild ด้วย docker compose build --pull php แล้วแทนที่ container ด้วย docker compose up -d --no-deps --force-recreate php ถ้าใช้ image สำเร็จรูป ให้เปลี่ยน tag เป็นรุ่นที่แก้แล้ว ใช้ docker compose pull php และสร้าง container ใหม่ ตรวจเวอร์ชันด้วย docker compose exec php php -v โดยเปลี่ยนชื่อ service ให้ตรงระบบจริง สำหรับ WordPress ต้องอัปเดต PHP ของโฮสติ้งด้วย การอัปเดต WordPress core ธีม หรือปลั๊กอินไม่ได้เปลี่ยน PHP runtime หลังอัปเดตควรทดสอบหน้าเว็บ ระบบสมาชิก ฟอร์ม และการอัปโหลดไฟล์

07

มาตรการชั่วคราวระหว่างรอติดตั้งแพตช์

การตั้งค่าชั่วคราวลดได้บางเส้นทางโจมตี แต่ไม่ครอบคลุมช่องโหว่ทั้งหมด การอัปเดตยังเป็นวิธีแก้ไขหลัก แนวทางที่ประกาศระบุ ได้แก่ ปิด session.upload_progress.enabled และสำหรับ PHP 8.5 ให้ปิด fatal_error_backtraces โดยตั้งใน configuration ที่มีผลก่อน parse request และ restart ทุก worker การเปลี่ยนผ่าน ini_set() ภายในแอปอาจช้าเกินไป ควรจำกัดขนาด request ตามความจำเป็น และแก้ fatal error หรือ timeout ที่ผู้โจมตีเข้าถึงได้ การซ่อน error จากหน้าจอไม่ได้แก้สถานะหน่วยความจำ ประกาศยังกล่าวถึง memory_limit=-1 เพื่อลดบางเส้นทาง OOM แต่ไม่ควรปรับโดยไม่มีการควบคุมหน่วยความจำระดับระบบ เพราะเป็นการยกเลิกลิมิตของ PHP และยังไม่แก้ทุกกรณี

08

ตรวจสอบหลังอัปเดต และรับมือเมื่อสงสัยว่าถูกโจมตี

หลังอัปเดต ให้ตรวจว่าแพตช์ครอบคลุมทุกเครื่อง container และ replica รวมถึงยืนยันว่า process เก่าถูก restart หรือแทนที่แล้ว ทดสอบระบบเข้าสู่ระบบ session อัปโหลดไฟล์ ฟอร์ม และงานเบื้องหลัง ใช้ log ประกอบกับการตรวจไฟล์ บัญชีผู้ดูแล และพฤติกรรมเครือข่าย การไม่มี error ใน log ไม่ใช่หลักฐานว่าปลอดภัย ขณะเดียวกัน OOM หรือ worker crash เพียงอย่างเดียวก็ไม่ได้ยืนยันว่าถูกโจมตี หากสงสัยว่าระบบถูกเจาะ ควรแยกเครื่อง เก็บ log และ snapshot เพื่อตรวจสอบ ตรวจหาการฝังตัว และเปลี่ยนรหัสผ่านหรือ secrets ที่อาจรั่วจากสภาพแวดล้อมที่สะอาด การติดตั้งแพตช์ไม่ได้ลบ backdoor ที่อาจถูกวางไว้ก่อนหน้า