การ์ดหลัก PHP2Shell: จากคำขอที่ล้มเหลวสู่การรันโค้ดจากระยะไกล CVE-2026-109618 และ CVE-2026-109619
Engineering & Research

OrcaCyber Research - PHP2Shell: คำขอที่ล้มเหลวกลายเป็นการเรียกใช้โค้ดจากระยะไกลได้อย่างไร

ผู้เขียน

Rowan Sterling

วันที่เผยแพร่

โมเดลล่าสุด · 20ดูโมเดลทั้งหมด →
เบนช์มาร์ก: Artificial Analysis · อัปเดตทุกวัน
กลับไปยังโพสต์ทั้งหมด

การพิสูจน์แนวคิดในการตรวจสอบนี้ถูกสร้างขึ้นด้วยOrcaCyber ZeroและOrcaCyber Ultra ซึ่งเป็นโมเดล ชุดงานวิจัยนี้บันทึกการวิเคราะห์ระดับซอร์สโค้ด การจำลองซ้ำแบบควบคุมโดยใช้ exploit สาธารณะที่ดัดแปลงแล้ว อาร์ติแฟกต์การเปิดเผยข้อมูลหน่วยความจำ การหยุดทำงานของโปรเซส และหลักฐานการเรียกใช้คำสั่ง ไฟล์ที่จัดส่งมาไม่ได้บันทึกโดยอิสระว่าขั้นตอนใดดำเนินการโดยโมเดลใด การระบุที่มาของโมเดลจัดทำโดยทีมวิจัย

สภาวะหน่วยความจำหมดแบบร้ายแรง (fatal out-of-memory) ควรยุติคำขออย่างปลอดภัย ในกรณีนี้ มันอาจขัดจังหวะ PHP ขณะที่สถานะเนทีฟถูกกำหนดค่าเริ่มต้นไว้เพียงบางส่วน ทำให้เหลือการอ้างอิงที่คงอยู่ต่อไปยังคำขอถัดไป ผลลัพธ์คือการละเมิดอายุการใช้งานของหน่วยความจำข้ามคำขอ ซึ่งส่งผลกระทบตั้งแต่การเปิดเผยข้อมูลไปจนถึงการเรียกใช้โค้ดจากระยะไกลในสภาพแวดล้อมที่ทำการทดสอบ

หลักฐานสำคัญโดยสรุป

• เป้าหมาย — PHP 8.4.26, Apache/mod_php, เวิร์กเกอร์เดี่ยว, แล็บ Docker แบบแยกเดี่ยว

• บันทึกการแครช — มี SIGABRT หนึ่งครั้งและ SIGSEGV สามครั้งจากการออกของ worker ในข้อความที่ให้มา

• การตอบสนอง HTTP — 819,200 ไบต์ในค่า PHPSESSID ที่ถอดรหัส URL แล้ว

• หลักฐานการดำเนินการ — code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>.

• รีเกรสชัน — รายงานอธิบายถึงความพยายามที่ไม่สำเร็จสี่ครั้งบน PHP 8.4.27 ที่แพตช์แล้ว; ไม่ได้รวมผลการรันดิบไว้ด้วย

ที่มา: ไฟล์ REPORT.md, crash_evidence.log, leak_attempt.resp และ rce_proof_8426.txt ที่อัปโหลด เอกสารหลักฐานที่อธิบายไว้ด้านล่างเป็นการจำลองอาร์ติแฟกต์เหล่านั้นในรูปแบบแผงหลักฐานที่จัดเรียงพิมพ์ ไม่ใช่ภาพถ่ายหรือภาพหน้าจอเทอร์มินัลจากต้นฉบับ

1. ช่องโหว่: ความล้มเหลวในการเป็นเจ้าของขอบเขตคำขอ

ปัญหาที่เกี่ยวข้องสองประการนี้เกี่ยวกับการเริ่มต้นคำขอที่ถูกขัดจังหวะและพอยน์เตอร์แบบ runtime-global ที่ล้าสมัย ในสถาปัตยกรรม PHP ที่เกี่ยวข้อง การจัดการ multipart/form-data และ callback ความคืบหน้าการอัปโหลดของเซสชันอาจทำงานก่อนโค้ดแอปพลิเคชันของผู้ใช้ตามปกติ การเปลี่ยนผ่านโฟลว์การควบคุมแบบผิดปกติ รวมถึง code>zend_bailout()/code> อาจข้ามการล้างข้อมูลที่คาดไว้ และทำให้สถานะยังชี้ไปยังหน่วยความจำที่ถูกปล่อยหรือนำกลับมาใช้ใหม่ในภายหลัง

