במאמר הזה מתואר מצב האבטחה של מחשוב (seccomp) ב-Linux ב-Google Kubernetes Engine (GKE). במסמך הזה אנחנו מניחים שאתם יודעים את הפרטים הבאים:
המידע במסמך הזה יעזור לכם להבין אילו פעולות האפליקציות בקונטיינרים יכולות לבצע במכונה הווירטואלית (VM) המארחת שמגבה את הצמתים.
המסמך הזה מיועד למומחי אבטחה שמשתמשים ב-seccomp כחלק מאסטרטגיית האבטחה של הארגון שלהם, ורוצים להבין איך GKE פועל עם פרופילי seccomp. מידע נוסף על תפקידים נפוצים ועל משימות לדוגמה שאנחנו מתייחסים אליהן ב Cloud de Confiance by S3NS תוכן, זמין במאמר תפקידים נפוצים של משתמשים ומשימות ב-GKE.
מה זה seccomp?
מצב מחשוב מאובטח, או seccomp, הוא יכולת אבטחה ב-Linux שמאפשרת להגביל את קריאות המערכת (syscalls) שתהליך יכול לבצע לליבת Linux.
כברירת מחדל, צמתי GKE משתמשים במערכת הפעלה שמותאמת לקונטיינרים עם זמן ריצה של קונטיינרים מסוג containerd. כדי להגן על ליבת Linux, containerd מגביל את היכולות המותרות של Linux לרשימת ברירת מחדל, ואפשר להגביל עוד יותר את קריאות המערכת המותרות באמצעות פרופיל seccomp. יש ל-containerd פרופיל seccomp שזמין כברירת מחדל. האם GKE יחיל בשבילכם את פרופיל ברירת המחדל של seccomp? התשובה תלויה במצב האשכול שבו אתם משתמשים, באופן הבא:
- Autopilot (מומלץ): GKE מחיל את פרופיל ברירת המחדל של containerd seccomp על כל עומסי העבודה באופן אוטומטי.
- Standard: GKE לא מחיל באופן אוטומטי את פרופיל ברירת המחדל של containerd seccomp על כל עומסי העבודה. מומלץ להחיל על עומסי העבודה את פרופיל ברירת המחדל של seccomp או פרופיל seccomp מותאם אישית.
פרופיל ברירת המחדל של containerd seccomp מספק אבטחה בסיסית תוך שמירה על תאימות לרוב עומסי העבודה. ההגדרה המלאה של פרופיל seccomp עבור containerd זמינה ב-GitHub.
יכולות וקריאות מערכת ב-Linux
תהליכים בלי הרשאות root שפועלים במערכות Linux עשויים לדרוש הרשאות ספציפיות כדי לבצע פעולות בתור משתמש root. ב-Linux נעשה שימוש ביכולות כדי לחלק את ההרשאות הזמינות לקבוצות, כך שתהליך שאינו root יכול לבצע פעולה ספציפית בלי לקבל את כל ההרשאות. כדי שתהליך יוכל לבצע קריאת מערכת ספציפית בהצלחה, התהליך צריך לקבל הרשאות מתאימות באמצעות יכולת.
רשימה של כל היכולות של Linux מופיעה במאמר בנושא יכולות.
נדחות קריאות מערכת בפרופיל ברירת המחדל של GKE seccomp
פרופיל ברירת המחדל של containerd seccomp חוסם את כל קריאות המערכת (syscalls) ואז מאפשר באופן סלקטיבי קריאות מערכת ספציפיות, שחלקן תלויות בארכיטקטורת ה-CPU של מכונת ה-VM של הצומת ובגרסת הליבה. המשתנה syscalls בפונקציה DefaultProfile מפרט את קריאות המערכת המותרות לכל הארכיטקטורות.
פרופיל seccomp שמוגדר כברירת מחדל חוסם קריאות למערכת (syscalls) שאפשר להשתמש בהן כדי לעקוף את גבולות הבידוד של הקונטיינר ולאפשר גישה מורשית לצומת או לקונטיינרים אחרים. בטבלה הבאה מתוארות כמה קריאות מערכת משמעותיות שפרופיל ברירת המחדל של seccomp דוחה:
| קריאות מערכת שנדחו | |
|---|---|
mount, umount, umount2,
fsmount, mount_setattr |
הגבלת הגישה של תהליכים למערכת הקבצים של הצומת או לשינוי שלה מחוץ לגבולות של הקונטיינר. הבקשה נדחתה גם כי היכולת |
bpf |
הגבלת תהליכים מיצירת תוכניות eBPF בליבה (kernel), מה שעלול להוביל להסלמת הרשאות (privilege escalation) בצומת. לדוגמה,
CVE-2021-3490
השתמש ב-syscall |
clone, clone3, unshare |
הגבלת תהליכים כך שלא יוכלו ליצור תהליכים חדשים במרחבי שמות חדשים
שעשויים להיות מחוץ למרחב השמות המוגבל של הקונטיינר. יכול להיות שלתהליכים החדשים האלה יש הרשאות ויכולות מתקדמות. לדוגמה,
ב-CVE-2022-0185
נעשה שימוש ב-syscall |
reboot |
הגבלת תהליכים מהפעלה מחדש של הצומת. הגישה נדחתה כי היכולת |
open_by_handle_at, name_to_handle_at |
הגבלת הגישה לקבצים מחוץ למאגר. הקריאות האלה למערכת
שימשו באחד מהניצולים הראשונים של פירצות בקונטיינר Docker. הגישה נדחתה גם כי היכולת |
איך משתמשים ב-seccomp ב-GKE
באשכולות Autopilot, GKE מחיל באופן אוטומטי את פרופיל ברירת המחדל של containerd seccomp על כל עומסי העבודה. לא נדרשת פעולה נוספת. ניסיונות לבצע קריאות מערכת מוגבלות נכשלים. ב-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 באשכולות רגילים. התהליך הזה דורש גישה למערכת הקבצים בצומת. הדרכה על טעינה ושימוש בפרופילי seccomp בהתאמה אישית זמינה במאמר הגבלת קריאות המערכת של קונטיינר באמצעות seccomp.
המאמרים הבאים
- שימוש ב-PodSecurityAdmission כדי לאכוף מדיניות מוגדרת מראש ברמת ה-Pod
- שימוש בשירות Organization Policy Service להגדרת כללי מדיניות ברמת הפרויקט או ברמת הארגון