DeepSeek Harness אפשר לתוקף בתוך סביבת ארגז חול (sandbox) להריץ פקודות שרירותיות פשוט על ידי שינוי כותרת ה-HTTP Host ל-127.0.0.1, מה שמעניק ציון של 9.4 בסולם CVSS. הפגם מדגים כיצד החלטת אמון אחת שגויה יכולה להפוך גבול הגנה לדלת אחורית פתוחה.
איך הבאג חלחל פנימה
הקוד הפגיע נמצא בפונקציה בודדת שקוראת את כותרת ה-Host של הבקשה, ואם הערך שווה לכתובת ה-loopback, היא מתייחסת לבקשה כאילו היא מגיעה מהמכונה המקומית.
תוקף שיכול להריץ קוד בתוך ארגז החול אינו זקוק למטען (payload) מתוחכם. על ידי שליחת בקשת HTTP אחת עם Host: 127.0.0.1, ה-backend מאמין שהקריאה מקורה בשרת עצמו ומדלג על כל ההתראות האבטחתיות, בדיקות מגבלת קצב (rate-limit) ושלבי אימות הפקודות. התוצאה: הרצת פקודות ללא הגבלה ללא צורך באינטראקציה נוספת.
למה לסמוך על כותרות (headers) זה מסוכן
כותרות הן מחרוזות טקסט פשוט (plain-text) המסופקות על ידי הקורא. בין אם השדה נקרא Host, X-Forwarded-For, או כל שם מותאם אישית אחר, הלקוח יכול להגדיר אותו לכל ערך שירצה. מקור האמת האמין היחיד לגבי המקור האמיתי של החיבור הוא שכבת התעבורה (transport layer) – כתובת ה-IP של מקור ה-socket שהמערכת ההפעלה רושמת כאשר לחיצת היד של ה-TCP (TCP handshake) מסתיימת.
כאשר אפליקציה מחליטה לסמוך על כותרת מבלי לוודא שפרוקסי (proxy) ידוע ומוגדר כהלכה הוא זה שהחדיר אותה, היא מעניקה לתוקף את מפתחות הממלכה. הבאג ב-DeepSeek Harness הוא דוגמה קלאסית לטעות זו.
השפעה בעולם האמיתי: דוגמת shell.online
פרויקט הקוד הפתוח shell.online, המציע טרמינל מבוסס דפדפן, תיעד לאחרונה את אותה מלכודת. הוא משתמש בדגל הגדרה הנקרא TRUST_PROXY:
- TRUST_PROXY = 0 – האפליקציה מתעלמת מכותרת ה-X-Forwarded-For ומסתמכת על הכתובת המרוחקת של ה-socket. זה מונע מלקוח לזייף כתובת IP כדי לחמוק ממגבלות קצב או להתחזות למשתמש מהימן.
- TRUST_PROXY = 1 – האפליקציה סומכת על כותרת ה-X-Forwarded-For כזהות הלקוח. אם השירות אינו נמצא מאחורי פרוקסי אמיתי שמנקה (sanitises) את הכותרת הזו, תוקף יכול לספק כתובת IP חדשה בכל בקשה, ובכך לאפס בפועל כל הגבלת קצב (throttling) מבוססת IP.
הבאג ב-DeepSeek משקף תרחיש זה: הקוד סמך על Host כאילו פרוקסי הגדיר אותו, למרות שניתן היה לגשת לשירות ישירות.
מה מפתחים צריכים לעשות עכשיו
- בצעו ביקורת (Audit) לכל מקום שבו אתם קוראים כותרות המסופקות על ידי לקוח. זהו אילו כותרות נחשבות עבורכם לסמכותיות (למשל, Host, X-Forwarded-For, X-Real-IP) וודאו שפרוקסי מהימן אכן כותב אותן מחדש לפני שהן מגיעות לאפליקציה שלכם.
- קשרו החלטות אבטחה לכתובת ה-socket במידת האפשר. השתמשו בכתובת ה-IP של המקור המסופקת על ידי מערכת ההפעלה לצורך אימות, הגבלת קצב ובדיקות בקרת גישה.
- הפעילו דגלי אמון-פרוקסי (proxy-trust) רק כאשר reverse proxy המוגדר כהלכה נמצא לפני השירות. אם אתם מריצים את האפליקציה ישירות, השאירו דגלים אלו כבויים.
- תעדו את טופולוגיית הפריסה (deployment topology) הנדרשת בקובץ ה-README או במדריך הפריסה של הפרויקט שלכם, כדי שמשתמשים המריצים את השירות באופן עצמאי (self-host) ידעו על דרישת אמון הפרוקסי.
- הריצו כלי ניתוח סטטי (static-analysis) או כלי סקירת קוד שמסמנים שימוש ישיר בכותרות לצורך החלטות אבטחה ללא לוגיקת אימות פרוקסי נלווית.
מה לשים לב בהמשך
קהילות המספקות שירותי אינטרנט בניהול עצמי (self-hosted) צפויות לבחון מחדש את הגדרות אמון הפרוקסי שלהן בעקבות תקרית זו.
הלקח המרכזי הוא חד משמעי: לעולם אל תתנו למחרוזת טקסט שכל אחד באינטרנט יכול לכתוב להכתיב את מצב האבטחה (security posture) של המערכת שלכם. סמכו על שכבת הרשת, לא על שכבת הבקשה.