อินวาเรียนต์ด้านความปลอดภัย: การอ้างอิงระดับ global ของ worker ที่ถูกเปิดเผยต่อคำขอ B ต้องไม่อ้างอิงถึงหน่วยความจำที่ความเป็นเจ้าของและอายุการใช้งานสิ้นสุดลงพร้อมกับคำขอ A ความล้มเหลวที่รายงานมาละเมิดอินวาเรียนต์นี้

จุดปลายทางที่สาธิตเป็นหน้า PHP แบบเรียบง่ายที่เพียงคืนค่า OK; คำอธิบายการโจมตีไม่ได้ขึ้นอยู่กับจุดปลายทางประเภท SQL injection ระดับแอปพลิเคชัน การรวมไฟล์ หรือการดีซีเรียลไลเซชัน

2. ลำดับขั้นทางเทคนิค

• A1 — การขัดจังหวะ การจัดการมัลติพาร์ตและความคืบหน้าการอัปโหลดทำให้เกิด OOM ระหว่างการล้างข้อมูล ทำให้สถานะเซสชันค้างอยู่

• B1 — การรั่วไหล คำขอที่ตามมาทำให้การซีเรียลไลซ์คุกกี้เซสชันอ่านเกินกว่า ID เซสชันที่ถูกต้อง

• การกู้คืนที่อยู่. ค่าพอยน์เตอร์ที่รั่วไหลถูกใช้เพื่ออนุมานเลย์เอาต์ของไลบรารีและฮีปที่เกี่ยวข้องในบิลด์นั้น

• A2/B2 — ข้อมูลเสียหาย ลำดับคำขอสองรายการอีกลำดับหนึ่งจะจัดรูปแบบและเปลี่ยนเส้นทางข้อมูลที่ล้าสมัยซึ่งใช้เมื่อปิดระบบ

• ผลลัพธ์ เอ็กซ์พลอยต์สาธารณะที่ถูกดัดแปลงรายงานการรันคำสั่งในฐานะ www-data

Five-step diagram of the PHP2Shell chain from OOM interruption to command execution as www-data, reconstructed from the research bundle

หลักฐานที่นำมาแสดง: สิ่งที่ไฟล์ที่ให้มาจริง ๆ แสดงให้เห็น

หลักฐานหมายเลข A — การสิ้นสุดการทำงานของเวิร์กเกอร์จากบันทึก Apache

• code>[core:notice] [pid 1:tid 1] AH00051: กระบวนการลูก pid 54 ออกด้วยสัญญาณ Abort (6), อาจมี coredump ใน /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: โปรเซสลูก pid 55 ออกด้วยสัญญาณ Segmentation fault (11) อาจมี coredump อยู่ใน /etc/apache2/code>

• [core:notice] [pid 1:tid 1] AH00051: โพรเซสลูก pid 58 ออกด้วยสัญญาณ Segmentation fault (11), อาจมี coredump ใน /etc/apache2/code>

• code>[core:notice] [pid 1:tid 1] AH00051: child pid 61 ออกด้วยสัญญาณ Segmentation fault (11) อาจมี coredump ใน /etc/apache2/code>

ข้อความตัดตอนที่จัดเรียงแล้วจาก crash_evidence.log (23 ตุลาคม 2026) การที่เวิร์กเกอร์หลายตัวสิ้นสุดการทำงานบ่งชี้ถึงความล้มเหลวด้านความปลอดภัยของหน่วยความจำ; การแครชเพียงอย่างเดียวไม่เพียงพอที่จะยืนยันว่าเกิด RCE

• code>HTTP/1.1 200 OK/code>, โดยละเว้นข้อมูลไบนารี

• code>Server: Apache/2.4.69 (Debian)/code>

• code>X-Powered-By: PHP/8.4.26/code>

• code>Set-Cookie: PHPSESSID=[ข้อมูลไบนารีที่ละไว้]/code>

• ความยาวคุกกี้ที่เข้ารหัสแล้ว: 2,330,754 ไบต์

• ค่าที่ถอดรหัส URL แล้ว: 819,200 ไบต์

การวัดที่คำนวณโดยตรงจาก leak_attempt.resp ค่าไบนารีถูกละเว้นโดยเจตนาเพื่อหลีกเลี่ยงการทำซ้ำเนื้อหาของโปรเซสที่รั่วไหล

เอกสารแนบ C — หลักฐานการดำเนินการ

code>uid=33(www-data) gid=33(www-data) groups=33(www-data)/code>

เนื้อหาทั้งหมดของ rce_proof_8426.txt ตามที่จัดส่งมา สนับสนุนผลลัพธ์การดำเนินการที่รายงานไว้ แต่ไม่ใช่บันทึกคำสั่ง/เซสชันฉบับเต็ม

Evidence summary card: four worker exits, an 819,200-byte URL-decoded session cookie, and uid=33 execution context

เอกสารแนบ D — การแก้ไขวงจรชีวิตเซสชัน

