חזרה לפיד
articlesמקור: PortSwigger Research27.10.2026

פרצות אבטחה בסינון קבצי SVG: איך להגן על האתר

אמ;לק

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

סיכום בעברית: מערכת VibeSec · מדיניות המקורות

נוסף ל-VibeSec:

כותרת מקורית: Scalable Vector Grief

פרצות אבטחה בסינון קבצי SVG: איך להגן על האתר

התוכן המלא בעברית

תרגום אוטומטי מהמקור; מונחים טכניים נשארו באנגלית. לנוסח המחייב — הכתבה המקורית.

⁦Gareth Heyes⁩

• פורסם: יום שלישי, 27 באוקטובר 2026 בשעה 14:29 ⁦UTC⁩

• עודכן: יום שלישי, 27 באוקטובר 2026 בשעה 14:29 ⁦UTC⁩

בדקתי שמונה כלי ניקוי (sanitizers) פופולריים ל-SVG ועקפתי שישה מהם. בפוסט זה אראה לכם כיצד כותרת תגובה (response header) יכולה להריץ JavaScript ב-Firefox, גם כאשר גוף התגובה הוא XML תמים לחלוטין. כמו כן, אראה לכם כיצד לגרום ל-Safari לייבא GIF בתור SVG ולהריץ ממנו JavaScript.

פריצת כלי ניקוי ל-SVG

המטרות

SVG הוא פורמט תמונה שיכול להכיל סקריפטים, מטפלי אירועים, קישורים, אנימציות ואפילו HTML מוטמע. לכן, אפליקציות המאפשרות העלאת קבצי SVG בדרך כלל מעבירות אותם תחילה דרך כלי ניקוי. כדי לראות עד כמה הכלים הללו חסינים, בדקתי את ספריות ה-SVG הפופולריות ביותר לפי ChatGPT:

• ⁦https://github.com/darylldoyle/svg-sanitizer⁩

• ⁦https://github.com/Borewit/svg-sanitizer⁩

• ⁦https://github.com/mattkrick/sanitize-svg⁩

• ⁦https://github.com/alnorris/SVG-Sanitizer⁩

חימום: בלבול במרחבי שמות (namespace)

הספרייה המושפעת: ⁦mattkrick/sanitize-svg⁩

לספרייה הזו יש כל כך הרבה מעקפים שאני אכסה רק את המעניינים שבהם.

הממצא הראשון שלי היה שלא צריך <foreignObject> כדי להכניס HTML לתוך SVG. אם משנים את מרחב השמות (namespace) של XML ברכיב בודד ל-XHTML, הדפדפן מרנדר אותו כ-HTML ישירות בתוך ה-SVG. כל מה שצריך זה <frame> עם JavaScript URL:

אותו טריק של מרחב שמות עובד גם עם iframes, מה שנותן לכם את srcdoc לעבוד איתו:

ניתן לעקוף את הספרייה גם באמצעות <foreignObject> פשוט. הספרייה מרנדרת את ה-SVG, מה שממיר את שם הרכיב לצורת ה-camelCase שלו, foreignObject. לאחר מכן היא מחפשת את הרכיב באמצעות querySelectorAll('foreignobject'), שלא מוצא דבר, ולכן ה-payload עובר ללא הפרעה:

אפילו SVG מקונן עם מטפל onload עבר את הבדיקה:

הגעה ל-JavaScript URL באמצעות אנימציה

זה לא דרש מאמץ רב. הספרייה אפשרה לתגי <animate> לעבור ללא סינון, כך שניתן להשתמש באנימציה כדי להפוך את ה-href של קישור ל-JavaScript URL:

עקפתי את אותה ספרייה בדרך נוספת באמצעות הטריק של Kevin Mizu, שמשתמש ב-<animateTransform> כדי להגדיר JavaScript URL ב-Safari:

⁦XSS⁩ מתוך גיליון סגנונות ⁦XSLT⁩ עצמאי

ספריות מושפעות: ⁦bgalek/safe-svg⁩, ⁦mattkrick/sanitize-svg⁩, ⁦alnorris/SVG-Sanitizer⁩

