forge-jsxy npm Infostealer: מדריך IOCs וזיהוי

forge-jsxy: גונב המידע של npm שמשנה את שמו שוב ושוב

TL; DR

במשך בערך חודשים, גונב מידע יחיד של npm צץ מחדש תחת סדרה מתחלפת של שמות חבילות תוך כדי העברת מטען כמעט ללא שינוי. זה התחיל בגלוי כ forge-jsxy, הוליד forge-jsx3 / forge-jsx4 אחים ואחיות, ואז נטשו לחלוטין את המיתוג "forge" כדי להתחזות לתשתית מפתחים - תחילה zredis-typed, ולאחרונה pinokio-redis.

כל גרסה נושאת את אותה שרשרת כלים פנימיתקבצים בשם forge-jsx-explorer-*, relayPackageServe מודול שמשרת א forge-jsxy-package.tgz, וזמן ריצה עמיד המוסתר תחת ספרייה מנוקדת כך שישרוד גם לאחר מחיקת חבילת npm.

המטען קורא חומר לארנק קריפטוגרפי ופרטי מפתח מהמארח ומשדר אותם לדיסקורד וובhooks, העלאות של HuggingFace Hub, ונקודת קצה C2 מקודדת קשיח. היא מתקינה הפעלה אוטומטית ברמת מערכת ההפעלה כך שהיא תפעל שוב לאחר אתחול מחדש, והיא לוכדת פעילות של לוח הגזירים, המקלדת והמסך. הגרסה האחרונה, pinokio-redis, מתאר את עצמו כאינטגרציה של "Autodesk Forge" - תיאור שאינו קשור למה שהקוד עושה.

מערכת אקולוגיתNpm
מחלקת מטעןגנב מידע רב-שלבי + סוכן שלט רחוק (RAT)
מטרות עיקריותארנקי קריפטו, הרחבות ארנק דפדפן, אישורי מפתח/ענן
התמדהזמן ריצה עמיד נסתר + הפעלה אוטומטית של מערכת ההפעלה (שורדת הסרת חבילות)
exfiltrationדיסקורד רשתhooks + ממסר, HuggingFace Hub, C2 מקודד קשיח בפורט 9877
טווח נצפהמאי 2026 – יולי 2026 (מתמשך)
שם אחרוןpinokio-redis:1.0.127

אנטומיה של התקפה

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

  • שלב 1 - להתממש. סקריפט ההתקנה מפענח קובץ מקודד ומקובץ blob לתוך קבוצת סקריפטים של זמן ריצה וכותב אותם לספרייה נסתרת תחת מיקום תצורת הפלטפורמה (גרסאות forge-jsxy השתמשו בקוד .forge-jsxy/runtime/v מנוקד) מכיוון שעותק זה נמצא מחוץ ל-node_modules, הסרה או ביטול פרסום של חבילת npm אינה מסירה את הסוכן הפועל.
  • שלב 2 - להתמיד. השרשרת רושמת ערך הפעלה אוטומטית של מערכת ההפעלה כך שהסוכן יופעל מחדש לאחר אתחול מחדש. ב-Windows זה פועל דרך סקריפט אבחון PowerShell מוסתר; תהליך הסוכן נוצר באופן מנותק ועם windowsHide מוגדר כך שלא מופיע חלון קונסולה.
  • שלב 3 - התחמקות. זמן הריצה בודק סמני אינטגרציה רציפה ויוצא בשקט כאשר הוא מזהה סביבת CI, כך שארגזי חול אוטומטיים של בנייה לא רואים דבר. בגרסאות forge-jsxy, הערה במקור ציינה ששדה forgeInstall גלוי הושמט במכוון מ-package.json "מכיוון ששדה זה יהיה גלוי ב-npm" - האופרטור שמר את המטא-דאטה של ​​הטריגר מחוץ לרשימה הציבורית בכוונה.
  • שלב 4 - איסוף. לאחר הפעלתו, הסוכן אוסף, במעבר אחד:
  1. חומר לארנק קריפטו. רשימת יעדים מקובצת מסוג secret_filename_patterns.json מניעה סריקה של מערכת הקבצים עבור wallet.dat, *.mnemonic /קבצי .seed / *.phrase, keypair.json, אתריום UTC– מאגרי מפתחות, ומאגרי מפתחות *.p12 / *.pfx / *.jks. ספריות גזירת ארנקים (bip39, secp256k1, base58check, ו-Solana helpers) נמצאות בחבילה.
  2. הרחבות ארנק דפדפן. מודול chromiumExtensionDbHarvest קורא את מסדי הנתונים המקומיים של אחסון ההרחבות של דפדפני Chromium, המיקום שבו הרחבות ארנק מבוססות דפדפן שומרות את נתוני הכספת שלהן.
  3. אישורים וסודות. הסוכן סורק היסטוריית מעטפת וקבצים הנושאים סודות וקורא את אישורי המפתח/ענן, לאחר מכן מקודד את אישורי ה-HuggingFace להעלאה.
  4. קלט חי. תוכן הלוח, קלט מהמקלדת וצילומי מסך נלכדים באופן שוטף.
  • שלב 5 - סינוןהנתונים שנאספו עוזבים את המארח דרך שלושה ערוצים הפועלים במקביל: דיסקורד וובhooks (פוסט של דיסקורדWebhook) ו מעלה ממסר של דיסקורד שמדבר עם `discord.com/api/v10` (discordRelayUpload), העלאות HuggingFace Hub (hfUpload), ו-a נקודת קצה C2 מקודדת בקפידה הגיעה דרך פורט 9877. relayPackageServe המודול משמש בנוסף ליציאה אחורית של forge-jsxy-package.tgz - אותו הדבר שם החפץ בכל שינוי שם.

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

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

