How To: Hack Forum Accounts with Password-Stealing Pictures

Hack Forum Accounts with Password-Stealing Pictures

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.

A GIF image viewed as hexadecimal values.

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.

<html>
<body>
<img src="script.js.gif">
<script src="script.js.gif"></script>
</body>
</html>

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 <img> 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 <script> tag, or (more easily) load the image (as a script) from our own phishing webpage. In the example below, we uploaded our avatar, 1337.gif, and following a </textarea> exit tag, we enclose it in script tags. After this, anyone who views this profile will have their cookies dumped to their browser window. Replace the script above with one that silently posts the values of document.cookie to a server of your choosing, and you've got your self a silent credential thief.

Step 7: Defending Against the Attack

The solution for defending against an attack like this on the client-side may be as simple as installing NoScript, and to stick to trustworthy sites (such as Null Byte) that spend copious amounts of time protecting themselves against XSS attacks. However, it's quite difficult to differentiate good and bad scripts, and the responsibility for preventing malicious JavaScript injection lies on the shoulders of web developers and administrators.

For web developers to properly avoid any sort of JavaScript, PHP, or SQL injection, the solution is the same — input sanitation and user privilege management. If a user is at any point able to attain remote code execution, the majority of the battle has already been lost. Make sure your web server is up to date and is properly configured to serve image/* mime-types for any image files you host. While it can take a little more work, the best practice would be to strip any EXIF data from any user uploaded images... or if you don't know how to do that, simply use one of the image resizing libraries such as ImageMagick to re-size and re-compress any images that are uploaded as this will often strip EXIF data as part of the process.

Just updated your iPhone to iOS 18? You'll find a ton of hot new features for some of your most-used Apple apps. Dive in and see for yourself:

Cover image and screenshots by TAKHION/Null Byte

9 Comments

What an amazing injection attack! Nice tutorial mate im gonna try this one out asap :)

I tried to test the image but the html file doesnt work it only shows the image.gif and im not sure if there is something to do with firefox esr that comes in kali

Try launching Firefox from command line in safe mode.

firefox -safe-mode

This should disable all addons and extensions, as it may be in part to those bundled with Kali, or the Firefox profile settings. If that doesn't solve the issue, try creating a new Firefox profile.

firefox -P NewProfileName

Please let me know if either of those solve your problem!

I am on Firefox 52 and the script is being blocked for disallowed MIME Type. Maybe it work only in older browser. What version of Firefox did you use in your tutorial? Below is a paste of the error showing in firefox developer toolbar.

---->

14:23:08.618 Script from "http://localhost:8000/script.js.gif " was blocked because of a disallowed MIME type. 1 localhost:8000

<----

I used Firefox 54 for the demonstration. Perhaps you have increased security settings, or an addon which is preventing the file from being run? You may wish to test this with addons or preferences disabled.

I would also try renaming the file and the filename reference within the HTML from "script.js.gif" to simply "script.gif" as the presence of the ".js" may be triggering the error.

hi!

Trying to test the script on chomium I get this error 'Uncaught SyntaxError: Invalid or unexpected token' on the javascript console :( any ideas?

First, try using FireFox - specifically with addons disabled. The script demonstrated in the example did work within Chromium for me when I tested, but it's best to make sure that it's not just a browser issue.

It sounds like maybe the JavaScript had improper opening or closing arguments, make sure that the .js file you add to the image doesn't have any unnecessary headers or declarations.

Let me know if either of these fix your issue!

I tried but.... when I entered "./imagejs gif script.js -i image.gif"
It jst showed "the file image.gif could not be opened"
Any solution please

Is a file named "image.gif" in the same folder as the program? Make sure that it is, and make sure that it's a properly formatted .gif file.

Share Your Thoughts

  • Hot
  • Latest