שורה אחת בהרשאות נתנה לסוכן הניטור גישה לכל הסודות ב-cluster: מה מצא Unit 42 ב-operator-ים של Kubernetes
בקובץ ההרשאות של רכיב ניטור שמותקן על cluster-ים של Kubernetes בארגונים גדולים יושבת שורה קצרה אחת: הרשאת קריאה על כל ה-secrets, בכל ה-namespaces, בלי הגבלה. ב-Kubernetes, ה-secrets הם המקום שבו נשמרים הדברים הרגישים באמת, סיסמאות למסדי נתונים, מפתחות API, תעודות TLS ו-token-ים של חשבונות מערכת. הרכיב הזה לא צריך כמעט אף אחד מהם. כל תפקידו הוא לאסוף מטריקות ביצועים מ-Prometheus ולהעביר אותן הלאה לניתוח.
הרכיב הוא Prometurbo, הסוכן של פלטפורמת Turbonomic של IBM, והשורה הזאת קיבלה בסוף מספר חולשה משל עצמה. מי שמצא אותה הוא ליאור יקים, חוקר ב-Unit 42 של Palo Alto Networks, והדוח שהוא פרסם ב-29 בספטמבר לא עוסק בעיקר בה. הוא עוסק בשאלה למה היא כל כך נפוצה. יקים בנה כלי שמשווה את ההרשאות של רכיבי אוטומציה כאלה מול מה שהתיעוד שלהם מבטיח שהם עושים, הריץ אותו על הקטלוג המרכזי שממנו מתקינים אותם, ומצא שמעט יותר מ-5% מהם מבקשים הרשאות שאין להם שימוש בהן, חלקם עד כדי נתיב עקיף להרשאות מנהל על ה-cluster כולו.
בהמשך נעבור על למה רכיב ניטור מחזיק מפתחות כאלה מלכתחילה, מה נמצא בשני המקרים שהדוח מפרק לפרטים, ולמה הקטלוג שממנו כולם מתקינים הוא עצמו חלק מהבעיה.
הרכיב שמנהל לכם את התשתית, ומה הוא מחזיק ביד
נניח שאתם מריצים אשכול מסדי נתונים על Kubernetes. מישהו צריך לשים לב שאחד העותקים נפל, להקים חדש במקומו, לעדכן את ההגדרות כשהן משתנות ולהחזיר את המצב למה שהוגדר שיהיה. את העבודה הזאת אף אחד לא רוצה לעשות ביד, ולכן מריצים בתוך ה-cluster לולאה שלא נגמרת: היא בודקת כל הזמן מה המצב בפועל, משווה אותו למצב שהוגדר בקבצי התצורה, ומתקנת את הפער. לרכיב שעושה את זה קוראים operator.
מבחינה טכנית מדובר בשני חלקים שעובדים יחד. הראשון הוא CRD, הרחבה של ה-API של Kubernetes שמאפשרת למפתחים להתייחס ללוגיקה שלהם, אשכול מסדי נתונים או מדיניות firewall, כאובייקט מקורי של המערכת. השני הוא ה-controller, הלולאה עצמה. כדי להריץ את הלולאה ה-controller חייב זהות משל עצמו, service account שמקושר להרשאות מוגדרות דרך מנגנון ההרשאות של Kubernetes, ה-RBAC.
וכאן נקודת המוצא של כל המחקר, והיא פשוטה: אם תוקף משתלט על operator, היקף הפריצה נקבע לפי ההרשאות שיש לו, לא לפי מה שהוא עושה בפועל. התוקף יכול להגיע לשם דרך image נגוע שהורד בשרשרת האספקה, דרך חולשה באחת התלויות שלו, או דרך השתלטות על ה-node שעליו הוא רץ. מרגע שהוא בפנים, ההרשאות הן התקרה, ו-operator שמחזיק יותר ממה שהוא צריך הוא בפועל דלת אחורית שקטה שמישהו התקין מרצונו.
שורה אחת בהרשאות, וכל הסודות ב-cluster פתוחים
כשהכלי של יקים סרק את הקטלוג הוא סימן את Prometurbo בגלל שימוש ב-wildcards בהרשאות, כלומר הרשאה שחלה על הכול במקום על משאב מסוים. הגרסה שהייתה שם, v8.6.0, היא מ-2022, ולכן החוקרים הורידו את הגרסה העדכנית מהמאגר של IBM עצמה, v8.17.6, כדי לבדוק אם המצב השתנה. הוא לא השתנה. ה-service account של הסוכן לא היה מוגבל ל-namespace שבו הוא מותקן אלא קושר ל-ClusterRole, כלומר להרשאות שתקפות על כל ה-cluster, ובתוכו חוק מפורש שנותן get, list ו-watch על משאבי ה-secrets בקבוצת ה-API המרכזית.
ההבדל הזה בין Role ל-ClusterRole הוא כל הסיפור. operator שמנהל רכיב אחד זקוק בדרך כלל לגישה לכמה secrets ספציפיים ב-namespace שלו. גישת קריאה לכל ה-secrets בכל ה-cluster מוצדקת כמעט רק אם הרכיב עצמו הוא מנהל סודות מרכזי, וסוכן שאוסף מטריקות הוא לא. לפי Unit 42, המשמעות המעשית היא שתוקף שמשתלט על הסוכן יכול מיד לעבור לחילוץ של token-ים של service account-ים בעלי הרשאות מנהל, פרטי אימות למסדי נתונים, מפתחות API ותעודות TLS מ-namespaces שאין להם שום קשר אליו. פריצה מקומית לרכיב ניטור הופכת בצעד אחד לשליטה בסביבה כולה.
יקים דיווח ל-IBM ב-5 בנובמבר 2025. IBM אישרה ב-3 בפברואר 2026 שהבעיה תוקנה, וב-24 באפריל פרסמה בולטין אבטחה רשמי עם CVE-2026-6389. הבולטין מגדיר את החולשה כניהול הרשאות לקוי (CWE-269), מפרט שהגרסאות הנגועות של סוכן prometurbo הן 8.16.0 עד 8.17.6, ושהתיקון הוא מעבר לגרסה 8.18.0. בשורת המעקפים כתוב None. אין פתרון ביניים, רק עדכון.
על הציון עצמו יש מחלוקת בין שני גופים רשמיים, וכדאי להכיר אותה. IBM נתנה 8.8 עם וקטור שמסמן Scope: Changed, כלומר שהפריצה חורגת מגבולות הרכיב שנפרץ. NVD, המאגר של NIST, חישבה ציון משל עצמה, 7.8, עם Scope: Unchanged. שני הציונים מופיעים זה לצד זה באותה רשומה. מי שסורק את הסביבה שלו עם כלי שמושך ציונים מ-NVD יראה מספר נמוך יותר ממה שהיצרן עצמו חושב.
עד כאן חולשה אחת, שדווחה ותוקנה. מה שהסקר הרחב מצא סביבה מטריד יותר.
למה הגרסה שתתקינו בקליק אחד היא כנראה הישנה
הכלי שיקים בנה, OperTraitor, פורסם כקוד פתוח. העיקרון שלו לא מתוחכם: הוא אוסף את קבצי ה-YAML הגולמיים של operator-ים, גם כאלה שמותקנים מקומית וגם כל הקטלוג הציבורי, מזין את הגדרות ה-RBAC שלהם למודל שפה שהוגדר לניתוח איומים, ומבקש ממנו להשוות בין ההרשאות שהרכיב מקבל בפועל ובין מה שהתיעוד שלו אומר שהוא עושה. הפער בין השניים מתורגם לציון סיכון בין 1 ל-10.
מה שעלה מהסריקה הוא בעיה בשרשרת האספקה, והיא מתחילה בדרך שבה אנשים מתקינים את הדברים האלה. יצרנים רבים מפרסמים את הגרסאות החדשות והמתוקנות של ה-operator-ים שלהם דרך Helm charts, דרך המאגר שלהם ב-GitHub או דרך ArtifactHub. הגרסאות הישנות, אלה שההרשאות שלהן רחבות מדי, נשארות בינתיים זמינות דרך Operator Lifecycle Manager, מנגנון ההתקנה שהוא ברירת המחדל בעולם הקוד הפתוח ובסביבות OpenShift. אין שום דבר שמסמן למשתמש שהגרסה שהוא מתקין בשלושה קליקים נזנחה לפני ארבע שנים. Prometurbo הוא בדיוק הדוגמה: בקטלוג יושבת גרסה מ-2022, בזמן שהיצרן ממשיך לפרסם במקום אחר.
החלק הפחות נוח בדוח הוא מה שקרה מול בעלי ה-operator-ים האחרים שסומנו. יקים כותב שרבים מהם לא השיבו כלל לניסיונות הגילוי האחראי, ומעריך שבמקרים לא מעטים זה פשוט אומר שהרכיב כבר לא מתוחזק. רכיב לא מתוחזק עם הרשאות רחבות שיושב בקטלוג ברירת המחדל הוא לא תקלה נקודתית, הוא משטח תקיפה קבוע. ההמלצה שעולה מכאן היא לבדוק לפני התקנה גם את ההרשאות שהרכיב מבקש וגם אם מישהו עוד מתחזק אותו.
ומה אם ההרשאות הרחבות באמת נחוצות?
המקרה השני בדוח הוא דווקא זה שמסבך את התמונה. הכלי סימן גם את ה-operator של Datadog, שמבקש גישה ל-secrets בכל ה-cluster ובנוסף פעולות על משאבי ההרשאות עצמם, ClusterRoles ו-ClusterRoleBindings. לפי Unit 42, נציגי Datadog הסבירו בתשובתם שהשמות של ה-secrets שהרכיב צריך להגיע אליהם נקבעים על ידי המשתמש, ולכן אי אפשר לדעת אותם מראש ולרשום אותם בהרשאה. החוקרים קיבלו את ההסבר וכתבו שזאת נקודה לגיטימית.
בתיעוד ההרשאות שהחברה פרסמה אפשר לראות את ההיגיון במלואו. המשאבים שה-operator מנהל מקבלים שמות שנגזרים מההגדרות של המשתמש, בתבנית כמו datadogagent-name-cluster-agent, ולכן ההרשאה לא יכולה לנקוב בשמות מסוימים. הגישה הרחבה ל-secrets בכל ה-namespaces תלויה בדגל בשם global.secretBackend.enableGlobalPermissions שברירת המחדל שלו היא false, כלומר היא נדלקת רק אם הלקוח הפעיל במפורש את התכונה שצריכה אותה.
התוצאה במקרה הזה לא הייתה תיקון קוד. Datadog בחרה לתעד בפירוט מה כל הרשאה עושה ולמה היא נדרשת, כדי שצוותי אבטחה שמעריכים את הסיכון של ה-cluster שלהם יוכלו להחליט מדעת אם הם מקבלים אותו. זה פחות מספק מ-CVE שנסגר, אבל זה הדבר הנכון כשההרשאה אמיתית: הבעיה היא לא תמיד רשלנות, לפעמים זה מתח אמיתי בין צמצום הרשאות לבין מוצר שאפשר להתקין בלי להגדיר לו ידנית כל שם משאב.
ה-operator הבא יחליט בעצמו
החלק שהדוח בנוי לקראתו הוא מה שקורה כשמכניסים מודלי שפה ללולאה הזאת. יקים מתאר שלוש תבניות שמתחילות להופיע: operator-ים שמשלימים תיקון תקלות רגיל בקריאות למודל, כמו K8sGPT; operator-ים שמשמשים צינור לסוכני AI חיצוניים, למשל דרך Model Context Protocol; ו-operator-ים שתפקידם לנהל סוכני AI בתוך ה-cluster עצמו.
בכל אחת מהן ההרשאות הרחבות משנות אופי. operator עם גישת קריאה לכל ה-secrets שהוא גם רכיב דטרמיניסטי הוא סיכון שמתממש רק אם תוקף מגיע אליו. אותו operator כשהוא מריץ החלטות של מודל הוא ישות שיכולה לקרוא מידע רגיש ב-namespaces שלא התכוונתם אליהם בלי שאף אחד תקף אותה. במקרה של גשר לסוכן חיצוני, ההרשאות של ה-operator הן בפועל ההרשאות שאתם נותנים למודל שרץ אצל מישהו אחר. "operator עם יותר מדי הרשאות היום הוא הסוכן האוטונומי והלא מבוקר של מחר", כתב יקים.
מה זה אומר בפועל
מי שמריץ Turbonomic של IBM עם סוכן prometurbo בגרסאות 8.16.0 עד 8.17.6 צריך לעלות ל-8.18.0, ולפי הבולטין של IBM אין כאן שום מעקף שקונה זמן. מעבר למוצר הספציפי הזה, שתי הבדיקות שמשתלמות הכי מהר הן לוודא שה-operator-ים שמותקנים אצלכם הגיעו מהערוץ שהיצרן מתחזק ולא מגרסה שנשארה בקטלוג, ולפתוח את קטע ה-RBAC בקבצי ה-YAML לפני ההתקנה ולשאול על כל ClusterRole אם הרכיב באמת צריך את ההרשאה הזאת על כל ה-cluster או רק ב-namespace שלו.
הדבר השלישי הוא ניטור. יומני הביקורת של Kubernetes מראים מה כל service account עשה, וההתנהגות של operator היא מהדברים הצפויים ביותר בסביבה: אותן פעולות, על אותם משאבים, בלי הפסקה. בדיוק בגלל זה חריגה בולטת. operator ניטור שמתחיל פתאום לבקש רשימה של secrets ב-namespace שאין לו שום קשר אליו הוא התראה שכדאי שתגיע למישהו.
תגובות