מה זה DOM Clobbering, ואיך פורצים בלי להריץ אפילו שורת JavaScript אחת¶
תשאלו כל מפתח ווב "איך מונעים XSS", והוא יגיד לכם - חוסמים תגי script, שמים CSP חזק, מנקים כל HTML שמגיע מהמשתמש. זה נכון, וזה עוזר מאוד. אבל יש טכניקה שמתעלמת לגמרי מכל ההגנות האלה, כי היא לא מזריקה קוד בכלל. היא משתמשת ב-HTML תמים לגמרי כדי לשבש את הלוגיקה של הדף. זה נקרא DOM Clobbering, וזו אחת הטכניקות המפתיעות ביותר שתפגשו בעולם הווב.
הרעיון הבסיסי - מתי HTML לבד מספיק¶
בדפדפן, כשיש לאלמנט HTML תכונת id או name, הדפדפן לפעמים "עוזר" למפתחים על ידי כך שהוא חושף את האלמנט הזה כמשתנה גלובלי, נגיש ישירות דרך window. זו תכונה ותיקה בדפדפנים, שנועדה במקור לנוחות, אבל היא זו שפותחת את הדלת לכל הסיפור.
תחשבו על קוד JavaScript שסומך על משתנה גלובלי בשם config, ובודק אם הוא קיים לפני שהוא משתמש בו. אם באיזשהו מקום בדף מופיע HTML עם id="config", הדפדפן עלול ליצור משתנה גלובלי בשם הזה שמצביע על האלמנט - וזה בדיוק המקום שבו אם תוקף מצליח להזריק HTML לדף, גם בלי שום תג script, הוא יכול "לדרוס" בעצמו את המשתנה הגלובלי שהקוד האמיתי של האתר מסתמך עליו.
אז איך תוקף בלי JavaScript עושה נזק¶
הנה הרעיון המרכזי - תוקף שיכול להזריק HTML לדף, אבל לא יכול להריץ סקריפט (כי יש CSP חזק, או כי סניטייזר מנקה כל תג script), עדיין יכול ליצור אלמנטים עם id או name מדויקים שמתנגשים עם משתנים שהקוד הלגיטימי של הדף מצפה להם.
- דריסת דגלים לוגיים - אם הקוד בודק
if (window.isAdmin), ותוקף מזריק אלמנט עםid="isAdmin", המשתנה הזה כבר לאundefined- הוא הופך לאובייקט אלמנט, שבתנאי מסוים מוערך כ-truthy, ומשנה את זרימת הלוגיקה של הדף. - דריסת קונפיגורציה - אם קוד באתר טוען קובץ סקריפט מ-URL שמאוחסן במשתנה שאמור להגיע מהשרת, ותוקף מצליח לדרוס את המשתנה הזה עם אלמנט HTML שמכיל את התכונה
srcשמצביעה לדומיין זר, הדף עלול לטעון סקריפט מהשרת של התוקף. - שרשור עם עוד חולשות - הרבה פעמים DOM Clobbering לבד לא מספיק כדי להשיג הרצת קוד, אבל הוא מספיק כדי לשבש הנחת יסוד אחת בקוד, שמובילה לחולשה נוספת בהמשך השרשרת.
למה זה כל כך מסוכן דווקא היום¶
האירוניה היא ש-DOM Clobbering נהיה רלוונטי יותר, לא פחות, ככל שאתרים משתפרים בהגנה מפני XSS קלאסי. ככל שיותר אתרים מטמיעים CSP קפדני שחוסם תגי script לגמרי, ומריצים סניטייזרים חכמים שמסננים כל תוכן HTML שנראה חשוד, כך גדל המקום שבו התוקף עדיין יכול לפעול - כי HTML "תמים" כמו <a>, <img> או <form> עם id מתאים כמעט תמיד עובר סניטייזרים בלי בעיה. הם נבנו לחסום קוד, לא לחסום שמות.
זו בדיוק הסיבה שאי אפשר להגיד "האתר הזה בטוח מ-XSS" רק כי אין תגי script בפלט. אם אפליקציה סומכת על מבנה גלובלי מסוים ב-JavaScript בלי לוודא במפורש שהוא לא הגיע במקרה מ-HTML שהוזרק, היא חשופה, גם עם ההגנות הכי חזקות שיש.
איך מגנים על אפליקציה מפני זה¶
ההגנה העיקרית היא הרגל קוד פשוט - לעולם לא לסמוך על משתני window בלי לוודא שהם באמת מהסוג שאתם מצפים לו, ולא רק אלמנט HTML שמתחזה למשתנה. שימוש נכון במרחבי שמות מקומיים במקום גלובליים, ובדיקות טיפוס מפורשות לפני שימוש בערך, סוגרים את רוב הדלת הזו. זו בדיוק סוג ההבנה העמוקה של איך הדפדפן מתנהג "מתחת למכסה המנוע" שאנחנו בונים לאט לאט בקורס פריצת אתרים מתקדם, כי בלי להבין את ההתנהגויות הישנות והמוזרות האלה של הדפדפן, קשה מאוד לזהות איפה בדיוק אפליקציה חשופה.
מי שרוצה להתעמק בטכניקה הזו ולתרגל אותה על אתגרים אמיתיים מוזמן להצטרף לדיסקורד שלנו - יש שם דיונים קבועים בדיוק על הטכניקות הפחות מוכרות כאלה.
לסיכום¶
DOM Clobbering מוכיחה שאבטחת ווב היא לא רק "לחסום script tags". זו טכניקה שמנצלת התנהגות ישנה ותמימה לכאורה של הדפדפן כדי לשבש הנחות יסוד בקוד, בלי להריץ אפילו שורת JavaScript אחת. ודווקא בגלל זה, היא ממשיכה לעבוד גם באתרים שמשקיעים המון באבטחה קלאסית מול XSS.