top of page

Exploiting XSS with Javascript/JPEG Polyglot

Updated: Jun 15

XSS (Cross-Site Scripting) vulnerabilities pose a significant security risk to web applications. They allow attackers to inject malicious scripts into trusted websites, leading to the execution of unauthorized code on users' browsers. Over the years, security researchers have explored various techniques to exploit XSS vulnerabilities creatively. One intriguing approach involves the use of polyglots, which are files that combine multiple file types to bypass security measures.

However, innovative attackers continuously seek new ways to bypass these security measures and find novel attack vectors. One such technique involves leveraging the power of polyglots - files that combine two different file types - to create an XSS payload embedded within a seemingly innocent JPEG image.

In this article, we will delve into the world of XSS exploitation with Javascript/JPEG polyglots. Before that, we will learn what is polyglot.

What is a polyglot?

Polyglots are unique combinations of two different file types. They merge the characteristics of disparate file formats, creating intriguing hybrids. Some examples include Phar + JPEG (combining a PHP archive with a JPEG file), GIFAR (a fusion of a GIF and RAR file), and Javascript + JPEG, among others.

Web applications often impose restrictions on file types allowed for features like file uploads. This is done to prevent potential security risks, as certain file types such as .php or .js files can enable attackers to upload malicious content onto the application. To enforce these restrictions, applications perform various checks, including extension filtering (e.g., double extensions like .jpg.php) and detection of null bytes in extensions (e.g., .php%00.jpg). Additionally, applications examine file names (e.g., .htaccess, .config) and compare the uploaded file's signature with its declared content type.

However, different applications employ different methods for validation checks. In some cases, polyglots can be utilized as a means to bypass these checks, exploiting the complexities that arise from their combination of file formats. By cleverly crafting a polyglot, attackers may succeed in circumventing certain validation measures and infiltrating the system with potentially malicious files.

Understanding polyglots and their implications is crucial for both developers and security professionals. By delving into the intricacies of these hybrid files, we can better appreciate the challenges posed by file type validation and enhance our defenses against potential threats.

What is JPEG Structure?

JPEG images are structured as a sequence of segments, each of which begins with a header. These headers play a crucial role in defining specific information about the image file. The payload following each header varies depending on the header type.

Here are some common JPEG marker types:

  • 0xffd8: "Start of Image"

  • 0xffe0: "Application Default Header"

  • 0xffdb: "Quantization Table"

  • 0xffc0: "Start of Frame"

  • 0xffc4: "Define Huffman Table"

  • 0xffda: "Start of Scan"

  • 0xffd9: "End of Image"

In any binary file, including a JPEG image, several headers exist. These headers are vital as they provide crucial information about the file. Most headers are followed by length information, indicating the size of the corresponding segment.

The "Start of Image" header is represented by FF D8. If this marker is missing, it can be assumed that the file is not a valid JPEG image. Another important marker is FF D9, which denotes the end of the image.

To disguise the payload as a legitimate JPEG file, several steps are taken. First, the length of the header, comment header, null bytes for padding, and the JavaScript attack vector are added.

Let's consider the attack vector as /=alert("XSS")/. When converted to hexadecimal, it appears as follows:


To inject JavaScript into the image metadata, we can utilize a hex editor. This technique takes advantage of the fact that browsers interpret the code embedded in the image's metadata when rendering it as HTML.

Let's consider an example where we have an image named test.jpg. Below is the hexdump of the test.jpg file:

[Hexdump of test.jpg] 

Using a hex editor, such as ghex, we can replace specific hexadecimal characters within the file. By modifying the hex values and saving the changes, we can inject JavaScript code into the image's metadata. The injected JavaScript will be executed when the browser renders the image as part of an HTML document.

The first FF D8 is the start of the image, the next two bytes represent the upcoming two bytes, 00 10 represents the length of the JPEG header which in decimal equivalent is 16 bytes.

Time for Injection

To perform the injection, we will insert our payload between the hexadecimal values FF E0 and FF DB. In this case, our payload is represented by the hex value 2F 2A, which corresponds to the "/*" characters.

Based on the provided screenshot, the size of our payload is 18 bytes. To ensure the correct padding, we need to add null bytes to reach the desired length of 12074 bytes. Therefore, the number of null bytes required is 12074 - 16 - 18 = 12040 bytes.

To modify the test.jpg file accordingly, we can use the following commands:

xxd -p -c 16 test.jpg | sed 's/ffe0ffdb/ffe02f2affdb/' | xxd -p -r | cat - <(printf '\0%.0s' {1..12040}) > test_new.jpg

The above commands will read the content of test.jpg, insert our payload between FF E0 and FF DB, convert the modified hex back into binary, add 12040 null bytes, and write the result to a new file called test_new.jpg.

In the ghex editor, you can observe the hexdump of test_new.jpg to see the modifications.

To execute the image as JavaScript, you can use the following code:

<script charset="ISO-8859-1" src="test_new.jpg"></script>

Please note that when using Firefox with a UTF-8 character set for the document, including the script may corrupt the polyglot. To ensure the script works correctly, specify the charset as ISO-8859-1 on the script tag, and it should execute fine.


The use of polyglots combining Javascript and JPEG file types introduces a new dimension to XSS exploitation. By carefully crafting these files, attackers can inject malicious Javascript code into seemingly harmless image files, bypassing traditional security measures and potentially executing unauthorized code on users' browsers.

bottom of page