WEBA

הקומיט הזדוני נבלם ב-Git ולא הגיע למאגר npm של Zod

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

513 מילים16 עובדות אומתו

השמועות על השבתת חצי מהאינטרנט שוב הקדימו את המציאות. הבוקר התמלאו הפידים בדיווחים בהולים על כך שספריית הוולידציה הפופולרית Zod נפרצה, ושגרסה 4.6.6 כוללת נוזקה מסוכנת שגונבת מפתחות ומריצה קוד מרוחק. מפתחי TypeScript רבים כבר מיהרו לבדוק גיבויים, אבל אפשר להירגע: הקוד הזדוני נבלם ברמת ה-Git ולא הופץ מעולם כגרסה רשמית למאגר npm הציבורי. שום שרת פרודקשן לא נדבק מהתקנה רגילה, ואין שום סיבה לרוץ ולבצע שנמוך גרסאות בהול.

האירוע הזה אמיתי לגמרי ברמת הכוונה, אך כושל ברמת הביצוע. קומיט d821685 אכן נדחף ישירות למאגר colinhacks/zod תחת הכותרת התמימה Fix bugs and improve performance. התוקף ניצל הרשאות דחיפה כדי להעלות את מספרי הגרסאות בקובצי ה-JSON מ-4.6.5 ל-4.6.6. התקרית הזו הייתה חלק מגל רחב יותר שפגע בחבילות נוספות כמו nub ו-standard-schema, אבל ב-Zod שרשרת ההפצה החזיקה מעמד.

אזעקת שווא בשרשרת האספקה

מה שניסה התוקף לעשות היה מתוחכם על הנייר. בתוך השינויים שנדחפו למאגר GitHub של Zod, נוסף לקובצי ה-package.json הוק מסוג preinstall שהריץ קובץ חדש בשם meta.test.mjs. הרעיון ברור: ברגע שמפתח או שרת CI מריצים פקודת התקנה, הסקריפט מופעל אוטומטית עוד לפני שהספרייה עצמה נטענת לפרויקט.

מי שלא מושך קוד מענפי פיתוח לא נפגע.

נוזקה בחסות הבלוקצ'יין

החלק המעניין באמת בקוד הזדוני שנחשף ב-meta.test.mjs הוא השימוש בבלוקצ'יין כמנגנון פיקוד ושליטה. במקום לפנות לשרת C2 רגיל שקל לחסום ברמת ה-DNS, הסקריפט ביצע קריאות RPC לצמתים ציבוריים של Ethereum, בהם שירותים מוכרים כמו Cloudflare ו-llamarpc. הקריאה פנתה לחוזה חכם בכתובת ייעודית באמצעות הפונקציה eth_call כדי לשלוף נתונים מוצפנים.

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

a version bump on main publishes nothing by itself; a maintainer runs gh workflow run release.yml and approves the npm environmentהערת התיעוד המקורית שנמחקה בקובץ release.yml

ההבדל בין Git לרישום

המחסום שהכשיל את המתקפה היה תהליך האוטומציה. כפי שמופיע בבירור בהיסטוריית ה-diff ב-release.yml, תהליך השחרור של Zod לא מפרסם חבילות רק בגלל שדחפתם קוד ל-main. התוקף ניסה לשנות את קובץ ה-workflow כדי שדחיפה לענף הראשי תפעיל פרסום אוטומטי ל-npm, אבל השינוי הזה לא עזר לו לעקוף את מנגנון האישור הידני והסביבה המאובטחת.

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

חבילה נקייה כבר שוחררה לכולם.

מה צריך לבדוק עכשיו

אם אתם מנהלים פרויקטים בסביבת Node.js או TypeScript, הבדיקה שלכם פשוטה ומהירה. פתחו את קובץ package.json וודאו שהתלות של Zod מוגדרת מול מספר גרסה רשמי ולא מושכת קוד ישירות מכתובת URL של GitHub או מענף main. כל עוד החבילות מגיעות ישירות מ-npm, המערכות שלכם בטוחות לחלוטין.

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

מה לעשות עכשיובדקו שקובץ ה-package.json מושך את Zod מ-npm ולא ממאגר ה-Git ישירות, והמשיכו לעבוד כרגיל.

מקורות

  • Zod 4.6.6 compromised by malware?https://github.com/colinhacks/zod/commit/d821685ea6732436fcdf786a81d076958471e467
  • release.ymlhttps://github.com/colinhacks/zod/commit/d821685ea6732436fcdf786a81d076958471e467#diff-87db21a973eed4fef5f32b267aa60fcee5cbdf03c67fafdc2a9b553bb0b15f34
  • meta.test.mjshttps://github.com/colinhacks/zod/commit/d821685ea6732436fcdf786a81d076958471e467#diff-5acedd97e07708c715d41def1f6fea2b2dc7b126a06d71786130d28b1db4398d
  • GitHubhttps://weba.co.il/tools/github/
  • JSONhttps://weba.co.il/glossary/json/

הידיעה נכתבה מהמקורות שלמעלה בתאריך הפרסום, וכל טענה בה נבדקה מולם. מצאתם טעות? כתבו.

מה שואלים על זה

האם צריך לעדכן או לשנמך את גרסת Zod בפרויקט?

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

איך הנוזקה ניסתה להשתמש ברשת Ethereum כדי לתקוף?

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

באילו מקרים פרויקט בכל זאת עלול להיות חשוף לפגיעה?

הפרויקטים אינם חשופים לפגיעה בהתקנה רגילה. יתרה מזאת, גם אם תלות הוגדרה למשוך ישירות את הקומיט הזדוני מ-Git, סקריפט ה-preinstall לא היה רץ כיוון שהתוקף הכניס את השדה ברמה הראשית של קובץ package.json במקום תחת האובייקט scripts.