אין קובץ בדיסק, אין פורט שמאזין ואין חיבור יוצא: PEERSTITCH, השתל ש-Unit 42 מצאה בתוך חומות אש FortiGate
בתוך הארכיון שהתוקפים הוציאו ממכשיר הניהול היה גם קובץ טקסט פשוט: רשימה של יותר מ-500 מספרים סיריאליים של חומות אש FortiGate, ולצד כל אחד כתובת ה-IP הציבורית שלו. בלי הצפנה, בלי מסד נתונים, סתם אינוונטר. חוקרי Unit 42 של פאלו אלטו פרסמו ב-14 באוקטובר את תחקיר החדירה שממנה נלקח הקובץ, אצל ספק תקשורת שמנהל תשתית אבטחה גם ללקוחות אחרים. דניאל גוט ושון ווסטפול, שכתבו את הדוח, עוקבים אחרי האשכול בשם CL-STA-0954, ולפי הערכתם חלק מהפעילות שאחרי הפריצה חופפת לחדירות שיוחסו לגורמים שחשודים כמדינתיים.
המעניין בתחקיר הוא לא הכמות אלא מה שהתוקפים השאירו על חומות האש עצמן. נוזקה בשם PEERSTITCH, שלא כותבת קובץ לדיסק, לא פותחת פורט שמאזין ולא יוצרת שום חיבור יוצא. היא יושבת בתוך הזיכרון של שני תהליכים שרצים ב-FortiOS ממילא, ומחכה שהתעבורה הלגיטימית שעוברת דרכם תביא לה את הסימן שהיא מחפשת. בהמשך נראה איך נכנסו למכשיר הניהול, איך עלו מהרשאות אדמין ל-root, ואיך שני תהליכים על אותה חומת אש מעבירים ביניהם מידע בלי אף ערוץ שאפשר להאזין לו.
מה יצא מתוך מכשיר ניהול אחד
החדירה התחילה בספטמבר 2024, לפי Unit 42, בניצול CVE-2024-47575 מול FortiManager מרכזי, החולשה שמוכרת כ-FortiJump. הציון שלה 9.8 כי אין בה שלב אימות בכלל: תוקף לא מאומת שולח בקשות מעובדות לערוץ הניהול FMG-Access ב-TCP port 541, ומריץ פקודות. CISA הכניסה אותה לרשימת החולשות שמנוצלות בפועל שלה ב-23 באוקטובר 2024, היום שבו הרשומה פורסמה.
התוקפים רשמו ל-FortiManager מכשיר FortiGate וירטואלי מזויף בשם localhost, מכתובת חיצונית שבשליטתם, ומיד אחר כך יצרו ארכיון תצורה וחילצו אותו. בתוכו היו קובצי התצורה המלאים של יותר מ-500 חומות אש מנוהלות, מסדי הנתונים המרכזיים של הניהול (global.db ו-revinfo.db), מפות טופולוגיה וטבלאות ניתוב, פרטי אימות של מנהלים ושל SSL/VPN כטקסט מוצפן הפיך, ותעודות ומפתחות פרטיים. החוקרים מדגישים כאן נקודה שקל לפספס: הם בדקו רק את הסביבה של הספק ולא את רשתות הלקוחות, ולכן מה שתועד הוא חשיפה של תצורה ופרטי אימות, לא חדירה מאומתת לרשתות הלקוחות.
את פרטי האימות המוצפנים אפשר לפתוח בכוח חישוב, ו-Unit 42 אימתו את זה כשהצליחו לשחזר סיסמאות של מנהלים ושל SSL/VPN מתוך הקבצים שחולצו. משם התוקפים פשוט התחברו: סשנים של SSL/VPN אל חומות ההיקף, עם פרטי אימות תקפים לגמרי, מתוך תשתית חיצונית משלהם, ומשם גישה מאומתת למקטעי הניהול הפנימיים.
עוד לפני זה הם עשו עם מכשיר הניהול את מה שמסביר למה פלטפורמת ניהול שווה כל כך הרבה: דחפו ממנה הגדרות האזנה לתעבורה אל חומות האש שמתחתיה. ההאזנה כוונה לתעבורת HTTP לא מוצפנת ולאחד-עשר שירותים ספציפיים, ובשלב מאוחר גם ל-RADIUS ול-RADIUS Accounting (UDP 1812 ו-1813), ל-LDAP (TCP 389) ול-TFTP (UDP 69). אימות רשת, שאילתות Active Directory והעברות קבצים, הכול מנקודת התצפית הטובה ביותר ברשת.
אז איך עולים מאדמין ל-root?
מנהל FortiOS, גם עם הרשאות super_admin, לא מקבל shell. הוא עובד בתוך שורת פקודה מנוהלת ומוגבלת, בלי גישה ישירה למערכת הקבצים ובלי שליטה בתהליכים שרצים על המכשיר. ה-daemon-ים שמממשים את FortiOS, מצד שני, רצים כ-root מתחת לממשק. הפער בין שתי השכבות הוא כל העניין.
CVE-2025-61624 מוחקת אותו. שם האובייקט במנוע system.auto-script לא מסונן, ולכן שם שמכיל רצף מעבר נתיב (../../) מניח את גוף הסקריפט מחוץ לתיקייה המיועדת לו, בכל מקום שנבחר במערכת הקבצים, והסקריפט מורץ בהרשאות של המנוע. בפועל זו כתיבה ומחיקה של קבצים כ-root מתוך ממשק שלא אמור לאפשר אפילו להציץ למערכת הקבצים. התוקפים יצרו אובייקט שהשם שלו הוא ../../../../setup, והשתמשו בו כדי להוריד את שלב הטעינה הראשון של PEERSTITCH.
הציון שלה הוא 6.5 ב-NVD ו-6.0 אצל פורטינט, שתי הדרגות MEDIUM, והיא לא נמצאת ברשימת החולשות המנוצלות בפועל של CISA. ההיגיון מאחורי הציון הבינוני ברור: היא מחייבת חשבון אדמין קיים עם הרשאות קריאה-כתיבה, וזה בדיוק מה שהתוקפים השיגו שלב אחד קודם. (אגב, ברשומת NVD ההערכה של CISA מאפריל 2026 עוד אומרת שאין ניצול ידוע.) ההמלצה, שפורסמה באפריל 2026, נוגעת ל-FortiOS מגרסה 6.4 ועד 7.6.4 וגם ל-FortiProxy, ל-FortiPAM ול-FortiSwitchManager; התיקון ב-FortiOS הוא 7.4.10 או 7.6.5.
שני תהליכים שמדברים ביניהם דרך הזיכרון
PEERSTITCH הוא קובץ ריצה ל-Linux בארכיטקטורת ARM64, כתוב ב-C ומקושר סטטית ל-glibc. הוא לא נוזקה שנשארת לרוץ ברקע אלא מזריק חד-פעמי: עולה, עושה את שלו ונעלם. מה שנשאר אחריו הוא השינוי שהכניס לשני תהליכים שרצים על החומה ממילא, /bin/miglogd שאחראי על רישום הלוגים של המערכת ושל התעבורה, ו-/bin/iked שמנהל את משא ומתן ההצפנה של IPsec ו-IKE.
סדר הפעולות שלו קצר. הוא עובר על /proc, מפרסר את שורות הפקודה ומאתר את המזהים של שני ה-daemon-ים, קורא את מפות הזיכרון שלהם כדי לדעת איפה כל אחד יושב, נצמד לשניהם דרך ptrace ועוצר אותם, ושומר את מצב הרגיסטרים. אז הוא מקצה בכל אחד מהם אזור זיכרון של 16 קילובייט שמותר לקרוא ממנו, לכתוב אליו וגם להריץ ממנו (RWX), וכותב לתוכו מטען של 1,344 בייט. לסיום הוא מכניס שלושה תיקוני NOP לנקודות קבועות בקוד התהליך, כדי להשתיק בדיקות שלמות ולשנות שגרות ברירת מחדל, ומפנה את זרימת ההרצה אל אזור הזיכרון החדש.
עד כאן זו הזרקת זיכרון מורכבת אבל מוכרת. החדש הוא מה ששני ההוקים עושים אחרי שהם בפנים.
הקוד שהושתל בכל אחד מהתהליכים לא מפנה תעבורה ולא פותח ערוץ. הוא רק מסתכל על הנתונים שכבר עוברים דרך התהליך ומחפש בהם שני סימנים, המחרוזת 8550 והכתובת 169.254.0.1, ושניהם לא פורט שמאזין ולא כתובת שפונים אליה אלא תווים שמופיעים בגוף התעבורה ומשמשים סימן זיהוי. כשסימן כזה מופיע, ההוק שולף מתוכו מזהה סשן באורך של עד 31 בייט ושומר אותו במאגר מחזורי (ring buffer) בן 16 תאים באזור הזיכרון שלו.
ואז מגיע החלק שמחליף את ערוץ התקשורת. ההוק שב-miglogd פותח את /proc/<pid>/mem של iked וכותב את המזהה ישירות לזיכרון של התהליך השני, לפי טבלת העברה שהוזרקה אליו מראש עם המזהה והכתובת של עמיתו. כשה-iked מטפל אחר כך בסשן VPN, ההוק שלו בודק אם המזהה המתאים מופיע במאגר, ואם כן הוא קופץ למסלול חזרה אחר ומדלג על בדיקות האבטחה שה-FortiOS עושה בדרך כלל. ואין כאן ערוץ שאפשר לחסום: שני תהליכים על אותו מכשיר מעבירים ביניהם מידע בלי socket, בלי קובץ ובלי שום דבר שסורק רשת או דיסק יכול לראות.
ה-C2 שהתחבא בתוך חידוש תעודות
הנוזקה עצמה, כאמור, לא יוצרת חיבורים, ולכן במקביל אליה התוקפים בנו ערוץ שליטה ובקרה נפרד (C2, הערוץ שדרכו התוקף שולח פקודות לנוזקה), מתוך מודול לגיטימי שקיים על החומה: mod_md של Apache, שתפקידו לנהל חידוש אוטומטי של תעודות SSL בפרוטוקול ACME.
הם יצרו קובץ תצורה ל-mod_md שמפנה את בקשות ה-ACME לשרת תעודות שבשליטתם, ומיפו את אתגר האימות DNS-01 ישירות אל /bin/node. מכאן זה מתגלגל לבד: בכל פעם שה-Apache מתחיל אימות תעודה הוא מריץ Node.js עם פרמטרים שהגיעו מהשרת של התוקף, ואת הפקודות עצמן הזריקו לתוך שדה שם המתחם של בקשת האתגר. מה שיצא מזה הוא חיבור reverse shell מעל SSH, חיבור שהמכשיר הנפרץ פותח בעצמו כלפי חוץ במקום לחכות שיתחברו אליו. הגדרת MDRenewMode על always סגרה את הלופ: היא מכריחה את ה-daemon לנסות לחדש בלי סוף, וכל ניסיון מריץ מחדש את אותו מטען.
מי שמנהל תשתית של אחרים
בשלב מסוים נרשמו על חומות אש מנוהלות הורדות של קובצי תצורה מלאים, בידי חשבון מנהל בשם FortiGateCloud, מעל פרוטוקול FGFM ב-TCP port 541. לארגון שנפגע לא היה tenant של FortiManager Cloud, וחשבון כזה לא הוגדר על המכשירים. Unit 42 מעריכים ברמת ביטחון בינונית שהתוקפים התחזו לפלטפורמת הניהול, ואומרים במפורש שהראיות לא מבדילות בין שתי האפשרויות: ניצול חולשה שמאפשרת לעקוף את האימות של FGFM בעזרת המספר הסיריאלי של ה-FortiManager, או שימוש חוזר בחומר ההצפנה שנגנב בארכיון המקורי. באותה רמת ביטחון הם מעריכים שהנפילות החוזרות של ממשק הניהול בזמן הפעילות הזדונית נגרמו בכוונה.
שאר עבודת הניקיון מצטיירת שיטתית. לפני הרצת הסקריפטים התוקפים הרגו את תהליכי הלוג המקומי והמרוחק, ניקו את יומן הקריסות שנוצר מניסיונות ההזרקה הראשונים, מחקו את חשבונות המנהל המזויפים ואת אובייקטי ה-auto-script מיד אחרי השימוש, ודרסו את קובץ התצורה של ערוץ ה-C2 במחרוזת שגרתית שמופיעה בקבצים כאלה ממילא. גם המזריק ניקה אחריו: מחק את עצמו מהדיסק וסיים את תהליך הטעינה לפני שיצא.
ההשלכה האמיתית, לפי החוקרים, היא לא על המכשיר שנפרץ אלא על מה שהחזיק. "עבור ארגונים שמנהלים תשתית בשם אחרים, פלטפורמת הניהול היא המטרה בעלת הערך הגבוה ביותר ברשת", כתבו גוט ווסטפול, "והפריצה אליה גם לא מסתיימת כשהפלטפורמה מתוקנת". חומר ההצפנה שמסדיר את היחסים בין הפלטפורמה לכל מכשיר מנוהל יוצא עם התוקף ונשאר תקף עד שמחליפים אותו, ובמקרה הזה הוא יצא יחד עם 500 מספרים סיריאליים והכתובות שבהן אפשר למצוא אותם.
מה זה אומר בפועל
מי שמריץ FortiOS בין 6.4 ל-7.6.4 צריך לעדכן ל-7.4.10 או ל-7.6.5, וזה נכון גם ל-FortiProxy, ל-FortiPAM ול-FortiSwitchManager. העדכון הוא החלק הקל. אם ה-FortiManager שלכם היה חשוף אי פעם ל-FortiJump, צריך לעבוד לפי ההנחה שפרטי האימות והתעודות שהוא החזיק כבר לא סודיים, ולהחליף סיסמאות מנהלים, פרטי SSL/VPN ותעודות ומפתחות של כל מכשיר מנוהל, לא רק של זה שנפרץ. ובדיקה שאפשר להתחיל ממנה היום: לחפש בהיסטוריית התצורה אובייקטים של system.auto-script ששמם מכיל ../../, ולסרוק את מפות הזיכרון של miglogd ו-iked בחיפוש אזור אנונימי של 16,384 בייט עם הרשאת הרצה. אזור כזה לא אמור להיות שם.
תגובות