כדאי לעיין בדף הזה כדי להכיר את המושגים של SELinux.
בקרת גישה מחייבת
Security Enhanced Linux (SELinux) היא מערכת חובה לבקרת גישה (MAC) למערכת ההפעלה Linux. מערכת MAC שונה ממערכת בקרת הגישה (DAC) המוכרת של לינוקס. במערכת DAC, קיים מושג של בעלות, שבו הבעלים של משאב מסוים שולט בהרשאות הגישה שמשויכות אליו. בדרך כלל מדובר בהרשאות גסות שעלולות להוביל להעלאת הרשאות לא מכוונת. לעומת זאת, מערכת MAC מתייעצת עם רשות מרכזית כדי לקבל החלטה לגבי כל ניסיון גישה.
הטמענו את SELinux כחלק ממסגרת Linux Security Module (LSM), שמזהה אובייקטים שונים של ליבה ופעולות רגישות שמתבצעות בהם. בנקודה שבה כל אחת מהפעולות האלה אמורה להתבצע, נקראת פונקציית LSM hook כדי לקבוע אם הפעולה צריכה להיות מותרת על סמך המידע שמאוחסן לגביה באובייקט אבטחה אטום. SELinux מספק הטמעה של ה-hooks האלה וניהול של אובייקטי האבטחה האלה, שמשולבים עם המדיניות שלו כדי לקבוע את החלטות הגישה.
בנוסף לאמצעי אבטחה אחרים ב-Android, מדיניות בקרת הגישה של Android מגבילה מאוד את הנזק הפוטנציאלי של מכונות וחשבונות שנפרצו. שימוש בכלים כמו אמצעי הבקרה של Android לגישה לפי שיקול דעת ולגישה חובה מאפשר לכם ליצור מבנה שיבטיח שהתוכנה שלכם תפעל רק ברמת ההרשאה המינימלית. כך מצמצמים את ההשפעות של מתקפות ומפחיתים את הסיכוי שתהליכים שגויים ידחפו נתונים או אפילו ישדרו אותם.
ב-Android מגרסה 4.3 ואילך, SELinux מספקת בקרה כוללת על גישה חובה (MAC) מעל סביבות מסורתיות של בקרה על גישה לפי שיקול דעת (DAC). לדוגמה, בדרך כלל תוכנה צריכה לפעול כחשבון משתמש root כדי לכתוב למכשירים של בלוקים גולמיים. בסביבת Linux מסורתית שמבוססת על DAC, אם חשבון משתמש הבסיס נפרץ, המשתמש יכול לכתוב לכל מכשיר בלוק גולמי. עם זאת, אפשר להשתמש ב-SELinux כדי לתייג את המכשירים האלה, כך שהתהליך שהוקצתה לו הרשאת הבסיס יוכל לכתוב רק לאלה שצוינו במדיניות המשויכת. כך התהליך לא יכול לדרוס נתונים והגדרות מערכת מחוץ למכשיר הבלוק הגולמי הספציפי.
במאמר תרחישים לדוגמה אפשר למצוא עוד דוגמאות לאיומים ולדרכים להתמודד איתם באמצעות SELinux.
רמות האכיפה
אפשר להטמיע את SELinux במצבים שונים:
- Permissive (מתירנית) – מדיניות האבטחה של SELinux לא נאכפת, רק נרשמת ביומן.
- אכיפה – מדיניות האבטחה נאכפת ונרשמת ביומן. כשלים מופיעים כשגיאות EPERM.
הבחירה הזו היא בינארית וקובעת אם המדיניות תפעל או רק תאפשר לכם לאסוף נתונים על כשלים פוטנציאליים. האפשרות הזו שימושית במיוחד במהלך ההטמעה.
סוגים, מאפיינים וכללים
מערכת Android מסתמכת על רכיב Type Enforcement (TE) של SELinux לצורך המדיניות שלה. כלומר, לכל האובייקטים (כמו קובץ, תהליך או שקע) משויך סוג. לדוגמה, כברירת מחדל, סוג האפליקציה הוא untrusted_app. הסוג של תהליך נקרא גם הדומיין שלו. אפשר להוסיף הערה לסוג עם מאפיין אחד או יותר. המאפיינים שימושיים כשרוצים להתייחס לכמה סוגים בו-זמנית.
אובייקטים ממופים למחלקות (לדוגמה, קובץ, ספרייה, קישור סמלי, שקע), וסוגי הגישה השונים לכל מחלקה מיוצגים על ידי הרשאות.
לדוגמה, ההרשאה open קיימת למחלקה file. סוגים ומאפיינים מתעדכנים באופן קבוע כחלק ממדיניות SELinux של Android, אבל הרשאות ומחלקות מוגדרות באופן סטטי ומתעדכנות לעיתים רחוקות כחלק מגרסה חדשה של Linux.
כלל במדיניות מופיע בפורמט הבא:
allow source target:class permissions;
כאשר:
- מקור – הסוג (או המאפיין) של נושא הכלל. מי מבקש גישה?
- יעד – הסוג (או המאפיין) של האובייקט. למה נדרשת גישה?
- Class – סוג האובייקט (לדוגמה, קובץ, socket) שאליו מתבצעת גישה.
- הרשאות – הפעולה (או קבוצת הפעולות) (לדוגמה, קריאה, כתיבה) שמבוצעת.
דוגמה לכלל:
allow untrusted_app app_data_file:file { read write };
ההגדרה הזו מציינת שהאפליקציות יכולות לקרוא ולכתוב קבצים עם התווית app_data_file. יש סוגים אחרים של אפליקציות. לדוגמה, הקובץ isolated_app משמש לשירותי אפליקציות עם isolatedProcess=true במניפסט שלהם. במקום לחזור על הכלל עבור שני הסוגים, מערכת Android משתמשת במאפיין בשם appdomain לכל הסוגים שכוללים אפליקציות:
# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app appdomain;
# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app appdomain;
allow appdomain app_data_file:file { read write };
כשכותבים כלל שמציין שם מאפיין, השם הזה מורחב אוטומטית לרשימת הדומיינים או הסוגים שמשויכים למאפיין. חלק מהמאפיינים הבולטים הם:
-
domain– מאפיין שמשויך לכל סוגי התהליכים, -
file_type– מאפיין שמשויך לכל סוגי הקבצים.
פקודות מאקרו
בפרט כשמדובר בגישה לקבצים, יש הרבה סוגים של הרשאות שצריך לקחת בחשבון. לדוגמה, ההרשאה read לא מספיקה כדי לפתוח את הקובץ או כדי להפעיל את stat בקובץ. כדי לפשט את הגדרת הכלל, מערכת Android מספקת קבוצה של פקודות מאקרו לטיפול במקרים הנפוצים ביותר. לדוגמה, כדי לכלול את ההרשאות החסרות כמו open, אפשר לשכתב את הכלל שלמעלה כך:
allow appdomain app_data_file:file rw_file_perms;
בקבצים global_macros ו-te_macros אפשר למצוא דוגמאות נוספות למאקרו שימושיים. מומלץ להשתמש בפקודות מאקרו ככל האפשר כדי להקטין את הסיכוי לכשלים בגלל דחיות בהרשאות קשורות.
אחרי שמגדירים סוג, צריך לשייך אותו לקובץ או לתהליך שהוא מייצג. פרטים נוספים על אופן השיוך הזה מופיעים במאמר בנושא הטמעה של SELinux. מידע נוסף על כללים זמין במחברת SELinux.
הקשר וקטגוריות האבטחה
כשמבצעים ניפוי באגים במדיניות SELinux או כשמסמנים קבצים (באמצעות file_contexts או כשמבצעים ls -Z), יכול להיות שתיתקלו בהקשר אבטחה (שנקרא גם תווית). לדוגמה:
u:r:untrusted_app:s0:c15,c256,c513,c768. הפורמט של הקשר אבטחה הוא:
user:role:type:sensitivity[:categories]. בדרך כלל אפשר להתעלם מהשדות user, role ו-sensitivity של הקשר (ראו ספציפיות). השדה type
מוסבר בקטע הקודם. categories הם חלק מהתמיכה באבטחה רב-שכבתית (MLS) ב-SELinux. ב-Android מגרסה 12 ואילך, הקטגוריות משמשות ל:
- בידוד נתוני האפליקציה כך שאפליקציה אחרת לא תוכל לגשת אליהם,
- בידוד נתוני האפליקציה ממשתמש פיזי אחד למשתמש פיזי אחר.
ספציפיות
מערכת Android לא משתמשת בכל התכונות ש-SELinux מספקת. כשקוראים מסמכים חיצוניים, חשוב לזכור את הנקודות הבאות:
- רוב כללי המדיניות ב-AOSP מוגדרים באמצעות Kernel Policy Language (שפת מדיניות של ליבת מערכת ההפעלה). יש כמה חריגים לשימוש בשפת ביניים נפוצה (CIL).
- לא נעשה שימוש במשתמשים ב-SELinux. המשתמש היחיד שמוגדר הוא
u. כשצריך, משתמשים פיזיים מיוצגים באמצעות השדה categories של הקשר האבטחה. - לא נעשה שימוש בתפקידים של SELinux ובבקרת גישה מבוססת-תפקידים (RBAC). מוגדרים שני תפקידי ברירת מחדל שמשמשים את המערכת:
rלנושאים ו-object_rלאובייקטים. - לא נעשה שימוש ברגישויות של SELinux. הרגישות שמוגדרת כברירת מחדל
s0תמיד מוגדרת. - לא נעשה שימוש בערכים בוליאניים של SELinux. כשמגדירים מדיניות למכשיר, היא לא תלויה במצב המכשיר. כך קל יותר לבצע ביקורת על כללי המדיניות ולנפות באגים.