ประกาศนี้ออกตามหลัง PHP2Shell มาสองวัน
เมื่อวันที่ 21 ต.ค. PHP เพิ่งออก 8.5.12, 8.4.27, 8.3.36 และ 8.2.35 ที่แก้ช่องโหว่ RCE สองตัวของ PHP2Shell อีกสองวันต่อมา php.net ก็ลงประกาศสั้น ๆ อีกฉบับ ว่าเจอทาง RCE อีกทางที่เกี่ยวกับ session upload progress
ประกาศครั้งนี้เป็นแบบแจ้งเพื่อทราบ ไม่ใช่ security release ฉุกเฉิน ทีม security มองว่าเงื่อนไขที่ต้องเข้าข่ายพบได้ยากในแอปจริง จึงจะแก้ในรอบ release ปกติ แล้วออก advisory ฉบับเต็มของ CVE-2026-115560 พร้อมกันตอนนั้น ตอนนี้จึงยังไม่มีคะแนน CVSS และยังไม่ได้บอกว่าเวอร์ชันไหนบ้างที่ได้รับผลกระทบ
ค่าที่แนะนำให้ปิดเป็นค่าเดียวกับที่อยู่ใน advisory ของ CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp) อยู่แล้ว ถ้าเราตั้งไว้ตอนอ่านโพสต์ PHP2Shell แพตช์ออกแล้ว ก็ใช้ได้กับเรื่องนี้ด้วย ส่วนใครที่ตั้งไว้ชั่วคราวแล้วกำลังจะถอดออกหลังอัปเดต ให้คงค่านี้ไว้ก่อน
ประกาศนี้ไม่ได้มาแทนการอัปเดต เครื่องที่ยังไม่ได้ขึ้นเวอร์ชันชุดวันที่ 21 ยังต้องอัปเดตเหมือนเดิม
serialize handler คือรูปแบบที่ PHP ใช้เขียน $_SESSION ลงที่เก็บ
เวลาแอป PHP เรียก session_start() แล้วใส่ค่าลงใน $_SESSION ตอนจบ request PHP จะแปลง array นั้นเป็นข้อความก่อนเขียนลงไฟล์หรือที่เก็บ session อื่น ค่า session.serialize_handler เลือกรูปแบบของข้อความนี้
phpเป็นค่าเริ่มต้น เป็นรูปแบบเฉพาะของ sessionphp_binaryเป็นอีกรูปแบบภายในของ PHPphp_serializeใช้serialize()ธรรมดากับ array ทั้งก้อน คู่มือ PHP แนะนำให้ใช้ตัวนี้ถ้า$_SESSIONมี key เป็นตัวเลขหรือมีตัวอักษร|กับ!เพราะสองรูปแบบแรกเก็บแบบนั้นไม่ได้
ส่วน session upload progress เป็นฟีเจอร์ที่เปิดอยู่เป็นค่าเริ่มต้น ถ้าฟอร์มอัปโหลดไฟล์ส่งช่องชื่อ PHP_SESSION_UPLOAD_PROGRESS มาด้วย PHP จะเขียนความคืบหน้าของการอัปโหลดลงใน $_SESSION ให้เองระหว่างรับไฟล์ คู่มือบอกว่าขั้นนี้เกิดก่อนสคริปต์ของแอปจะเริ่มรัน และข้อมูลที่เขียนลงไปมีชื่อไฟล์กับชื่อช่องที่ฝั่ง client ส่งมาเอง
พอเอาสองเรื่องนี้มารวมกัน เงื่อนไขทั้งสามข้อก็ชี้ไปที่จังหวะเดียวกัน คือ PHP เขียนข้อมูลลง session ไว้ก่อนด้วยรูปแบบจาก config แล้วแอปมาสลับรูปแบบทีหลังตอนรัน ประกาศยังไม่ได้อธิบายกลไกว่าจากตรงนั้นไปถึงการรันโค้ดได้ยังไง รายละเอียดจะมากับ advisory ฉบับเต็ม
แอป Laravel ไม่เข้าเงื่อนไขข้อที่สอง
Laravel มี session ของตัวเองใน Illuminate\Session\Store เก็บผ่าน driver ที่ตั้งไว้ใน config/session.php เช่น file, database หรือ redis และไม่ได้เรียก session_start() เลย ใน laravel/framework ไม่มีโค้ดตรงไหนเรียกฟังก์ชันนี้ หรือแตะ session.serialize_handler แม้แต่ที่เดียว ค่า session.* ใน php.ini จึงไม่มีผลกับ session ของ Laravel
ที่ต้องดูคือเว็บ PHP อื่นที่รันอยู่บนเครื่องเดียวกันหรือ PHP-FPM pool เดียวกัน เช่นเว็บที่เขียน PHP เองแบบไม่ใช้ framework หรือระบบรุ่นเก่าที่ยังใช้ session ของ PHP อยู่ ไล่เช็คได้สองจุด
- เปิด
phpinfo()ของเว็บนั้นดูค่าsession.serialize_handlerถ้ายังเป็นphpตามค่าเริ่มต้น ก็ไม่เข้าเงื่อนไขข้อแรกแล้ว - ถ้าเป็น
php_binaryหรือphp_serializeลองค้นในโค้ดของเว็บนั้นหาserialize_handlerว่ามีจุดไหนตั้งค่าด้วยini_set()ก่อนเรียกsession_start()บ้าง ถ้าไม่มี php.net บอกว่าเปิด upload progress ไว้ต่อได้
ปิด upload progress ไว้ก่อนได้โดยไม่กระทบแอป Laravel
แอป Laravel ไม่ได้ใช้ฟีเจอร์นี้ แถบ progress ตอนอัปโหลดในแอป Laravel มาจาก JavaScript ฝั่ง browser ไม่ว่าจะเป็น Livewire, Inertia หรือ JavaScript ที่เขียนเอง ปิดไปจึงไม่มีอะไรเปลี่ยน คู่มือของ PHP เองก็แนะนำให้ปิดในแอปที่ไม่ได้ใช้แถบ progress แบบนี้อยู่แล้ว
ตั้งค่าใน php.ini หรือใน pool ของ PHP-FPM ซึ่งเป็นระดับที่ PHP อ่านก่อนรับ request ประกาศเมื่อวันที่ 21 ก็ย้ำไว้ว่าอย่าพึ่ง ini_set() หรือ .user.ini สำหรับค่านี้
php_admin_value[session.upload_progress.enabled] = 0
ตั้งแล้ว restart PHP-FPM ทุกเวอร์ชันที่มีบนเครื่อง worker ที่รันอยู่จะได้อ่านค่าใหม่ ถ้าเว็บอยู่บน shared hosting และแผงควบคุมไม่มีช่องให้ตั้งค่านี้ ก็ส่ง ticket ถามผู้ให้บริการได้เลย
รายละเอียดของประกาศ พร้อมลิงก์ไป advisory ก่อนหน้า อ่านต่อได้ที่บทความต้นฉบับบน PHP News ครับ






