בקוד של LiteLLM יש רשימה של נתיבים שממשק הניהול בדפדפן רשאי לפנות אליהם, ובתוכה מופיע הנתיב /config. הכוונה המקורית נראית תמימה לגמרי: שהממשק יוכל להציג למי שמחובר את ההגדרות הנוכחיות של השרת. הבדיקה עצמה שואלת שאלה אחת בלבד, אם הנתיב המבוקש מתחיל באחת הרשומות ברשימה. הנתיב שכותב הגדרות חדשות לשרת נקרא /config/update, והוא מתחיל ב-/config.

מהפער הקטן הזה צומח כל השאר. חוקרי Check Point Research פרסמו ב-13 באוקטובר את הממצאים מבדיקת אבטחה שערכו ל-LiteLLM בגרסה 1.77.7, אחד משערי ה-LLM הנפוצים בעולם הארגוני. המסקנה המרכזית שלהם היא שמשתמש רשום בהרשאות הבסיסיות ביותר יכול לשנות את הגדרות הריצה של השרת כולו, ומשם להגיע לקריאת כל קובץ שהתהליך רואה, להשתלטות על חשבון המנהל, ולהרצת קוד על המכונה. בהמשך נראה למה ה-token שהדפדפן מקבל נספר אחרת מכל token אחר, מה בדיוק נפתח מתוך endpoint הגדרות יחיד, ולמה שערים מהסוג הזה כבר נמצאים תחת אש.

מה בעצם יושב בתוך שער LLM

כשאפליקציה בארגון שולחת בקשה למודל שפה, היא לרוב לא פונה ישירות ל-OpenAI או ל-Anthropic. בין השתיים יושב רכיב שמרכז את כל התנועה: הוא מחזיק את המפתחות מול כל הספקים, מחליט לאיזה מודל הולכת כל בקשה, מגביל קצב, רושם שימוש ועלויות, ומעביר בקשות לספק חלופי כשאחד מהם נופל. לרכיב הזה קוראים שער LLM. LiteLLM הוא פרויקט קוד פתוח שעושה בדיוק את זה, ולפי מחקר של Zenity Labs הוא מתקרב ל-100 מיליון הורדות בחודש.

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

למה ה-token של הדפדפן נספר אחרת

ב-LiteLLM יש endpoint-ים ניהוליים שמוגנים כמו שצריך. זה שיוצר הזמנות למשתמשים חדשים, למשל, בודק במפורש שהתפקיד של מי שפנה הוא PROXY_ADMIN לפני שהוא ממשיך. ה-endpoint שכותב הגדרות חדשות לשרת נשען רק על רכיב האימות הגנרי, זה שמוודא שהפונה מחובר, ואף פעם לא שואל מה התפקיד שלו. זאת החולשה הראשונה, והיא מתויגת CVE-2026-35029.

חסר כאן עוד חלק, כי רכיב האימות הגנרי כן מחזיק רשימת נתיבים מותרים, והוא אמור לעצור פנייה שלא במקומה. כאן נכנס לתמונה ההבדל בין שני סוגי token. כשמישהו מתחבר לממשק הניהול בדפדפן, השרת מייצר לו מפתח זמני לתוקף של 24 שעות ומשייך אותו לצוות מיוחד בשם litellm-dashboard. בשלב ההרשאות הקוד מסווג כל token לאחד משני סוגים, "ui" או "api", והקריטריון היחיד הוא אם שדה הצוות מכיל בדיוק את השם הזה. token מסוג "ui" מנותב לבדיקה המקלה, זו שמשווה קידומות מול רשימת נתיבי הממשק, במקום לבדיקה המחמירה שחלה על token של API.

ו-/config יושב ברשימה המקלה, ככל הנראה בשביל קריאת ההגדרות בלבד. כל נתיב שמתחיל כך עובר. התוצאה היא שכל מי שמחזיק סשן תקף בממשק, גם בהרשאות משתמש בסיסיות, יכול לכתוב מחדש את הגדרות השרת.

מה נפתח מתוך endpoint הגדרות אחד

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

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

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

LiteLLM תומך במה שנקרא pass-through endpoints, נתיבים שמעבירים בקשות לשירות חיצוני ויכולים לטעון מודול התאמה משלהם. בהגדרה של נתיב כזה יש שדה יעד, וכשהערך שלו מתחיל ב-s3:// או ב-gcs:// השרת מוריד את קובץ הפייתון שנמצא שם וטוען אותו כמודול. טעינת מודול בפייתון מריצה את כל הקוד שברמה העליונה שלו, עוד לפני שמישהו קרא לאיזושהי פונקציה. אז מי שיכול לכתוב הגדרות יכול להצביע על קובץ בדלי אחסון שבשליטתו ולגרום לשרת להריץ אותו. בהדגמה של Check Point הקוד שנטען רק יצר תיקייה מסמנת בתוך ה-container, כדי להוכיח את הנקודה בלי לגרום נזק, והחוקרים מציינים שבמקומו יכול לשבת כל דבר אחר.

