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

הפוסט הבא נכתב כתשובה למישהו שאמר לי “הטרמינל קורא את השורה הראשונה בקובץ (*sh), ומחליט כיצד להריץ אותו”. והאמת היא שזה לא נכון, כי הקרנל בכבודו ובעצמו מטפל בזה.

כולנו מכירים את ה - Shebang/Hashbang) שנראה כך:

#!/usr/bin/env bash

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

$ ./script.py

במקום:

$ python script.py

אם לא תציינו את ה - Shebang, המערכת תריץ את הסקריפט שלכם כקובץ שנכתב ב - shell.

איך זה עובד?

בלינוקס המודל שמטפל במנגנון, נקרא binfmt_script, תוכלו למצוא אותו במיקום fs/binfmt_script.c.
המימוש שבודק את השורה הראשונה:

static int load_script(struct linux_binprm *bprm)
{
    const char *i_arg, *i_name;
    char *cp;
    struct file *file;
    int retval;

    if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
        return -ENOEXEC;

}

כפי שניתן לראות בקוד, המודל בודק את שני התווים הראשונים בשורה, במידה והשורה לא מתחילה ב - #! מוחזרת שגיאת ENOEXEC, וההרצה מעוברת לטרמינל שמריץ אותו כקובץ shell. במידה והסקריפט עבר את הבדיקה מתבצע ניתוח הפרמטרים והרצה בהתאם. מודל פשוט ויעיל.

אבטחה

מנגנון - Shebang מאפשר להריץ קבצים מבלי לדעת את הסיומת שלהם, אתם יכולים לכתוב קוד Python לשמור כ - readme.txt ועדין הוא ירוץ כרגיל, לכן חשוב מאוד לבדוק כל קוד שאתם מורידים מהרשת.

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