פרצות אבטחה בסינון קבצי SVG: איך להגן על האתר
אמ;לק
מחקר חדש חושף שיטות לעקיפת מערכות סינון של קבצי SVG, מה שמאפשר להריץ קוד זדוני בדפדפני פיירפוקס. חשוב לוודא שמערכת העלאת הקבצים שלכם עוברת ולידציה קפדנית ולא מסתמכת רק על בדיקות בסיסיות.
סיכום בעברית: מערכת VibeSec · מדיניות המקורות
נוסף ל-VibeSec:
כותרת מקורית: Scalable Vector Grief

התוכן המלא בעברית
תרגום אוטומטי מהמקור; מונחים טכניים נשארו באנגלית. לנוסח המחייב — הכתבה המקורית.
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.js / JS / TS- Bearer — SAST עם התמקדות בפרטיות ו-PII
- CodeQL — מנוע ניתוח סטטי של GitHub
- Dependabot — עדכונים אוטומטיים לתלויות פגיעות
- עדכון כלי בקרת הקוד markdownlint-cli
- הקוד נוצר ב-10 שניות, הבדיקה לקחה 3 ימים: למה צריך ארכיטקטורה בקוד של AI
- הכירו את HTTP2Shell: סיכון אבטחה בטכנולוגיית הדחיסה Brotli