דילוג לתוכן
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

הרשאות ב-Linux: משתמשים, קבוצות, chmod ו-umask

בעלים וקבוצות ב-Linux, ביטי rwx,‏ chmod,‏ umask ו-setuid, עם מעבדה שבודקת גישה כמשתמש שני ומוצאת הרשאות קבצים מסוכנות.

מתחילים10 דקות קריאהמאת NotHoly

הרשאות Linux קובעות מי יכול לקרוא, לשנות ולהריץ כל קובץ במערכת. רוב הבעיות שעולות בסקירת אבטחה הן לא אקספלויטים אקזוטיים. הן קובץ קונפיגורציה שכל חשבון מקומי יכול לכתוב אליו, סקריפט ששירות root מריץ אבל משתמש רגיל יכול לערוך, או בינארי עם ביט setuid שאיש לא זוכר שהוסיף. המאמר הזה בונה את המנגנון מלמטה למעלה: בעלים, קבוצות, ביטי rwx, ‏chmod, ‏umask והביטים המיוחדים שהכי חשובים בסקירה. יוצרים קבצים, משנים את ההרשאות שלהם, בודקים גישה כמשתמש מקומי שני ב-VM של מעבדה ומחפשים הרשאות מסוכנות.

הרעיון המרכזי הוא הרשאה מינימלית. לתהליך צריכה להיות רק הגישה שהוא צריך, ורק האנשים והתוכנות שאמורים לשנות קובץ צריכים הרשאת כתיבה אליו. הרשאות קבצים הן המקום הראשון שבו Linux אוכף את הכלל הזה, ולכן הן הדבר הראשון שבודקים.

מהי הרשאת קובץ

כל קובץ ותיקייה נושאים שלושה דברים שקובעים גישה:

  1. בעלים, חשבון משתמש אחד.
  2. קבוצה, חשבון קבוצה אחד.
  3. מצב (mode), קבוצת ביטים שאומרת מה הבעלים, הקבוצה וכל השאר רשאים לעשות.

מריצים את זה על כל קובץ בתיקיית הבית:

bash
ls -l notes.txt

התו הראשון הוא סוג הקובץ (- הוא קובץ רגיל, d הוא תיקייה, l הוא קישור סמלי). תשעת התווים הבאים הם ההרשאות. שמות הבעלים והקבוצה באים אחרי מספר הקישורים.

הליבה בודקת הרשאות בכל פעם שתהליך פותח קובץ. shell, שרת web ו-cron job עוברים כולם את אותה בדיקה. אם הבדיקה נכשלת, מתקבל Permission denied. למערכת הקבצים לא משנה אם התהליך מהימן.

בעלים, קבוצות וכל השאר

בהרשאות יש שלוש שלישיות, אחת לכל סוג משתמש:

  • User (u): החשבון שמחזיק בקובץ.
  • Group (g): חברי הקבוצה שמחזיקה בקובץ.
  • Other (o): כל חשבון שאינו הבעלים ואינו חבר בקבוצה.

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

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

bash
id
groups

שינוי בחברות בקבוצה נכנס בדרך כלל לתוקף בהתחברות הבאה, ולא ב-shell שבו הורצה הפקודה.

קריאת ביטי rwx

כל שלישייה מחזיקה שלושה ביטים:

ביט על קובץ רגיל על תיקייה
r (קריאה, ערך 4) קריאת התוכן הצגת השמות שבפנים
w (כתיבה, ערך 2) שינוי התוכן יצירה, שינוי שם או מחיקה של רשומות
x (הרצה, ערך 1) הרצה כתוכנית כניסה לתיקייה והגעה לרשומות שלה

שתי נקודות מכשילות מתחילים.

ראשית, הביט x של תיקייה הוא מה שמאפשר לעבור דרכה. תיקייה עם r בלי x מאפשרת לראות שמות אבל לא לפתוח אותם. תיקייה עם x בלי r מאפשרת לפתוח קובץ ששמו המדויק כבר ידוע, אבל לא להציג את התיקייה.

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

כתיב סמלי ואוקטלי

chmod מקבל שני כתיבים לאותו דבר.

אוקטלי. כל שלישייה הופכת לספרה אחת, סכום הביטים שלה: r הוא 4, w הוא 2, x הוא 1. לכן rw- הוא 6, r-- הוא 4, r-x הוא 5 ואילו rwx הוא 7. המצב 644 פירושו קריאה וכתיבה לבעלים (6), קריאה לקבוצה (4), קריאה לאחרים (4). המצב 600 פירושו שרק הבעלים יכול לקרוא או לכתוב.