• code>static inline void php_rinit_session_globals(void)/code>

• code>@@ -121,6 +120,7 @@ static inline void php_rinit_session_globals(void)/code>

• code>* เข้ารหัสเซสชันใหม่ระหว่างการเริ่มต้นคำขอ ก่อน RINIT เมื่อไม่มีผู้ใช้/code>

• code>/* ทำงานก่อน RINIT: ไม่สามารถเรียกใช้โค้ดของผู้ใช้ได้ ดู php_session_unserialize_init() *//code>

• code>/* โค้ดนี้ทำงานก่อน RINIT ดังนั้นเราจึงต้องเคลียร์ค่าเหล่านี้ตั้งแต่เนิ่นๆ *//code>

• code>php_rinit_session_globals();/code>

บรรทัดซอร์สไดฟ์ที่เลือกมาจาก session.c.diff การเปลี่ยนแปลงนี้รีเซ็ตสถานะโกลบอลระดับเซสชันอย่างชัดเจนก่อนกว่า RINIT ตามปกติ

3. ทำไมหลักฐานจึงสำคัญ

การเปิดเผยหน่วยความจำ (memory disclosure) เป็นสะพานเชื่อมระหว่างการที่โปรเซสพัง (process crash) กับการต่อโซ่การโจมตี (exploit chain) ค่าเซสชันที่มีขนาดผิดปกติพร้อมข้อมูลไบนารีฝังอยู่ สอดคล้องกับพฤติกรรมของรันไทม์ที่ตีความหน่วยความจำที่ไม่ถูกต้องเป็นสตริง Zend รายงานการวิจัยยังอธิบายเพิ่มเติมถึงการดึงที่อยู่โค้ดและที่อยู่ฮีปจากหน้าต่างข้อมูลที่รั่วไหล ชุดหลักฐานมีการตอบกลับดิบ แต่ไม่มีสคริปต์แยกต่างหากที่พิสูจน์ทุกที่อยู่ที่กู้คืนมาได้

อาร์ติแฟกต์ RCE แสดงบริบทความปลอดภัยของ www-data แต่ไม่ได้ยืนยันการเข้าถึงระดับ root การถูกบุกรุกของสภาพแวดล้อม production หรือความสามารถในการพอร์ตได้อย่างสมบูรณ์ไปยังการติดตั้งใช้งาน PHP ใด ๆ การกำหนดค่าห้องปฏิบัติการแบบ worker เดียวมีความสำคัญ เพราะการจัดลำดับคำขอและ worker affinity ส่งผลต่อกลไกนี้

4. การแก้ไขที่วงจรชีวิตพื้นฐาน ไม่ใช่เพียงอาการที่ปรากฏ

diff ต้นฉบับที่ให้มาสำหรับ PHP patch commit 01a40e89fbfc ("Avoid state corruption via bailout") แสดงให้เห็นถึงการกำหนดค่าเริ่มต้นของ session-global แต่เนิ่น ๆ การเปลี่ยนแปลงในการจัดการ OOM ของ allocator และตรรกะการรีเซ็ต/ล้างข้อมูลที่ครอบคลุมมากขึ้น การเปลี่ยนแปลงเหล่านี้มีจุดประสงค์เพื่อป้องกันไม่ให้ native state หลงเหลืออยู่ในสถานะที่ไม่ถูกต้องหลังจากคำขอถูกขัดจังหวะ การแก้ไขเฉพาะเส้นทางการเข้ารหัสคุกกี้เพียงอย่างเดียวจะไม่สามารถคืนหลักประกันความเป็นเจ้าของหน่วยความจำนี้ได้ด้วยตัวเอง

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

5. การดำเนินการเชิงป้องกัน

• ทันที อัปเกรดไลน์ PHP ที่รองรับซึ่งได้รับผลกระทบไปยังรีลีสที่แก้ไขด้านความปลอดภัยแล้ว และใช้คำแนะนำจากผู้จำหน่ายเพื่อยืนยันสถานะแพ็กเกจที่แน่นอน

• ลดการเปิดเผย ควรพิจารณาจำกัดอินพุตแบบหลายส่วนและปิดใช้งาน code>session.upload_progress/code> หากไม่ได้ใช้งาน; สิ่งเหล่านี้ไม่ได้แทนที่แพตช์

• การตรวจจับ ตรวจสอบการแครชระหว่างการเริ่มต้นคำขอ ข้อผิดพลาด 500 ที่ไม่คาดคิด และcode>Set-Cookie/code> ส่วนหัวการตอบกลับที่มีขนาดใหญ่เกินไป

• การรับประกัน ทดสอบซ้ำด้วยพูลเวิร์กเกอร์ที่เป็นตัวแทนสภาพแวดล้อมการผลิต และตรวจสอบว่าสถานะเซสชันเดิมไม่สามารถคงอยู่ข้ามคำขอได้

