במאמר הזה נתאר את מצב מחשוב מאובטח (seccomp) של Linux ב-Google Kubernetes Engine (GKE). במסמך הזה אנחנו מניחים שאתם מכירים את הנושאים הבאים:
המידע במאמר הזה יעזור לכם להבין אילו פעולות האפליקציות בקונטיינרים יכולות לבצע במכונה הווירטואלית (VM) המארחת שמגבה את הצמתים.
המסמך הזה מיועד למומחי אבטחה שמשתמשים ב-seccomp כחלק מאסטרטגיית האבטחה של הארגון, ורוצים להבין איך GKE פועל עם פרופילים של seccomp. במאמר תפקידים ומשימות נפוצים של משתמשי GKE תוכלו לקרוא מידע נוסף על תפקידים נפוצים ודוגמאות למשימות שאנחנו מתייחסים אליהן בתוכן של Google Cloud .
מה זה seccomp?
מצב מחשוב מאובטח, או seccomp, הוא יכולת אבטחה ב-Linux שמאפשרת להגביל את קריאות המערכת (syscalls) שתהליך יכול לבצע לליבת Linux.
כברירת מחדל, הצמתים של GKE משתמשים במערכת הפעלה שמותאמת לקונטיינרים עם זמן ריצה של קונטיינרים containerd. containerd מגן על ליבת Linux על ידי הגבלת היכולות המותרות של Linux לרשימת ברירת מחדל, ואפשר להגביל עוד יותר את קריאות המערכת המותרות באמצעות פרופיל seccomp. containerd כולל פרופיל seccomp שזמין כברירת מחדל. האם GKE יחיל את פרופיל seccomp שמוגדר כברירת מחדל? זה תלוי במצב האשכול שבו אתם משתמשים, באופן הבא:
- Autopilot (מומלץ): GKE מחיל באופן אוטומטי את פרופיל ברירת המחדל של containerd seccomp על כל עומסי העבודה.
- Standard: GKE לא מחיל באופן אוטומטי את פרופיל ברירת המחדל של containerd seccomp על כל עומסי העבודה. מומלץ להחיל על עומסי העבודה את פרופיל ברירת המחדל של seccomp או פרופיל seccomp בהתאמה אישית.
פרופיל ברירת המחדל של containerd seccomp מספק הקשחה בסיסית תוך שמירה על תאימות לרוב עומסי העבודה. ההגדרה המלאה של פרופיל seccomp עבור containerd זמינה ב-GitHub.
יכולות וקריאות מערכת (syscalls) ב-Linux
יכול להיות שתהליכים בלי הרשאות root שפועלים במערכות Linux ידרשו הרשאות ספציפיות כדי לבצע פעולות כמו משתמש root. ב-Linux נעשה שימוש ביכולות כדי לחלק את ההרשאות הזמינות לקבוצות, כך שתהליך שאינו root יכול לבצע פעולה ספציפית בלי לקבל את כל ההרשאות. כדי שתהליך יוכל לבצע בהצלחה קריאת מערכת ספציפית, התהליך צריך לקבל הרשאות מתאימות באמצעות יכולת.
רשימה של כל היכולות של Linux מופיעה במאמר בנושא יכולות.
קריאות המערכת שנדחות בפרופיל ברירת המחדל של GKE seccomp
פרופיל ברירת המחדל של containerd seccomp חוסם את כל קריאות המערכת ואז מאפשר באופן סלקטיבי קריאות מערכת ספציפיות, שחלקן תלויות בארכיטקטורת ה-CPU של מכונת ה-VM של הצומת ובגרסת הליבה. המשתנה syscalls בפונקציה DefaultProfile מפרט את קריאות המערכת המותרות לכל הארכיטקטורות.
פרופיל ה-seccomp שמוגדר כברירת מחדל חוסם קריאות למערכת (syscalls) שאפשר להשתמש בהן כדי לעקוף את הגבולות של בידוד הקונטיינר ולאפשר גישה מורשית לצומת או לקונטיינרים אחרים. בטבלה הבאה מתוארות כמה קריאות מערכת חשובות שפרופיל ה-seccomp שמוגדר כברירת מחדל דוחה:
| נדחו קריאות מערכת (syscalls) | |
|---|---|
mount, umount, umount2,
fsmount, mount_setattr |
הגבלת הגישה של תהליכים למערכת הקבצים של הצומת או לשינוי שלה מחוץ לגבולות של הקונטיינר. הבקשה נדחתה גם כי היכולת |
bpf |
הגבלת תהליכים מיצירת תוכניות eBPF בליבה (kernel), שיכולה להוביל להסלמת הרשאות (privilege escalation) בצומת. לדוגמה, ב-CVE-2021-3490 נעשה שימוש בקריאת המערכת |
clone, clone3, unshare |
הגבלת תהליכים כך שלא יוכלו ליצור תהליכים חדשים במרחבי שמות חדשים
שעשויים להיות מחוץ למרחב השמות המוגבל של הקונטיינר. יכול להיות שלתהליכים החדשים האלה יש הרשאות ויכולות גבוהות יותר. לדוגמה,
CVE-2022-0185
נעשה שימוש ב-syscall |
reboot |
להגביל תהליכים כך שלא יוכלו להפעיל מחדש את הצומת. הבקשה נדחתה כי היכולת |
open_by_handle_at, name_to_handle_at |
להגביל את הגישה לקבצים מחוץ לקונטיינר. הקריאות האלה למערכת שימשו באחד מניצול הפרצות המוקדמים ביותר בקונטיינר של Docker. הבקשה נדחתה גם כי היכולות
|
איך משתמשים ב-seccomp ב-GKE
באשכולות במצב Autopilot, GKE מחיל באופן אוטומטי את פרופיל ברירת המחדל של seccomp של containerd על כל עומסי העבודה. לא נדרשת פעולה נוספת. ניסיונות לבצע קריאות מערכת מוגבלות ייכשלו. ב-Autopilot אי אפשר להשתמש בפרופילי seccomp בהתאמה אישית, כי GKE מנהל את הצמתים.
באשכולות רגילים, צריך להחיל פרופיל seccomp באופן ידני. GKE לא מחיל פרופיל בשבילכם.
הפעלת seccomp באשכולות רגילים
כדי להחיל פרופיל seccomp באופן ידני, מגדירים את הקשר האבטחתי של ה-Pod או של הקונטיינר באמצעות השדה spec.securityContext.seccompProfile במפרט ה-Pod, כמו בדוגמה הבאה. מומלץ מאוד להשתמש בפרופיל seccomp לעומסי העבודה, אלא אם תרחיש השימוש מחייב שימוש בקריאות מערכת מוגבלות. אלה שני הסוגים הנתמכים של seccompProfile:
-
RuntimeDefault: פרופיל ברירת המחדל שצוין על ידי זמן הריצה של containerd. -
Localhost: הגדרה של פרופיל בהתאמה אישית.
בדוגמה הבאה של קובץ מניפסט, פרופיל ה-seccomp מוגדר לפרופיל ברירת המחדל של זמן הריצה:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
labels:
app: default-pod
spec:
replicas: 3
selector:
matchLabels:
app: default-pod
template:
metadata:
labels:
app: default-pod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: seccomp-test
image: nginx
כשפורסים את המניפסט הזה, אם קונטיינר ב-Pod מנסה לבצע קריאת מערכת (syscall) שמפרה את פרופיל ברירת המחדל של seccomp בזמן הריצה, יכול להיות שיתרחשו ב-Pod או בעומס העבודה התנהגויות לא צפויות. לדוגמה, Pod שמבצע קריאת מערכת מוגבלת במהלך ההפעלה לא יופעל. אם אפליקציה מנסה לבצע קריאת מערכת מוגבלת בזמן שה-Pod פועל, יכול להיות שתבחינו בשגיאות בקונטיינר. רמת החומרה של קריאת מערכת שנכשלה תלויה באופן שבו האפליקציה מטפלת בשגיאות.
שימוש בפרופיל seccomp בהתאמה אישית באשכולות רגילים
אם פרופיל ברירת המחדל של seccomp בזמן הריצה מגביל מדי בשביל האפליקציה (או לא מגביל מספיק), אתם יכולים להחיל פרופיל seccomp בהתאמה אישית על Pods באשכולות Standard. התהליך הזה דורש גישה למערכת הקבצים בצומת. במדריך הגבלת Syscalls של קונטיינר באמצעות seccomp מוסבר איך לטעון פרופילים מותאמים אישית של seccomp ולהשתמש בהם.
המאמרים הבאים
- שימוש ב-PodSecurityAdmission כדי לאכוף מדיניות מוגדרת מראש ברמת ה-Pod
- שימוש בשירות 'מדיניות הארגון' כדי להגדיר כללי מדיניות ברמת הפרויקט או הארגון