סמלי. נוקבים בסוג, באופרטור ובביטים:

  • סוגים: u (בעלים), g (קבוצה), o (אחרים), a (כולם). בלי סוג, ההנחה היא a, אלא שביטי umask נשארים ללא שינוי.
  • אופרטורים: + מוסיף ביטים, - מסיר אותם, = קובע בדיוק את הביטים האלה בסוג ומאפס את השאר.

לכן chmod u=rw,go=r notes.txt נותן את אותה תוצאה כמו chmod 644 notes.txt. chmod g+w notes.txt מוסיף כתיבה לקבוצה ומשאיר את שאר הביטים כמו שהם.

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

chmod שלב אחר שלב

chmod משנה את ההרשאות. רק הבעלים של קובץ או root יכולים להריץ את הפקודה עליו בהצלחה. כל אחד אחר מקבל Operation not permitted.

הרגל בטוח הוא לקרוא את ההרשאות, לשנות אותן ולקרוא שוב:

bash
stat -c '%a %A %U:%G %n' notes.txt
chmod 600 notes.txt
stat -c '%a %A %U:%G %n' notes.txt

stat -c מדפיס את המצב האוקטלי (%a), המצב הסמלי (%A), שמות הבעלים והקבוצה (%U, %G) ואת שם הקובץ (%n). הפורמט הזה משמש לאורך כל המעבדה.

chown משנה את הבעלים, ואת הקבוצה משנה chgrp. שינוי בעלות למשתמש אחר דורש בדרך כלל root. לא מריצים chown -R על עץ לפני שמציגים במה הוא ייגע.

umask: הרשאות ברירת מחדל לקבצים חדשים

כשתוכנית יוצרת קובץ, היא מבקשת מצב התחלתי. לקובץ רגיל הערך ההתחלתי הוא 666. לתיקייה הוא 777. ה-umask מסיר ביטים מהערך ההתחלתי הזה. ה-shell קובע אותו, וכל קובץ ותיקייה שה-shell ותהליכי הבן שלו יוצרים עוברים דרכו.

ברוב הפצות Linux ברירת המחדל היא 022. בקובץ, 666 פחות 022 הוא 644, כך שקבצים חדשים הם rw-r--r--. בתיקייה, 777 פחות 022 הוא 755, כך שתיקיות חדשות הן rwxr-xr-x. ה-umask רק מסיר הרשאות. מצב לא יכול להיות מתירני יותר מהערך ההתחלתי.

בודקים את הערך שלך:

bash
umask

umask מחמיר יותר כמו 077 נותן קבצי 600 ותיקיות 700, שרק הבעלים יכול לגשת אליהם. רופף יותר כמו 002 נותן קבצי 664 ותיקיות 775, שהקבוצה יכולה לכתוב אליהם. umask שמוגדר בפרופיל shell משפיע על ה-shell הזה ועל תהליכי הבן שלו. הוא לא משנה קבצים שכבר קיימים.

setuid, ‏setgid וה-sticky bit

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

  • setuid (4000): כשקובץ הרצה רץ, הוא רץ עם מזהה המשתמש של בעל הקובץ ולא של מי שקרא לו. בינארי בבעלות root עם setuid רץ כ-root.
  • setgid (2000): על קובץ הרצה, הוא רץ עם מזהה הקבוצה של הקובץ. על תיקייה, רשומות חדשות יורשות את הקבוצה של התיקייה.
  • sticky (1000): על תיקייה, רק הבעלים של רשומה או root יכולים לשנות את שמה או למחוק אותה, גם אם כולם יכולים לכתוב לתיקייה. /tmp היא הדוגמה הקלאסית.

ls -l מציג setuid בתור s במיקום ההרצה של הבעלים, ו-sticky בתור t במיקום ההרצה של האחרים. ב-Ubuntu 24.04 השורה של passwd נראית כך:

text
-rwsr-xr-x 1 root root 64152 May 30  2024 /usr/bin/passwd

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

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

מעבדה מעשית: קבצים והרשאות

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

יצירה ובחינה של קובץ

bash
mkdir ~/permlab && cd ~/permlab
echo 'lab secret' > notes.txt && ls -l notes.txt

ב-Ubuntu 24.04 תחת WSL, הקובץ החדש הציג -rw-r--r-- עם בעלים וקבוצה בשם החשבון. שם המשתמש, התאריך והקבוצה אצלך יהיו שונים. משווים את ההרשאות.

שינוי ההרשאות

bash
chmod 600 notes.txt && stat -c '%a %U:%G %n' notes.txt
umask

הפלט שהתקבל:

text
600 usurio:usurio notes.txt
0022