6. วิธีการวิจัยของ OrcaCyber

งานวิจัยที่มีคุณค่าไม่ใช่เพียงการชี้ให้เห็นการดำเนินการที่ไม่ปลอดภัยแต่ละรายการเท่านั้น แต่คือการติดตามการละเมิดเงื่อนไขคงที่ (invariant) แบบครบวงจร ตั้งแต่การแยกวิเคราะห์คำขอ พฤติกรรมของตัวจัดสรรหน่วยความจำ ตัวแปรโกลบอลเนทีฟแบบคงอยู่ การทำให้เป็นอนุกรม ไปจนถึงการปิดระบบ OrcaCyber Zero และ OrcaCyber Ultra ถูกใช้เพื่อสร้าง PoC ในการสอบสวนนี้ ตามที่ทีมวิจัยระบุ ชุดอาร์ติแฟกต์สาธารณะสนับสนุนการทำซ้ำทางเทคนิค แต่ไม่ได้ให้ร่องรอยการทำงานแยกตามแต่ละโมเดล หรือพิสูจน์การค้นพบช่องโหว่แบบอัตโนมัติ

ลำดับขั้นของหลักฐาน: สมมติฐานจากซอร์ส → ตัวกระตุ้นที่เข้าถึงได้ → ความล้มเหลวขณะรัน → การเปิดเผยข้อมูล → การพิสูจน์การรัน → การทดสอบถดถอยของเวอร์ชันที่แก้ไขแล้ว ลำดับนี้สร้างความเชื่อมั่นได้มากกว่าคำอธิบายช่องโหว่หรือผลลัพธ์ที่มีเพียงการแครช และยังส่งเสริมให้รายงานความไม่แน่นอนอย่างชัดเจนเมื่อไม่มีไฟล์ซอร์สหรือบันทึกการรันดิบ

7. ขอบเขตและข้อจำกัด

เอกสารเผยแพร่นี้อธิบายห้องปฏิบัติการ Docker แบบแยกเดี่ยวที่ได้รับอนุญาต เอ็กซ์พลอยต์นี้อ้างอิงจากงานวิจัย PHP2Shell ที่เผยแพร่ก่อนหน้านี้ โดยมีการปรับใช้เฉพาะสภาพแวดล้อมท้องถิ่นซึ่งบันทึกไว้ในรายงานที่จัดให้ ชุดข้อมูลประกอบด้วยสคริปต์ diff ไบต์ของการตอบสนอง ล็อก และเอาต์พุตหลักฐาน แต่ไม่รวมถึงเช็กเอาต์เอ็กซ์พลอยต์ต้นทางฉบับเต็ม ภาพหน้าจอเนทีฟ และบันทึกการทดสอบถดถอยแพตช์แบบดิบฉบับสมบูรณ์ ไม่มีการกล่าวอ้างถึงเหยื่อหรือลูกค้าในโลกจริงที่ถูกบุกรุก

แหล่งที่มาและอาร์ติแฟกต์

หลัก: ไฟล์ที่จัดหาให้ php2shell-report-bundle.tar.gz (REPORT.md; report-CVE-2026-109618.md; report-CVE-2026-109619.md; crash_evidence.log; leak_attempt.resp; rce_proof_8426.txt; diff ซอร์สโค้ด PHP) บริบทสาธารณะ: ประกาศด้านความปลอดภัยของ PHP GHSA-w8hw-w9fx-j79w และ GHSA-6wmf-4rv5-p3rp; ประกาศเปิดตัวเวอร์ชันความปลอดภัยของ PHP การระบุแหล่งที่มาของ exploit สาธารณะ: 9bie/php2shell-bypass-aslr-exp ที่เก็บงานวิจัย: orcacyber-php2shell-research.

The public orcacyber-php2shell-research GitHub repository README on the OrcaCyber PHP2Shell defender research artifacts and its defensive scripts

ข้อสรุป: คำขอหนึ่งล้มเหลว; พอยน์เตอร์ยังคงอยู่; คำขอถัดไปเชื่อถือมัน ส่วนที่ยากของการทำความเข้าใจช่องโหว่นี้คือการสร้างความเชื่อมโยงนั้นด้วยหลักฐานที่สังเกตได้

การเปรียบเทียบในบทความนี้1

ตรวจพบจากบทความนี้

© 2026 OrcaRouter

สำหรับผู้ให้บริการ

ให้บริการแพลตฟอร์มการอนุมานอยู่หรือไม่ นำโมเดลของคุณขึ้น OrcaRouter

providers@orcarouter.ai

เข้าร่วมคอมมูนิตี้ของเรา

Discordsupport@orcarouter.aiXGitHubYouTube