אתמול התגלה שמודול מרכזי ב-npm, מאגר המודולים המרכזי של node, הושחת בדרך מעניינת. למדתי על העניין הזה מפוסט של דני גרדנר מ-snyk והדיווח שלו באנגלית זמין כאן.
המודול event stream היה עד כה מודול אולטרא פופולרי של node. הוא איפשר למתכנתים לעבוד יותר בקלות עם streams. באופן אישי, לא הבנתי למה צריך אותו אבל היו אחרים שכן הצטרכו אותו. מיליונים מהם ליתר דיוק. למודול יש כשתי מיליון הורדות בשבוע. זה לא אומר ששני מיליון איש מורידים אותו בשבוע כמובן, אבל זה אומר שהוא נמצא בלא מעט בילדים ותוכנות שמורידות אותו בכל התקנה והתקנה.
מה הבעיה עם המודול הזה? שמי שמפעיל אותו, מתכנת בשם דומיניק טאר, התעייף מלתחזק את החבילה ולא עדכן אותה מספר שנים. מתכנת אחר שהכינוי שלו הוא right9ctrl, פנה לטאר, המתכנת המקורי, והציע לו עזרה בתחזוקה. טאר נתן לו הרשאות. מדובר כמובן בנוהג מקובל בתעשית הקוד הפתוח. אבל right9ctrl לא היה סתם מתכנת שרצה לעזור לתחזק את החבילה הפופולרית מטוב ליבו – מדובר היה בהאקר זדוני. הוא עשה כמה שינויים קלים והוסיף ל-dependencies את החבילה flatmap-stream. חבילה מזויפת המכילה קוד מעורבל.
קוד מעורבל למי שלא יודע הוא קוד שכתוב (לשם הדוגמה) ב base64 או משהו בסגנון ואנו עושים לו eval. אם אנו רואים כזה דבר, זה סימן שמי שעשה את זה לא רוצה שנבחין בקוד בקלות.
אותו קוד מעורבל סורק את המחשב או את השרת במטרה למצוא ארנקי ביטקוין. מה הוא עושה כשהוא מוצא את הארנק? גונב את תכולתו. לא ברור עדיין אם זה הדבר היחידי שהקוד עושה.
אחרי שההאקר הזדוני right9ctrl השתיל את הקוד, הוא הקפיץ את גרסת ה-minor של החבילה לגרסה 3.3.6. ונתן להורדות לזרום. כל מי שכיוון את ה-package.json שלו, כלומר הקובץ שמוריד מודולים לגרסה *.3 קיבל את החבילה המורעלת בכל התקנה או בילד.
כשמונה מיליון התקנות של הקוד הזדוני הזה התבצעו ללא הפרעה במשך חודשיים וחצי. עד שמשתמש בשם איירטון ספרלינג תהה מה לכל הרוחות קורה פה לאחר שזיהה את הקוד המעורבל ותהה למה הוא נמצא שם. משם הוא ומשתמשים אחרים הבינו מה קרה ודיווחו במהירות ל-npm ול-Github. הן בתורן הסירו את הגרסה הבעייתית.
מה אתם צריכים לעשות?
הדבר הראשון שצריך לעשות הוא לבדוק אם יש שימוש בחבילה הזו אצלכם. וזה לא משנה אם אתם משתמשים ב-node או מתכנתים בשפה אחרת. כיוון ש-node עוזרת בלא מעט פלטפורמות אחרות. איך בדיוק? באמצעות ה-package.json. פתחו את ה-package-lock.json שלכם וחפשו את ״event-stream״. אם אתם רואים משהו שמתאים לגרסה 3.3.6 – זה הזמן למחוק את node_modules ולהתקין מחדש.
בנוסף, אני ממליץ בחום להשתמש ב-snyk שמתריע בפניכם על בעיות כאלו ברגע שהן נוצרות.
למי שרוצה ללמוד עוד על העולם המרתק של ביטקוין וגניבות שלהם – אני ממליץ בחום רב על ההרצאה של אופיר הרפז שהתקיימה בג׳אווהסקריפט ישראל:
וזהו, תזהרו שם בחוץ 🙂
9 תגובות
תודה, מאוד חשוב.
חשוב להוסיף גם שלא מספיק לבדוק רק ב-package.json כי יכול להיות שאחת הספריות המותקנות משתמשת ב-event-stream.
עבור מי שמשתמש ב-yarn אפשר לבדוק את זה בעזרת:
yarn why event-stream
שגיאת הקלדה – היה צריך להיות package-lock.json. אבל טעיתי.
בכל מקרה התוספת של ה-yarn חשובה. תודה שהוספת!
2 נקודות מעניינות נוספות –
1. ה"האקר" לא רק פירסם את החבילה ושידרג גירסה (למרות שזה היה מספיק) – הוא גם שתל את הקוד רק בקובץ ה-minified שפורסם בשביל להקשות על הזיהוי.
2. סביר להניח שינסו לשחזר את המתודה הזאת כי היא כל כך קלה לביצוע – צריך רק לחפש חבילה פופולרית של npm שלא מתוחזקת ולבקש לעזור, נוהג סטנדרטי בקוד פתוח.
מסקנות ולקחים שצריך להטמיע –
לצמצם למינימום את הdependencies, אין שום צורך להתקין חבילה רק בשביל כמה שורות קוד.
כשמתקינים חבילה, לבדוק כמה ואיזה dependencies יש לה, כולל dependencies של dependencies של dependencies..
אם יש לכם פרוייקט קוד פתוח – לא לתת שליטה למישהו שאתם לא מכירים. אם החבילה לא מתוחזקת, לעשות לה archive בgithub ולסמן אותה deprecated בnpm.
אין צורך לתת שליטה למישהו אחר (שאתם לא מכירים), שיעשה fork ויעבוד על גירסה חדשה
היה מאמר מאוד נחמד לפני כשנה, שתיאר סיפור "דמיוני" זהה בתור הזהרה מתרחישים כאלה.
https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5
אז הוסיפו פקודה npm audit כדי לבדוק מודולים מול מאגר פרצות ידועות.
"מי שדיווח על העניין הזה הוא דני גרדנר מ-snyk והדיווח שלו באנגלית זמין כאן."
ממש לא נכון, מי שדיווח היה משתמש בגיטהאב שנתקל בזה בעקבות הודעת deprecation שקפצה עקב השימוש ב createDecipher בנוד 10, שם הפונקציה דפריקייטד.
זה קרדיט לא נכון, ספק פרסומת סמויה (כפי שניתן לראות גם בסוף הפוסט) ספק טעות בתום לב 😉
צודק, הייתי צריך לכתוב שלמדתי על העניין הזה מהפוסט (המצוין) שלו ותיקנתי. בלי שום קשר לכך שהוא משלם לי 5,000 דולר לחודש… (לא באמת) 🙂
להשלים כמה פרטים שהתבברו מאז:
החבילה הייתה מתוכננת לפגוע באופן ספציפי בשרתים של Copay, ולגנוב קריפטו-ארנקים.
ההשלכות המיידיות לציבור הרחב, כנראה, מצומצמות. ההשלכות לטווח הארוך (הערכה מחדש של שרשרת התלויות, ומודל העברת האמון) רלוונטיות מתמיד.
כתבה קצת עילגת אבל מפורטת https://arstechnica.com/information-technology/2018/11/hacker-backdoors-widely-used-open-source-software-to-steal-bitcoin/
למי שרוצה לעזור לNode.js לתת תמיכה לחבילות ולמנהלי חבילות, מוזמנים להצטרף לhttps://github.com/nodejs/package-maintenance
יש מאמר מאוד נחמד מלפני כשנה שדן בסיפור תקיפה דמיוני שמזהיר בדיוק מפני מתקפות כאלה. שווה קריאה:
https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5
לאחר מכן נוסף הכלי npm audit כדי לבדוק מודולים מול מאגר מודולים זדוניים. כמובן שזה לא יעזור אם זה עוד לא התגלה 🙂
https://docs.npmjs.com/cli/audit
יוותר פשוט לחפש ככה:
grep -irn event-stream
תודה