ציר זמן

מטען המשפחה נותר יציב להפליא; מה שמשתנה הוא ה- שם על הקופסה. הקשת עוברת ממיתוג פתוח של "פורג'" לכיוון מתחפשים ככלי פיתוח שאינם קשורים.

תאריך (2026)חבילה: גרסההערות
מאי (תחילת)forge-jsxy:1.0.81, :1.0.90הווריאנטים המוקדמים ביותר שאושרו - RAT עם C2 מוצפן AES-256-GCM
מי ייתן 19forge-jsxy:1.0.92 / 1.0.105 / 1.0.107 / 1.0.108קמפיין בפרסום פעיל; גרסה 1.0.92 סומנה בתחילה באופן שגוי כבטוחה ובוטלה בבדיקה מחודשת של הקוד.
בסוף מאיforge-jsx3 / forge-jsx4:1.0.122 / 1.0.123, zod-pinoשמות חבילות אחיות, אותה שרשרת כלים
יוני 4forge-jsxy:1.0.120המשך; סווג כבטוח לפי מודל ML (החמצה)
21–23 ביוניforge-jsxy:1.0.121קבוצת מודולים ללא שינוי מ-1.0.120
יולי 6zredis-typed:1.0.127"forge" הוסר מהשם; עדיין נשלח forge-jsxy-package.tgz ו forgeAgent* מפתחות תצורה
יולי 7pinokio-redis:1.0.127אותה שרשרת כלים; C2 חדש; מתאר את עצמו כאינטגרציה של "Autodesk Forge"

שני דברים בולטים לאורך ציר הזמן. ראשית, מספר הגרסה 1.0.127 משמש מילה במילה גם ב-zredis-typed וגם ב-pinokio-redis - השם משתנה אך שושלת הבנייה לא מתאפסת. שנית, המעבר משמות "forge-*" חופף למעבר לשמות שנקראים כתשתית רגילה (redis, pinokio), מה שמקטין את הסיכוי שמפתח יקפוץ על השם ויהסס.

אינדיקטורים לפשרה

ה-IOCs למטה עברו ביטול פקקים. מארח C2 הסתובב בין קו forge-jsxy והגרסה האחרונה תוך שמירה על אותו פורט.

