Using the HTML5 Canvas its possible to use XSS to take screenshots of administration and management interfaces that might not have access to.
Blind Stored XSS
Additionally you can also try onload or onmouseover events in case the injection is inside an HTML attribute; although this significantly increases the size of the payload to about 160 characters:
22.214.171.124 - - [09/Apr/2012:02:10:49 +0000] "GET / HTTP/1.1" 200 57 "http://www.site.com/admin/customers.aspx" "Mozilla/5.0 (Windows NT 6.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2" 126.96.36.199 - - [09/Apr/2012:02:10:59 +0000] "GET / HTTP/1.1" 200 57 "http://www.site.com/admin/view_customer.aspx?id=122" "Mozilla/5.0 (Windows NT 6.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2"
Taking a screenshot using the HTML5 Canvas
The HTML5 Canvas allows you to quickly render (client side) an accurate screenshot of the clients browser and use Ajax to return it to a server controlled by the attacker.
The code I use is based more or less entirely on Niklas Von Hertzen's version available on GitHub. However I've made a few modifications in order to weaponize it:
- Merged the source together (JQuery, HTMLCanvas and the JQueryHTMLCanvas plugin) so that the payload consists of just 1 file
- Removed any messages displayed to the user
- Added an Ajax post so that it posts the Canvas to a remote server
- Added some code to prevent the JS being loaded multiple times on the same page
On the server side there is also a script to decode the Canvas which is posted as a base64 encoded string and write it to a database which also has Referrer, Remote Address and User Agent fields. This allows me to keep track of users that execute the code.
Cross Domain Policy and other issues
The only real caveat is that the script will run with the same-origin policy preventing it from fetching resources from other domains (e.g. images hosted on a CDN). In an attempt to overcome this the script uses a proxy to fetch external resources that are outside of its domain (this obviously wont work for any resources that are not publicly accessible).
Its also worth nothing that taking a screenshot using HTML5 doesn't really provide you with any more information than harvesting a copy of the DOM using XSS.
Download HTML5 Screenshot XSS POC code (Tested in the latest versions of Chrome and Firefox)
Article updated 6th April 2012 to include protocol relative URLs and a custom Acunetix Script