כרטיס ה-hero של PHP2Shell: מבקשה שנכשלה ועד ביצוע קוד מרחוק, CVE-2026-109618 ו-CVE-2026-109619
Engineering & Research

OrcaCyber Research - PHP2Shell: כיצד בקשה שנכשלה הפכה להרצת קוד מרחוק

מחבר

Rowan Sterling

תאריך פרסום

מודלים אחרונים · 20צפו בכל המודלים →
בנצ'מרקים: Artificial Analysis · מתעדכן יומית
חזרה לכל הפוסטים

הוכחת ההיתכנות בחקירה זו נוצרה באמצעות OrcaCyber Zero וOrcaCyber Ultra מודלים. חבילת המחקר מתעדת ניתוח ברמת קוד המקור, שחזור מבוקר באמצעות ניצול ציבורי מותאם, פריט חשיפת זיכרון, קריסות תהליכים וראיות להרצת פקודות. הקבצים שסופקו אינם מתעדים באופן עצמאי אילו שלבים בוצעו על ידי כל מודל; ייחוס המודל ניתן על ידי צוות המחקר.

מצב קטלני של חוסר בזיכרון אמור לסיים בקשה בבטחה. כאן, הוא עלול היה להפריע ל-PHP בזמן שמצב native היה מאותחל רק חלקית, ולהשאיר הפניות שנמשכו אל הבקשה הבאה. התוצאה הייתה הפרה של משך החיים של זיכרון בין בקשות, עם השלכות שנעות מחשיפה ועד הרצת קוד מרחוק בסביבת הבדיקה.

ראיות מרכזיות במבט חטוף

• יעד — PHP 8.4.26, Apache/mod_php, עובד יחיד, מעבדת Docker מבודדת.

• יומני קריסה — יציאת worker אחת מסוג SIGABRT ושלוש יציאות worker מסוג SIGSEGV בקטע שסופק.

• תגובת 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. הפגיעות: כשל בבעלות על גבול הבקשה

שתי הבעיות הקשורות נוגעות לאתחול בקשה שנקטע ולמצביעים גלובליים בזמן ריצה שאינם מעודכנים. בארכיטקטורת PHP הרלוונטית, טיפול ב-multipart/form-data וקריאות חוזרות של התקדמות העלאה בסשן יכולים לרוץ לפני קוד היישום הרגיל של המשתמש. מעבר חריג בזרימת הבקרה, כולל code>zend_bailout()/code>, יכול לדלג על ניקוי צפוי ולהשאיר מצב שמצביע על זיכרון שמאוחר יותר משוחרר או נעשה בו שימוש חוזר.

אינווריאנט אבטחה: הפניה גלובלית של worker שנחשפת לבקשה B לעולם לא תפנה לזיכרון שהבעלות עליו ותוחלת חייו הסתיימו עם בקשה A. הכשל המדווח מפר את האינווריאנט הזה.

נקודת הקצה שהודגמה הייתה עמוד PHP מינימלי שהחזיר פשוט OK; נרטיב הניצול לא היה תלוי בנקודות קצה של הזרקת SQL ברמת היישום, הכללת קבצים או דה-סריאליזציה.

2. רצף טכני

• A1 — הפרעה. טיפול ב-Multipart ובהתקדמות העלאה גורם ל-OOM במהלך הניקוי, ומשאיר מצב סשן מיושן.

• B1 — דליפה. בקשה עוקבת גורמת לסריאליזציה של עוגיית סשן לקרוא מעבר למזהה סשן תקין.

• שחזור כתובות. ערכי מצביעים שהודלפו משמשים להסקת פריסת הספריות וה-heap הרלוונטית באותו build.

• 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

מוצגי ראיות: מה שהקבצים שסופקו מראים בפועל

נספח א׳ — הפסקת worker מתוך יומן 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), ייתכן קובץ ליבה ב־/etc/apache2/code>

• 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: תהליך בן 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>

• אורך ה-cookie המקודד: 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

נספח ד׳ — תיקון מחזור החיים של הסשן

• 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>

שורות נבחרות מתוך ה-diff של הקוד ב-session.c.diff. שינוי זה מאפס במפורש מצב גלובלי של הסשן מוקדם יותר מ-RINIT רגיל.

3. מדוע הראיות חשובות

חשיפת הזיכרון מספקת את הגשר בין קריסת תהליך לשרשרת ניצול. ערך סשן בגודל חריג עם נתונים בינאריים מוטמעים תואם לכך שסביבת ההרצה מפרשת זיכרון לא תקין כמחרוזת Zend. דוח המחקר מתאר בנוסף חילוץ כתובות קוד ו-heap מחלון ההדלפה. חבילת הראיות מכילה את התגובה הגולמית אך לא סקריפט עצמאי המוכיח כל כתובת ששוחזרה.

ארטיפקט ה-RCE מציג את הקשר האבטחה של www-data. הוא אינו מבסס גישת root, פגיעה בסביבת ייצור, או ניידות מלאה לפריסות PHP שרירותיות. תצורת המעבדה עם עובד יחיד חשובה מכיוון שסדר הבקשות והזיקה לעובד משפיעים על המנגנון.

4. תיקון של מחזור החיים הבסיסי, ולא רק של הסימפטום

ה-diff של קוד המקור שסופק עבור קומיט התיקון של PHP ‏01a40e89fbfc ("Avoid state corruption via bailout") מציג אתחול מוקדם של גלובליים ברמת הסשן, שינויים בטיפול ב-OOM של מקצה הזיכרון, ולוגיקת איפוס/ניקוי רחבה יותר. שינויים אלה נועדו למנוע ממצב נייטיב להישאר לאחר בקשה שנקטעה במצב לא תקין. תיקון נתיב קידוד ה-cookie בלבד לא היה משחזר, כשלעצמו, את הבטחת הבעלות על הזיכרון הזו.

דוח המחקר מציין כי ניסיונות כנגד PHP 8.4.27 לא הניבו עוגייה חריגה, קריסה או הוכחת RCE בארבעה ניסויים. תמלילי הגרסה המתוקנת בפועל אינם נמצאים בחבילה זו, ולכן השוואה זו מדווחת כתצפית של חוקר ולא כמוצג הניתן לבדיקה עצמאית.

5. פעולות הגנתיות

• מיידי. שדרגו את קו ה-PHP הנתמך שנפגע לגרסה שתוקנה מבחינת אבטחה, והשתמשו בהודעות היצרן כדי לאמת את מצב החבילה המדויק.

• צמצום החשיפה. שקלו להגביל קלטים מרובי-חלקים ולהשבית code>session.upload_progress/code> אם אינו בשימוש; אלה אינם מחליפים את התיקון.

• זיהוי. סקור קריסות במהלך אתחול בקשה, שגיאות 500 לא צפויות, וכותרות תגובה מסוג code>Set-Cookie/code> בגודל מוגזם.

• הבטחה. בדוק מחדש עם מאגרי עובדים המייצגים את סביבת הייצור ואמת שמצב סשן ישן אינו יכול להישמר בין בקשות.

6. מתודולוגיית המחקר של OrcaCyber

המשימה המחקרית בעלת הערך אינה רק איתור פעולות לא בטוחות בודדות; היא מעקב אחר הפרת אינווריאנטה מלאה לאורך פירוק בקשות, התנהגות מקצה הזיכרון, גלובלים נייטיביים מתמשכים, סריאליזציה וכיבוי. OrcaCyber Zero ו-OrcaCyber Ultra שימשו ליצירת ה-PoC בחקירה זו, כפי שיוחס על ידי צוות המחקר. מערך הארטיפקטים הציבורי תומך בשחזור הטכני, אך אינו מספק עקבות הרצה לכל מודל בנפרד או מוכיח גילוי אוטונומי של פגיעויות.

סולם הראיות: השערת מקור → טריגר נגיש → כשל בזמן ריצה → חשיפת מידע → הוכחת הרצה → רגרסיה בגרסה מתוקנת. רצף זה יוצר ביטחון חזק יותר מאשר תיאור פגיעות או תוצאה של קריסה בלבד. הוא גם מעודד דיווח ברור על אי-ודאות כאשר קבצי מקור או יומני הרצה גולמיים חסרים.

7. היקף ומגבלות

פרסום זה מתאר מעבדת Docker מבודדת מורשית. ניצול החולשה מבוסס על מחקר PHP2Shell שפורסם בעבר, עם התאמה מקומית המתועדת בדוח שסופק. החבילה כוללת סקריפטים, דיפים, בתים של תגובות, יומנים ופלט הוכחה, אך משמיטה את מלוא ה-checkout של ניצול ה-upstream, צילומי מסך מקוריים ותמלולים גולמיים מלאים של רגרסיית תיקונים. לא נטען כי קורבן או לקוח בעולם האמיתי נפגעו.

מקורות וארטיפקטים

ראשי: הקובץ שסופק 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; הבדלי קוד המקור של PHP). הקשר ציבורי: התראות אבטחה של PHP GHSA-w8hw-w9fx-j79w ו-GHSA-6wmf-4rv5-p3rp; הכרזות שחרור אבטחה של PHP. ייחוס ניצול ציבורי: 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

זוהה מתוך המאמר הזה