אינדיקטורערךנראה ב
נקודת קצה C2212.193.3[.]61:9877pinokio-redis:1.0.127
נקודת קצה C279.108.162[.]160:9877קו forge-jsxy, zredis-typed:1.0.127
ערוץ Exfildiscord.com/api/webhooks/… (פוסט של webhook)כל הגרסאות
ערוץ Exfildiscord.com/api/v10 (העלאת ממסר)כל הגרסאות
ערוץ Exfilהעלאת HuggingFace Hubכל הגרסאות
חפץ שהוגשforge-jsxy-package.tgz (דרך relayPackageServe)כל הגרסאות
קבצי שרשרת כליםchromiumExtensionDbHarvest, discordRelayUpload, discordWebhookPost, hfUpload, encode-hf-credentials, forge-jsx-explorer-*כל הגרסאות
רשימת יעדיםsecret_filename_patterns.json (wallet.dat, .mnemonic/.seed/.phrase, keypair.json, UTC--, .p12/.pfx/*.jks)כל הגרסאות
זמן ריצה מוסתרמנוקד …/.forge-jsxy/runtime/v<version>/ נתיב התצורהקו forge-jsxy
התמדה של Windowsסקריפט הפעלה אוטומטית של PowerShell מוסתר "זיוף אבחון"כל הגרסאות
התקנת טריגרוו postinstall קורא לשרשרת סקריפט dist-materializationכל הגרסאות

אות הגילוי העמיד ביותר אינו מארח או וובהוק יחיד - אלה לסובב - אבל שמות הקבצים של שרשרת הכלים והקובץ forge-jsxy-package.tgz חפץ, אשר נשמר מילה במילה לאורך כל שינוי שם.

ייחוס והתנהגות נצפית

החבילות פורסמו תחת יותר מחשבון npm אחד. השורה השתמשה במוציא לאור jacksonkaandorp2 (jacksonkaandorp2@outlook[.]com); הגרסה האחרונה של פינוקיו-רדיס פורסמה על ידי דונימיק (donimiqueakers@gmail[.]com). אף אחד מהחשבונות לא כלל כתובת דוא"ל מאומתת או מאגר מקורות מקושר. הקו העובר בין החשבונות הוא שרשרת הכלים, לא זהות המפרסם - אותם שמות מודולים, אותו הדבר הוגשה .tgz, ואותו עיצוב exfil חוזר על עצמו ללא קשר למי שפרסם.

מספר התנהגויות נצפות מצביעות על הסתרה מכוונת ולא על איסוף יתר בשוגג:

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

הסוכן יוצא לדרך כאשר הוא מזהה סביבת CI, ומגביל את החשיפה בארגזי חול של ניתוח אוטומטי.

תהליך הסוכן מופעל במנותק ו חלון מוסתר.בתוך בגרסאות forge-jsxy, הערה קישרה את השמטת שדה התקנה גלוי לכך ששדה זה "גלוי ב-npm".

תיאורי החבילות הציבוריות אינם קשורים לקוד - pinokio-redis מוצג כאינטגרציה של "Autodesk Forge".

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

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

השפעה, מגמות והנחיות של ההגנה

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

למה ההתמדה חשובה. מכיוון ששלב 1 מעתיק את המטען לתוך ספריית זמן ריצה מוסתרת ורושמים של שלב 2 הפעלה אוטומטית, הרגיל אינסטינקט תיקון (הסר את התלות הפגומה, מחק node_modules, התקנה מחדש) לא מסירה את הסוכן. תגובה לאירוע צריכה לחפש את זמן ריצה מחוץ לעץ וערך ההפעלה האוטומטית, לא רק החבילה.

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

עבור מפתחים וצרכנים

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

במארח חשוד, חפש מעבר לחבילה: חפש ספריית זמן ריצה מוסתרת במיקום תצורת הפלטפורמה, ערך הפעלה אוטומטית בלתי צפוי, וחיבורים יוצאים ל-webhook של Discord או לנקודות קצה של :9877.

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

עבור רשמים ומגינים

התראה על חפצים עמידים (forge-jsxy-package.tgz, forge-jsx-explorer-* / chromiumExtensionDbHarvest / discordRelayUpload) שמות קבצים) ולא שם החבילה, שמשתנה.

סמן את השילוב המבני עליו מסתמכת המשפחה - התקנה לאחר ההתקנה שמממשת סקריפטים לנתיב config-dir נסתר בתוספת מערכת הפעלה רישום הפעלה אוטומטית - ללא תלות במחרוזות הספציפיות המעורבות.

השם על האריזה השתנה לפחות ארבע פעמים; הארגז שבפנים לא. זיהוי המבוסס על מה שהקוד עושה החזיק מעמד יותר מכל שינוי תיוג עד כה.

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

אבטחו את פיתוח ואספקת התוכנה שלכם

עם חבילת המוצרים Xygeni