שם החשבון אצלך יהיה שונה. 600 פירושו שרק הבעלים יכול לקרוא ולכתוב. 0022 הוא ה-umask ב-shell הנוכחי, והאפס המוביל הוא חלק מהצורה האוקטלית.

עכשיו תיקייה:

bash
mkdir sub && chmod 750 sub && stat -c '%a %n' sub

התקבל: 750 sub. לבעלים יש גישה מלאה, הקבוצה יכולה לקרוא ולהיכנס, ולמשתמשים אחרים אין כלום.

שינויים סמליים, אחד בכל פעם, עם קריאה אחרי כל אחד:

bash
chmod u=rw,go=r notes.txt && stat -c '%a %A %n' notes.txt
chmod g+w notes.txt && stat -c '%a %A %n' notes.txt
chmod o-r notes.txt && stat -c '%a %A %n' notes.txt

התקבל:

text
644 -rw-r--r-- notes.txt
664 -rw-rw-r-- notes.txt
660 -rw-rw---- notes.txt

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

איך umask משנה קבצים חדשים

מריצים umask ב-subshell כדי שהשינוי לא יישאר בסשן שלך:

bash
(umask 077; touch private.txt; stat -c '%a %A %n' private.txt)
(umask 002; touch shared.txt; mkdir made_dir; stat -c '%a %A %n' shared.txt made_dir)

התקבל:

text
600 -rw------- private.txt
664 -rw-rw-r-- shared.txt
775 drwxrwxr-x made_dir

עם 077, הקובץ איבד כל ביט של קבוצה ושל אחרים. עם 002, הקבוצה קיבלה כתיבה גם על הקובץ וגם על התיקייה. התיקייה התחילה בערך 777 ואיבדה רק 002.

בדיקת גישה כמשתמש מקומי שני

השלב הזה צריך חשבון שאפשר ליצור ב-VM שלך. מריצים אותו רק שם.

bash
sudo useradd -m labuser
sudo -u labuser cat ~/permlab/notes.txt

לא הרצתי את הפקודות האלה. חשבון ה-WSL צריך סיסמה עבור sudo, ולא הזנתי כזאת. מה לחפש: עם מצב 600, הפקודה השנייה אמורה להיכשל בהודעת Permission denied, כי labuser הוא לא הבעלים ולא בקבוצה.

בשלב הבא מרחיבים את הרשאות הקובץ עבור אחרים:

bash
chmod 644 notes.txt
sudo -u labuser cat ~/permlab/notes.txt

מה לחפש: התוכן מודפס רק אם labuser יכול גם להיכנס לתיקיית הבית שלך וגם לתיקייה ~/permlab. הפצות רבות יוצרות תיקיות בית במצב 755, אבל חלקן במצב 750. אם תיקיית אב מונעת x ממשתמשים אחרים, הקריאה עדיין נכשלת, גם עם קובץ קריא. בודקים עם ls -ld ~ ~/permlab. בהתקנת Ubuntu 24.04 ב-WSL שבה השתמשתי, ls -ld ~ הדפיס drwxr-x---, כלומר 750, ולכן משתמש שני היה נחסם שם גם אחרי chmod 644. זה הביט x של תיקייה שתואר קודם, בפועל.

חיפוש הרשאות מסוכנות

מציגים קבצים רגילים שכל אחד יכול לכתוב אליהם תחת תיקיית הבית, בלי לחצות למערכות קבצים אחרות:

bash
find ~ -xdev -type f -perm -o+w 2>/dev/null

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

bash
chmod 666 ~/permlab/notes.txt
find ~ -xdev -type f -perm -o+w 2>/dev/null
chmod 644 ~/permlab/notes.txt

התקבל: החיפוש הראשון הדפיס /home/usurio/permlab/notes.txt. אחרי התיקון, אותו חיפוש לא הדפיס כלום.

מציגים בינאריי setuid בתיקיית מערכת:

bash
find /usr/bin -perm -4000 -type f 2>/dev/null | sort

ב-Ubuntu 24.04 תחת WSL התקבלו עשרה קבצים, כולל /usr/bin/passwd, /usr/bin/sudo, /usr/bin/su, /usr/bin/mount וגם /usr/bin/umount. הרשימה אצלך תלויה בהפצה ובחבילות המותקנות. בסקירה משווים את הרשימה למה שמנהל החבילות אומר שאמור להיות setuid. רשומה לא צפויה היא שאלה שצריך לענות עליה, ולא הוכחה לתקיפה.

בודקים את ה-sticky bit על תיקיות זמניות:

bash
stat -c '%a %A %n' /tmp /var/tmp

