מספיק import אחד: 14 חבילות npm הפיצו implant ללינוקס שמגיע עם עוזר LLM לתוקף
חבילת npm בשם streak-metrics-math מבטיחה דברים צנועים: לקבץ ערכים לפי יום, למדוד הפרש בין תאריכים, ולמצוא ימים שעומדים ביעד. מי שטורח לפתוח את הקוד עצמו, ב-dist/internal/daymath.mjs, מוצא בדיוק את זה. הפונקציות עובדות, התיעוד מדויק, ואין שם שורה אחת חריגה. בתיקייה שלידן יושב קובץ בינארי שהקוד מציג כמאיץ מתמטי מקומי. הוא לא מאיץ כלום.
ב-20 באוגוסט פרסם החוקר Aliakbar Zahravi מ-TrendAI Research ניתוח של אשכול בן 14 חבילות npm שבנויות כולן באותה צורה: לוגיקת תאריכים אמיתית מלפנים, קובץ ELF ללינוקס מאחור. הקובץ זוהה כ-RedShell, המימוש הלינוקסי של מסגרת פיקוד ובקרה מסחרית בשם RedC2 שמשווקת בפורום Hack Forums. נעבור על שלושה דברים: איך המטען מופעל בלי שאף אחד קרא לו, מה הוא יודע לעשות על המכונה, ולמה דווקא רכיב ה-AI שנלווה אליו הוא החלק שראוי לעצור עליו.
אשכול של 14 חבילות, מטען אחד
החבילות פורסמו כשירותי עזר קטנים וחסרי תלויות לחישובי לוח שנה ורצפים. ברשימה של TrendAI מופיעות streak-metrics-math (בגרסאות 1.0.0 ו-1.0.1), kit-map-vim, streak-map-cache, streak-map-kit, map-streak-kit, streak-cache-map, streak-calc-metrics, streak-calc-math, streak-math-abz, streak-metricsaz, streak-math-metrics, streak-metricazbd, streak-metricsazb ו-streak-kit-map, כולן בגרסה 1.0.0. השמות דומים מספיק זה לזה כדי להיראות כמו משפחה אחת של כלים, ורחוקים מספיק זה מזה כדי שהסרה של אחד לא תפיל את השאר.
שם הקובץ הבינארי משתנה בין החבילות, math-core.bin, math-calc.bin, calc-math.dat, calc-cache.bin, calc.bin או calc-mapping.bin, והוא יושב או ישירות ב-dist/ או תחת dist/internal/. התוכן, לעומת זאת, זהה בכולן. אותו implant בדיוק, באריזה אחרת.
למה --ignore-scripts לא עוזר כאן
הדרך המוכרת שבה חבילת npm זדונית מריצה קוד היא דרך hook התקנה, כלומר סקריפט שמוגדר בחבילה ורץ אוטומטית בזמן ההתקנה. בדיוק בגלל זה קיים הדגל --ignore-scripts, וארגונים רבים מפעילים אותו כברירת מחדל. כאן זה פשוט לא רלוונטי, כי לחבילות האלה אין hook כזה בכלל.
מה שיש להן זה קובץ הכניסה dist/index.mjs. הוא מייצא מחדש את חמש פונקציות התאריכים, כדי שמי שמייבא את החבילה יקבל את מה שהוא בא בשבילו, וכל השאר בקובץ הוא שגרת אתחול שאף פונקציה מיוצאת לא מגיעה אליה. השגרה עטופה בביטוי שמופעל מיד עם טעינת המודול, וזה הלב של העניין: אין צורך לקרוא לשום פונקציה כדי שהמטען ירוץ. "ייבוא אחד בכל מקום בגרף התלויות מספיק, כולל מתלות עקיפה שהמפתח מעולם לא בחר", כתב Zahravi.
לפני ההרצה השגרה עושה שלושה דברים. היא בודקת שהקובץ קיים, ואם לא, היא מדפיסה אזהרה על מאיץ חסר וחוזרת בשקט. היא מסמנת אותו כניתן להרצה. ואז היא מחשבת עליו טביעת אצבע SHA-256 ומשווה אותה לערך קבוע שמוטמע בקוד, כך שרק הבנייה המדויקת של המפעיל תרוץ. הנתיב אל הקובץ נגזר ממיקום המודול עצמו, ולכן הוא נכון בלי קשר לאיפה החבילה הותקנה או מאיזו תיקייה רץ התהליך. רק אחרי שכל זה עבר, המטען מופעל כתהליך רקע מנותק, בקבוצת תהליכים משלו, כך שהוא שורד גם אחרי שתהליך ה-Node שייבא אותו נסגר.
מה הקובץ עושה ברגע שהוא רץ
עד כאן איך הקוד נכנס. מהרגע שהוא רץ מתחיל implant מלא. RedShell מתעלם תחילה מהסיגנל SIGPIPE, כדי שחיבור רשת שנקטע לא יפיל אותו, ואז מנתק את עצמו מהטרמינל בטכניקת double-fork ועובר לרקע.
התקשורת מנוהלת בכמה ערוצים נפרדים, וזה חשוב להבנה של מה נראה ברשת. ערוץ הפיקוד הראשי פונה לכתובת קבועה, 217.60.77.63, בפורט 8792, ואם החיבור נכשל הוא נופל חזרה ל-127.0.0.1 באותו פורט. מעליו נפרשׂ TLS בגרסה 1.2 ומעלה, אבל אימות התעודה מבוטל במפורש, כך שהשרת יכול להציג כל תעודה שהיא. מעל ה-TLS יש עוד שכבת ערפול משלהם, שלושה סבבים של XOR בשילוב סיבוב ביטים. החיבור מכוון להתנתק מהר: בדיקות keepalive מתחילות אחרי שנייה של חוסר פעילות, חוזרות כל שלוש שניות, והחיבור נזרק אחרי חמישה כישלונות.
הודעת הרישום הראשונה מביאה למפעיל שם משתמש, שם מארח, פרטי מערכת הפעלה, האם התהליך רץ כ-root, כתובות IP מקומיות וכתובת ציבורית שנשלפת מ-api.ipify.org. אליהם מצורף מזהה התקנה קבוע, שנשמר בקובץ מוסתר תחת ספריית ההגדרות של המשתמש ונקרא משם בהפעלות הבאות. כך כל דיווח נקשר לאותה מכונה גם אחרי אתחול.
מה התוקף מקבל
רשימת הפקודות ארוכה, וכדאי להסתכל עליה לפי מה שהיא מאפשרת. יש בה מעטפת פקודות אינטראקטיבית שרצה דרך /bin/sh עם מגבלת זמן של 120 שניות, סקירה של המערכת והרשת, והעברת קבצים לשני הכיוונים. יש בה חילוץ ממוקד: פקודה אחת סורקת מפתחות SSH וקבצי הגדרות, שנייה אוספת קבצי פרטי אימות של דפדפנים, ושלישית מחפשת מסדי נתונים שרצים על המכונה, פורטים פתוחים וקובצי הגדרות שלהם.
לשמירת אחיזה אחרי אתחול יש ארבע אפשרויות נפרדות: רשומת @reboot ב-crontab, הוספת שורה ל-bashrc של המשתמש, service ברמת המשתמש ב-systemd, או רשומת הפעלה אוטומטית בתקן XDG. פקודה אחת מסירה את כולן. לתנועה פנימה ברשת יש proxy מסוג SOCKS5 והעברת פורטים, ולהרצה יש מסלול שלא נוגע בדיסק בכלל: קובץ ELF שמועלה לזיכרון ומורץ דרך memfd_create, או shellcode שמורץ מתוך אזור זיכרון ייעודי.
הצד המעניין הוא דווקא הפער בין הערוצים. הפיקוד עצמו מוצפן היטב, אבל הוצאת המידע בכמות לא. פקודת האיסוף ההמונית שולחת את הקבצים ישירות לאותה כתובת IP בפורט 8060 מעל HTTP רגיל, בלי TLS. הקבצים אמנם מקודדים ב-Base64, אבל קידוד הוא לא הצפנה, וכל מי שרואה את התעבורה רואה את התוכן. חלק מהעלאות הקבצים נעשות בכלל דרך שירות שיתוף קבצים ציבורי, litterbox.catbox.moe, מעל HTTPS תקין. הפער הזה הוא גם ההזדמנות של המגן: התעבורה הכי חושפנית היא גם הכי קלה לזיהוי.
העוזר שמתרגם משפט לשרשרת פקודות
החלק שמייחד את RedC2 מכלי פיקוד מסחריים אחרים הוא רכיב בשם Red Agent. מדובר בשכבת הרצה שמבוססת על מודל שפה, זמינה מתוך הטרמינל של כל beacon גם בממשק הרשת וגם בלקוח שורת הפקודה, ומופעלת בפקודה קצרה. לפי התיעוד שציטטו החוקרים, הוא אומן על מערך הפקודות של המסגרת ועל יכולות ה-beacon, ומבצע ניתוח שמפרק בקשה אחת בשפה חופשית לשרשרת משימות מסודרת.
Zahravi מציב את זה מול איך שזה עבד קודם. בעבר המודל היה מנותק מהכלי: המפעיל עבר לחלון צ'אט, ניסח שאלה, קיבל פקודה והדביק אותה חזרה בקונסולה. עכשיו המודל יושב בתוך המסגרת, רואה את מצב הסשן ויש לו סמכות להריץ. "מפעיל מזין הנחיות בשפה טבעית, והמסגרת מתרגמת אותן לרצפי פקודות להרצה", נכתב בדוח, והמסקנה שנגזרת שם היא שהיכולת הזאת מורידה את רף הכניסה ומאפשרת גם למפעילים פחות מיומנים להריץ חדירה רב-שלבית.
כדאי גם לשים לב לקצב. לפי ציר הזמן שריכזה TrendAI, תמיכת לינוקס נכנסה ל-RedC2 רק בגרסה 4.0 ביוני 2026, יחד עם RedShell ועם העברת הקומפילציה של ה-beacon-ים לתוך המסגרת. ביולי נוספה מנהרת מעטפת בין רשתות, שמאפשרת למפעיל לחבר beacon אחד לשני ברשתות שונות דרך השרת בלי מסלול ישיר ביניהם. בתחילת אוגוסט הורחבה התמיכה ל-WSL, ובאותו עדכון תוקנה תקלה שהפילה את Red Agent בלינוקס. פחות משלושה חודשים מהוספת התמיכה בלינוקס, הכלי כבר מופץ בפועל דרך ספריית קוד פתוח.
החוקרים לא ייחסו את הקמפיין לגורם מסוים, ולא פרסמו מספרי הורדות של החבילות. מה שכן, שילוב של מסגרת מדף שנמכרת בפורום פתוח עם ערוץ הפצה שמגיע ישירות לתוך תהליך הבנייה של ארגונים הוא בדיוק המקום שאליו הולכות מתקפות שרשרת האספקה בשנה האחרונה.
מה זה אומר בפועל
מי שמריץ בקרה על חבילות npm ונשען על חסימת סקריפטי התקנה צריך להבין שהבקרה הזאת עיוורת לתבנית הזאת לגמרי, כי כאן אין סקריפט התקנה, יש קוד שרץ בזמן ייבוא. שווה לחפש בסביבה קובצי .bin שנארזים בתוך חבילות npm ומקבלים הרשאת הרצה, ולבדוק תעבורה יוצאת מכונות בנייה ומשרתי CI אל כתובות IP חשופות בפורטים לא סטנדרטיים. TrendAI פרסמה את טביעת האצבע של הבינארי ואת כתובת השרת בדוח עצמו, וזו נקודת הפתיחה הזולה ביותר לבדיקה רטרואקטיבית.
תגובות