אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » פיתוח אינטרנט » פתרונות ומאמרים על פיתוח אינטרנט » אל תשתמשו ב-child_process.exec כדי להריץ פקודות ב-node שלכם

אל תשתמשו ב-child_process.exec כדי להריץ פקודות ב-node שלכם

רן בר-זיק אוקטובר 29, 2017 7:07 am תגובה אחת

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

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

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

בקוד היתה פונקציה קצת מסורבלת ולא ממש הכרחית שבדקה את שם הבראנץ'. הקוד שבתוכה נראה בערך כך:


const exec = require('child_process').execSync;
branch = exec('git symbolic-ref HEAD 2> NUL || git rev-parse --short HEAD 2> NUL');

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


...
app.get('/', (req, res) => {
  child_process.exec(
    'gzip ' + req.query.file_path);
  res.send('/* gzipped data */')
})
...

שאותו לקחתי מהדוגמה המצוינת שיש באתר hacker noon. הקוד הזה בגדול יושב לו בשרת node express ומה שהוא עושה זה לקבל פרמטר בשם file_path, לקחת את שם הקובץ שיש בו ולהחזיר אותו כקובץ zip. משהו שבהחלט אפשר לראות באתרים. המשתמש מכניס משהו כזה

: example.com/?file_path="some_image.jpg"  

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

example.com/?file_path="some_image.jpg; rm -rf /"

מה שירוץ בפועל זה:

gzip some_image.jpg; rm -rf /

כי child_process.exec יריץ את כל מה שיתנו לו כולל רווחים וכולל מה שבא לו. אז נכון, בסקריפט הקטן והחביב שלי לא היה שימוש במשתנים. אבל, וזה אבל משמעותי, למה להכניס ראש בריא למיטה חולה? ואם בעתיד אני או מישהו אחר שיתרום לשם קוד, יכניס לשם משתנים? הפתרון הטוב ביותר הוא מראש לא להכנס לפינות ומראש לא להשתמש ב-child_process.exec לשום דבר. במה כן להשתמש? למשל ב-execFile או ב-execFileSync אם אתם צריכים פעולה סינכרונית. גם כאן אנחנו יכולים להריץ איזו פקודה שבא לנו, אבל כאן כל הארגומנטים חייבים לבוא בתור מערך. תכניס רווח ותקבל error.


app.get('/', (req, res) => {
  child_process.execFileSynch('gzip', [req.query.file_path]);
  res.send('/* gzipped data */')
})
...

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

טוב, אז אנחנו כבר יודעים להשתמש ב-execFileSynch או ב-execFile. במקום ב-exec. אבל מה הפתרון האמיתי? הפתרון האמיתי הוא להשתמש כמובן ב-static code analysis, במקרה שלנו ב-eslint, על מנת להכשיל את הבילד בכל שימוש ב-exec. ניתוח קוד סטטי כזה יבטיח שאנחנו וכל מישהו אחר שיתרום אי פעם קוד לפרויקט שלנו, לא נשתמש בפונקציה שהיא בעייתית מלכתחילה. איך עושים את זה? משתמשים בתוסף של eslint בשם eslint-plugin-security למשל, או כותבים תוסף משלכם. מה שחשוב הוא זה לנסות למנוע את הבעיה מההתחלה 🙂

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
JavaScript node.js אבטחת מידע

תגובה אחת

  1. משתמש אנונימי (לא מזוהה) הגב אוגוסט 22, 2019 בשעה 7:01 pm

    הספר של לירן טל הוא בעברית?

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

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

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

גלילה לראש העמוד