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

מה החולשה?

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

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

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

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

הסיווג הוא CWE-918, ובסולם CVSS 4.0 הפרופיל צנוע ביחס לסיפור: נדרשת הרשאה, הפגיעה בסודיות מסומנת נמוכה, והשלמות והזמינות אפס. התוקף מציץ, הוא אינו משנה ואינו מפיל. מה שהציון אינו מודד הוא לאן ההצצה מגיעה, וזה תלוי לגמרי בשאלה מה יש ברשת שבה השרת יושב.

מי מושפע?

כל גרסה לפני 1.83.9. הגרסה המתוקנת היא 1.83.9.

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

השאלה המעשית אינה אם אתם מריצים LiteLLM, אלא למי יש מפתח ומה שכן ברשת של השרת.

האם מנוצלת בפועל?

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

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

מה עושים?

1. עדכנו ל-1.83.9 ומעלה. זו הגרסה שבה הבדיקה מכסה גם את התוכן של user_config.
2. עד לעדכון, התייחסו לכל מפתח תקף כאל גישה אל הרשת שבה השרת יושב. אם הרשת הזאת מכילה שירותים פנימיים שאין להם אימות משל עצמם, זו החשיפה בפועל.
3. הגבילו את התנועה היוצאת מהשרת. אם השרת צריך לדבר רק עם ספקי מודלים חיצוניים, חסמו ממנו גישה לכתובות פנימיות. זה מצמצם את מה שחולשה מהסוג הזה שווה, גם בפעם הבאה.
4. עברו על היומנים וחפשו בקשות שבגוף שלהן יש api_base בתוך user_config. זה הסימן המדויק של מה שהרשומה מתארת. את ההגדרה הזאת אפשר לראות גם בתיקון עצמו ובהודעת האבטחה.