The pictures we upload online are something we tend to think of as self-expression, but these very images can carry code to steal our passwords and data. Profile pictures, avatars, and image galleries are used all over the internet. While all images carry digital picture data — and many also carry metadata regarding camera or photo edits — it's far less expected that an image might actually be hiding malicious code.
How Is Hiding Code in an Image Possible?
Files are generally structured in a few different parts. Image files, for instance, generally begin with some declaration of the type of image file data present. This is usually something like a "Start of Image" marker, a sequence or number which indicates what is going to follow it. GIF files begin with GIF87a or GIF89a when viewed as ISO 8859-1 encoding, or "47 49 46 38 37 61" in hexadecimal.
These signatures are followed by data which corresponds to the arrangement and coloring of pixels in the image. This data, when enclosed in an image file, is enough to create a usable bitmap image. However, in addition to this visible image data, following the end of the image data, metadata such as EXIF can be inserted following an application marker segments. After these points, the image data has been both opened and closed with defined indicators, and anything after this data will not be processed as an image.
Metadata is generally only visible to the user when it's specifically parsed, and in the same way, hidden code will only be visible to a program which is looking for code to run. While this data often contains camera information, location data, or similar information related to the photograph itself, it could also be stuffed with another file, or in this case, executable code.
Despite the hidden content included in an image file, it still behaves as a standard image as the opening and closing components of the image content are sufficient for image-viewing programs to interpret and effectively display the image.
In the same way, when a website is told to look for a certain type of script, it will at least attempt to run, or look for something it can use for the action it is instructed to do. If this script is an image file rather than a text file, the website will be able to run the script so long as it can find the opening and closing elements of the code.
How Can This Technique Be Used?
Websites such as forums, hosting sites, or other sites with user-generated content often allow for the uploading of images and posting of text or media content.
In certain cases, HTML script tags will be permitted, perhaps a widget available for users to add to their posts or pages. A script tag may be able to be inserted where it should not have been due to a lack of form verification, often by using an escape tag like the HTML textarea property... But even if not, you'll be able to host your own web page that sources scripts from other pages, and if those scripts try to access cookies from the domain they're hosted on, they'll be granted access.
Because of this, as a protective measure, most sites won't let you upload scripts, but many will allow you to upload images. And many of those will just save the image and serve it up as-is (with our payload in tact). So, by uploading JavaScript within an image, it can be hosted on, and executed from a site's server. In addition, the technique greatly obfuscates malicious JavaScript even when used on a server controlled by the attacker, and could be used to obscure the actions of a phishing page.
What Can We Do by Executing JavaScript Hosted on a Target Server?
JavaScript can be used to attempt to steal cookies, which may include authentication tokens, are often vulnerable to XSS escape strings to execute more javascript, can prompt browsers to download or run a program, and even steal information from other websites the user has visited (assuming the target host serves up integrations that other web pages access). In the case of this example, a simple JavaScript alert function is used in order to confirm that JavaScript is running properly, but this could be replaced with malicious code or even a BeEF browser hook.
Step 1: Downloading & Installing Imagejs
Let's begin by cloning the git repository for the project. The commands in these examples are entered in a Kali Linux terminal environment.
git clone https://github.com/jklmnn/imagejs
After cloning the repository, we move into the directory with the following command.
cd imagejs
Finally, to compile the program, we simply run:
make
Step 2: Preparing JavaScript Code
The JavaScript formatting required is relatively minimal. No opening or closing tags are needed, and our file can simply specify the actions we wish to be performed. In order to test JavaScript functionality, we might use a sample string such as the one below. This JavaScript code will simply open an alert window with the text "Null Byte."
window.alert("Null Byte");
We can save this text as the filename of our choice, or directly send it to script.js with the following command line string.
echo "window.alert("Null Byte");" > script.js
Step 3: Embedding JavaScript into an Image
The JavaScript code can be embedded into any GIF, BMP, WEBP, PNM, or PGF file. However, depending on the limitations of where the image is going to be uploaded, we should consider how we form it.
If the image is going to be uploaded as an avatar or profile picture on a website, we should make sure both that it isn't too large of a file, nor that its resolution exceeds the maximum size. If the image with embedded JavaScript is scaled or compressed by the website, or if the site strips EXIF data, the functionality of the code may not be maintained, so the hope is that if you upload an image that fits the sites stated requirements, they'll save it in a hosted location as-is, without any alterations. I simply used the image below, saved as a GIF file by being exported using GIMP.
Step 4: Using Imagejs
Once we have both the code we would like to embed and the image we would like to add the code to, we can embed them using the following parameters. The script in this example is titled "script.js" and the image "image.jpg" — both of which are in the same directory as the imagejs program, as we can confirm by running ls.
The syntax begins with running the program, imagejs. The first argument, in this case gif, indicates the file type. The second argument refers to the script we are using, and the final argument following the -i flag is the image we wish to modify.
./imagejs gif script.js -i image.gif
The name of the output file. in this case. will be "script.js.gif." However, we can rename it to whatever we choose.
Step 5: Testing the Script
To test the functionality of the script image, let's create an HTML test page with opening and body tags.
We can save this file as "script.html" or the filename of our choice. When we open it in a browser, it should look like the following image.
The tag has been included in order to demonstrate that the GIF image is still entirely functional as an image, but it could be omitted and the script would still run.
Serving this from a file works as file systems don't specify file mime types. Most modern web servers will specify a mime type for the files it serves based on the file extension. If this is the case and the web server specifies an image mime type (such as image/gif), modern browsers will not attempt to execute the script as image mime types are not executable.
Step 6: Attacking
Now that we've established a way to embed JavaScript in images, we'll want to look at what we can do with that JavaScript code — and how it can be injected into a live website.
The following command will attempt to dump write cookies to the served up web-page. These cookies may be able to be used to impersonate users by stealing their authentication tokens. Now, obviously simply writing them to their browser isn't going to get them to you (you'll have to write a script to quietly post them to your own server), but this will serve as a simple proof of concept:
document.write('cookie: ' + document.cookie)
Finally, in order to deploy the attack, we need to find somewhere to upload our image and either another field that's vulnerable to XSS attacks where we are able to escape input verification and use a
Comments
No Comments Exist
Be the first, drop a comment!