התקבל: 1777 drwxrwxrwt בשתיהן. האות t אומרת שמשתמשים יכולים ליצור שם קבצים אבל לא למחוק קבצים ששייכים למישהו אחר.

ניקוי

bash
rm -rf ~/permlab
sudo userdel -r labuser

userdel -r מוחק גם את תיקיית הבית של החשבון. מריצים אותו רק עבור חשבון המעבדה שנוצר.

מה הבדיקה ב-Windows הראתה

אותם צעדים ראשונים ב-Git Bash ל-Windows לא התנהגו כמו Linux. אחרי chmod 600 notes.txt, ‏stat עדיין דיווח 644, וקריאות chmod מאוחרות יותר לא שינו גם הן את הפלט. Windows שומר גישה ברשימות בקרת גישה של NTFS, ו-Git Bash ממפה רק חלק מהביטים. מעבדת Windows יכולה ללמד את הפקודות, אבל לא להראות מה מצב של Linux עושה. למאמר הזה משתמשים ב-WSL עם הפצת Linux, או ב-VM.

טעויות נפוצות

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

שכחת התיקייה. קובץ קריא עדיין יכול להיות בלתי נגיש אם לתיקיית אב אין x עבור המשתמש. בודקים כל תיקייה בנתיב.

שימוש בפקודה chmod -R על עץ שלם. שינויים רקורסיביים מגדירים לעיתים קרובות הרצה על קבצים רגילים או מסירים אותה מתיקיות. משתמשים בפקודה find עם -type f או -type d כדי לכוון לסוג אחד.

אמון בהרשאות של קובץ שהועתק. cp, ‏tar וכלי ארכיון עשויים לשמור או לאפס הרשאות לפי דגלים. בודקים את התוצאה עם stat.

קריאה של מצבים סמליים כמוחלטים. chmod g+w מוסיף ביט אחד. chmod g=w מאפס קריאה והרצה לקבוצה. קל לפספס את ההבדל.

קפיצה ל-root קודם. בעיות קריאה וכתיבה רבות נפתרות עם חברות בקבוצה או מצב תיקייה, ולא עם תוכנית עזר setuid או shell של root.

למה זה חשוב בסקירות אבטחה

סקירת הרשאות מתחילה בשאלה אחת: מי יכול לשנות את מה שתהליך בעל הרשאות קורא או מריץ? שלושה ממצאים חוזרים שוב ושוב:

  1. קבצים פתוחים לכתיבה בנתיב של תהליך בעל הרשאות. קונפיגורציה או סקריפט ששירות root קורא וחשבון רגיל יכול לכתוב אליהם הם הסלמה שמחכה לעריכה.
  2. בינאריי setuid או setgid לא צפויים. כל אחד מהם הוא קוד שרץ עם יותר הרשאות ממי שקרא לו. משווים את הרשימה לקו בסיס.
  3. תיקיות פתוחות לכתיבה בנתיב חיפוש או בתיקיית שירות. משתמש שיכול ליצור קובץ או לשנות שם של קובץ שם יכול להחליף קובץ מהימן, גם אם הקובץ עצמו נעול.

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

איך ממשיכים

כשההרשאות הבסיסיות ברורות, לומדים רשימות בקרת גישה עם getfacl ועם setfacl, שמוסיפות רשומות לכל משתמש מעבר לבעלים, לקבוצה ולאחרים. קוראים את המדריך של chattr על דגלי immutable ו-append-only. namei -l /path/to/file מדפיס את ההרשאות של כל רכיב בנתיב. זו הדרך המהירה ביותר למצוא את התיקייה שחוסמת שירות.

להרגלי ה-shell שמאחורי הפקודות האלה, מתחילים מהמאמר הקודם של מדריך השטח על יסודות Bash לסטודנטים לאבטחה. המאמר הבא, מה זה SSH ואיך מפתחות SSH עובדים, עוסק במפתחות SSH, שתלויים באותן הרשאות: קובץ המפתח הפרטי חייב להיות קריא רק לבעלים שלו, ולקוח SSH מסרב להשתמש במפתח שההרשאות שלו פתוחות מדי.

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

מקורות

מקורות

  1. GNU Coreutils manual: File permissions
  2. chmod(1) manual page, Linux man-pages
  3. umask(2) manual page, Linux man-pages
  4. chmod, POSIX.1-2024 utility specification (The Open Group)

עוד בנושא Linux וכלי פיתוח

Linux וכלי פיתוח

יסודות Bash לעבודת אבטחה

pipes, הפניות, משתנים, לולאות, קודי יציאה ו-set -euo pipefail, ואז שימוש בהם כדי לספור התחברויות כושלות ולחשב hash לתיקייה.

מתחילים11 דקות קריאה