הדלת השנייה: שדה שמפנה את הבקשה החוצה

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

יש ב-LiteLLM הגדרה שנועדה בדיוק למנוע את זה, והיא חוסמת כתובת בסיס ומפתח כשהם מופיעים ברמה העליונה של הבקשה. השדה user_config עובר במסלול קוד אחר ולא נבדק בכלל. אז הבקשה יוצאת לשרת שהתוקף בחר, ואיתה המפתחות שהשער מצרף אליה בעצמו. בניסוי של החוקרים המאזין בצד השני קיבל מפתח API של ספק מודלים שלמשתמש השולח לא הייתה אליו שום גישה. החולשה הזאת מתויגת CVE-2026-59823, ורשומת ה-NVD שלה נותנת לה 5.3, נמוך בהרבה מהראשונה.

ועל הגרסאות כדאי לדייק, כי המקורות לא אומרים בדיוק אותו דבר. Check Point כותבים שהממצאים נפתרו החל מגרסה 1.83.9. ה-advisory של הפרויקט עצמו לחולשת ההרשאות, שפורסם כבר ב-3 באפריל 2026, מגדיר כמושפעת כל גרסה שלפני 1.83.0 ואת 1.83.0 כגרסת התיקון, ורשומת ה-NVD חוזרת על אותם מספרים. גם הציון שונה בין השניים, 8.8 ב-NVD בסולם 3.1 מול 8.7 ב-advisory בסולם 4.0. מעשית ההפרש לא משנה, כי הגרסה שסוגרת גם את ה-SSRF היא 1.83.9.

מי כבר תוקף שערים כאלה

את השאלה הזאת אפשר להפסיק לנחש, כי מישהו כבר ספר. Zenity Labs פרסמו ב-30 ביוני ממצאים ממערך מלכודות דבש שחיקו תשתית AI אמיתית, ובו נרשמו קרוב ל-10,000 ניסיונות תקיפה. שתי מערכות מתוכן נוגעות ישירות ל-LiteLLM. הראשונה כוונה לחולשת הרצת קוד אחרת לגמרי, CVE-2026-40217 בציון 8.8, שפורסמה ב-10 באפריל: לפי Zenity הניסיונות הראשונים הגיעו לחיישנים תוך ימים, ולאורך שישה שבועות נספרו כ-600 בקשות משמונה כתובות IP, כשהמטענים מתקדמים מגישושים ראשוניים, דרך ניסיונות בריחה מהארגז המבודד, עד הרצת פקודות מערכת. ההתקדמות הזאת, כתבו החוקרים, נראית כמו שרשרת ניצול מתורגלת ולא כמו סריקה אקראית.

המערכה השנייה רלוונטית הרבה יותר למה ש-Check Point מצאו עכשיו. היא כוונה ל-SSRF ב-endpoint אחר של LiteLLM, זה שבודק חיבור, שעקף את התיקון המקורי לחולשה משנת 2024. Zenity ספרו שם כמעט 3,000 ניסיונות מיותר מ-20 כתובות IP, וכולם בנויים לחלץ את המפתח הראשי של השרת ואת פרטי האימות של ספקי המודלים. זאת בדיוק המטרה שאליה מגיעה החולשה שתוארה למעלה, רק דרך דלת אחרת, וכבר בהיקף של אלפי ניסיונות.

(וזאת גם לא הפעם הראשונה שהשער הזה מגיע לכאן: ביוני נכנסה לרשימת ה-KEV של CISA חולשת הרצת פקודות נוספת ב-LiteLLM, CVE-2026-42271, שסקרנו יחד עם החולשה ב-Starlette ששורשרה אליה.)

התמונה שמצטיירת משלושת הדוחות דומה, והיא גם המסקנה של Check Point עצמם. אף אחת מהחולשות שתוארו כאן אינה סוג תקיפה חדש: בדיקת הרשאות חסרה, נתיב קובץ שלא מאומת, טעינת מודול ממקור מרוחק ושמירת סיסמאות בגיבוב בודד בלי מלח הן בעיות מוכרות עם פתרונות מוכרים. "קצב החדשנות לא יכול לבוא על חשבון עקרונות אבטחה בסיסיים", כתבו החוקרים.

מה זה אומר בפועל

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