כאן הדברים נהיים מעניינים יותר. זוהי טכניקה עוצמתית: ניתן להריץ JavaScript מגיליון סגנונות XSLT מבלי להזדקק לקובץ נפרד. הייתי להוט לכתוב על כך בבלוג, כיוון שלמרבה הצער התכונה הוצאה משימוש (deprecated) ואמורה להיות מוסרת בנובמבר 2026.

הטריק הוא להפנות הוראת עיבוד של xml-stylesheet אל data URL. Base64 היא הדרך האלגנטית ביותר לקודד את גיליון הסגנונות, אך גם קידוד URL עובד:

הנה גיליון הסגנונות שמקודד ⁦base64⁩:

הוא תואם לשורש המסמך ומפיק עמוד HTML המכיל סקריפט שמציג alert של document.domain, מה שמוכיח שהקוד רץ במקור (origin) של המסמך ולא במקור ריק. אם תחברו את הכל יחד, תקבלו את זה:

הפיכת כותרת תגובה ל-⁦XSS⁩

במחשבה לאחור נזכרתי בטריק שסיפר לי פעם Paulos Yibelo: דפדפן Firefox מאפשר לטעון קבצי CSS חיצוניים באמצעות כותרת תגובה מסוג Link. הבנתי שגם data URLs עובדים שם, מה שגרם לי לחשוב: אם זה עובד עבור CSS, האם זה יכול לעבוד גם עבור XSLT? ובכן, בהחלט כן.

ראשית, הייתי צריך גרסה של גיליון הסגנונות שמתאימה לתוך URL. לזו יש שתי שכבות. גיליון הסגנונות החיצוני מקודד כ-URL לתוך data URL. בתוכו, הפונקציה document() של XSLT טוענת data URL שני, המקודד גם הוא כ-URL, ומכיל XHTML <img> עם מטפל onerror. גיליון הסגנונות מעתיק זאת לתוך <foreignObject>, ושם הוא מתבצע.

כהוראת עיבוד, זה נראה כך:

הנה המטען לפני הקידוד. השארתי את התגים ⁦Hackvertor⁩ כדי שתוכל לראות היכן מוחלת כל שכבה של קידוד ⁦URL⁩:

אתה יכול לטעון ולערוך את המטען המלא ב-⁦Hackvertor⁩ .

כשגיליון הסגנונות מוכן, כל מה שנותר הוא להעביר אותו מהמסמך אל כותרת ⁦Link⁩:

גוף התגובה הוא פיסת XML תמימה לחלוטין, ובכל זאת היא מתבצעת ב-Firefox!

ייבוא ​​תמונות כ-⁦SVG⁩ ב-⁦Safari⁩

ספריות מושפעות: ⁦cloudflare/svg-hush⁩, ⁦jams2/py-svg-hush⁩, ⁦bgalek/safe-svg⁩

לסיום המחקר, הנה התנהגות מדהימה נוספת, הפעם ב-Safari. הן Firefox והן Safari מאפשרים להשתמש ברכיב <use> כדי להפנות לקבצים מאותו המקור (same-origin), אבל Safari לוקח את זה צעד אחד קדימה: הוא מאפשר לייבא קבצי תמונה בתור SVG!

למרבה הצער, לא ניתן ליצור SVG/image פוליגלוט אמיתי כי SVG קפדני מדי. עם זאת, אם תצליחו להעלות קובץ GIF שמכיל את ה-payload, הוא אמנם לא ירונדר כשפותחים אותו בדפדפן, אך עדיין ניתן לייבא אותו באמצעות רכיב <use>!

זה כל מה שצריך כדי לעקוף את כל שלוש הספריות:

מסכם

אני מקווה שנהניתם מהפוסט. ניצלתי גם שתי אפליקציות פופולריות שעדיין איני יכול לנקוב בשמן, אך אעדכן את הפוסט ברגע שאוכל. הן DOMPurify והן darylldoyle/svg-sanitizer עמדו בהצלחה מול כל מה שהצגתי בפוסט הזה, וזה די מרשים.

מה יש בשם תג? JavaScript, כנראה

גניבת עוגיות HttpOnly באמצעות טכניקת cookie sandwich

עקיפת ⁦WAFs⁩ עם עוגיית הפנטום $⁦Version⁩

#node#web-security#xss#svg-security
קרא במקור

קריאה וכלים קשורים

אבטחת Node.js / JS / TSמונחי אבטחה והסברים בעברית