XSS Attacks via SVG Files Disguised as GIFs

This article explains how attackers leverage Scalable Vector Graphics (SVG) disguised with a .gif extension to execute Cross-Site Scripting (XSS) attacks. It covers how file validation mechanisms are bypassed, how web servers and browsers handle ambiguous MIME types, and the technical mechanics that allow embedded JavaScript to execute within the victim's session context.

Unlike traditional raster formats such as GIF, JPEG, or PNG, an SVG is an XML-based vector image format. Because it is written in XML, the SVG specification natively supports the inclusion of script elements, such as <script> tags, and inline event handlers, such as onload or onerror. When an SVG document is rendered directly by a web browser, the browser's XML parser interprets the markup and executes any embedded JavaScript within the origin of the hosting domain.

To exploit file upload mechanisms that permit images but ban dangerous formats, attackers rename an SVG file to use a .gif extension (e.g., exploit.gif). If an application solely validates uploads using the file extension, the file is accepted and stored on the server. In more advanced scenarios where the application verifies magic bytes, attackers create a GIF/SVG polyglot file. This file begins with valid GIF header signatures, such as GIF89a, immediately followed by valid SVG XML markup containing executable script payloads.

The execution of the XSS payload relies on how the file is served and interpreted by the browser. If the web server does not explicitly send an accurate Content-Type: image/gif header, modern browsers perform MIME-type sniffing to deduce the file format. Upon scanning the file and encountering XML and SVG elements, the browser identifies the resource as image/svg+xml. When a user navigates directly to the file URL or the file is rendered in an inline context such as an <iframe> or an <object> tag, the browser treats the file as an active document, thereby executing the embedded JavaScript.

Execution also occurs when misconfigured servers rely on client-provided metadata or fail to enforce strict content handling. If the server serves the disguised file with a generic MIME type like text/plain or application/octet-stream without the X-Content-Type-Options: nosniff HTTP header, browsers attempt to determine the content type automatically. Once the browser detects markup, the payload triggers standard stored XSS behavior, enabling attackers to steal session cookies, manipulate the DOM, or perform unauthorized actions on behalf of the victim.

Preventing this vulnerability requires robust file upload and delivery controls: