diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index f6c4127dd..638676680 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -526,7 +526,13 @@ def cmdLineParser(): parser.add_option_group(windows) parser.add_option_group(miscellaneous) - (args, _) = parser.parse_args([utf8decode(arg) for arg in sys.argv]) + args = [] + for arg in sys.argv: + try: + args.append(utf8decode(arg)) + except: + args.append(unicode(arg, sys.getfilesystemencoding())) + (args, _) = parser.parse_args(args) if not args.direct and not args.url and not args.list and not args.googleDork and not args.configFile\ and not args.requestFile and not args.updateAll and not args.smokeTest and not args.liveTest: diff --git a/lib/utils/resume.py b/lib/utils/resume.py index 78d1d13a5..51c67cea7 100644 --- a/lib/utils/resume.py +++ b/lib/utils/resume.py @@ -103,104 +103,108 @@ def resume(expression, payload): This function can be called to resume part or entire output of a SQL injection query output. """ - - if "sqlmapfile" in expression or "sqlmapoutput" in expression: - return None - - condition = ( - kb.resumedQueries and conf.url in kb.resumedQueries.keys() - and expression in kb.resumedQueries[conf.url].keys() - ) - - if not condition: - return None - - resumedValue = kb.resumedQueries[conf.url][expression] - - if not resumedValue: - return None - - resumedValue = resumedValue.replace("__NEWLINE__", "\n").replace("__TAB__", "\t") - - if resumedValue[-1] == "]": - resumedValue = resumedValue[:-1] - - infoMsg = "read from file '%s': " % conf.sessionFile - logValue = re.findall("__START__(.*?)__STOP__", resumedValue, re.S) - - if logValue: - logValue = ", ".join([value.replace("__DEL__", ", ") for value in logValue]) - else: - logValue = resumedValue - - if "\n" in logValue: - infoMsg += "%s..." % logValue.split("\n")[0] - else: - infoMsg += logValue - - logger.info(infoMsg) - - return resumedValue - - # If we called this function without providing a payload it means that - # we have called it from lib/request/inject __goInband() function - # in UNION query (inband) SQL injection so we return to the calling - # function so that the query output will be retrieved taking advantage - # of the inband SQL injection vulnerability. - if not payload: - return None - - if not kb.dbms: - return None - - substringQuery = queries[kb.dbms].substring - select = re.search("\ASELECT ", expression, re.I) - - _, length, regExpr = queryOutputLength(expression, payload) - - if not length: - return None - - if len(resumedValue) == int(length): - infoMsg = "read from file '%s': " % conf.sessionFile - infoMsg += "%s" % resumedValue.split("\n")[0] - logger.info(infoMsg) - - dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue))) - - return resumedValue - elif len(resumedValue) < int(length): - infoMsg = "resumed from file '%s': " % conf.sessionFile - infoMsg += "%s..." % resumedValue.split("\n")[0] - logger.info(infoMsg) - - dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue))) - - if select: - newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1) - else: - newExpr = safeStringFormat(substringQuery, (expression, len(resumedValue) + 1, int(length))) - - missingCharsLength = int(length) - len(resumedValue) - - infoMsg = "retrieving pending %d query " % missingCharsLength - infoMsg += "output characters" - logger.info(infoMsg) - - start = time.time() - count, finalValue = bisection(payload, newExpr, length=missingCharsLength) - - debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start)) - logger.debug(debugMsg) - - if len(finalValue) != ( int(length) - len(resumedValue) ): - warnMsg = "the total length of the query is not " - warnMsg += "right, sqlmap is going to retrieve the " - warnMsg += "query value from the beginning now" - logger.warn(warnMsg) - + try: + if "sqlmapfile" in expression or "sqlmapoutput" in expression: return None - return "%s%s" % (resumedValue, finalValue) + condition = ( + kb.resumedQueries and conf.url in kb.resumedQueries.keys() + and expression in kb.resumedQueries[conf.url].keys() + ) - return None + if not condition: + return None + + resumedValue = kb.resumedQueries[conf.url][expression] + + if not resumedValue: + return None + + resumedValue = resumedValue.replace("__NEWLINE__", "\n").replace("__TAB__", "\t") + + if resumedValue[-1] == "]": + resumedValue = resumedValue[:-1] + + infoMsg = "read from file '%s': " % conf.sessionFile + logValue = re.findall("__START__(.*?)__STOP__", resumedValue, re.S) + + if logValue: + logValue = ", ".join([value.replace("__DEL__", ", ") for value in logValue]) + else: + logValue = resumedValue + + if "\n" in logValue: + infoMsg += "%s..." % logValue.split("\n")[0] + else: + infoMsg += logValue + + logger.info(infoMsg) + + return resumedValue + + # If we called this function without providing a payload it means that + # we have called it from lib/request/inject __goInband() function + # in UNION query (inband) SQL injection so we return to the calling + # function so that the query output will be retrieved taking advantage + # of the inband SQL injection vulnerability. + if not payload: + return None + + if not kb.dbms: + return None + + substringQuery = queries[kb.dbms].substring + select = re.search("\ASELECT ", expression, re.I) + + _, length, regExpr = queryOutputLength(expression, payload) + + if not length: + return None + + if len(resumedValue) == int(length): + infoMsg = "read from file '%s': " % conf.sessionFile + infoMsg += "%s" % resumedValue.split("\n")[0] + logger.info(infoMsg) + + dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue))) + + return resumedValue + elif len(resumedValue) < int(length): + infoMsg = "resumed from file '%s': " % conf.sessionFile + infoMsg += "%s..." % resumedValue.split("\n")[0] + logger.info(infoMsg) + + dataToSessionFile("[%s][%s][%s][%s][%s" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression, replaceNewlineTabs(resumedValue))) + + if select: + newExpr = expression.replace(regExpr, safeStringFormat(substringQuery, (regExpr, len(resumedValue) + 1, int(length))), 1) + else: + newExpr = safeStringFormat(substringQuery, (expression, len(resumedValue) + 1, int(length))) + + missingCharsLength = int(length) - len(resumedValue) + + infoMsg = "retrieving pending %d query " % missingCharsLength + infoMsg += "output characters" + logger.info(infoMsg) + + start = time.time() + count, finalValue = bisection(payload, newExpr, length=missingCharsLength) + + debugMsg = "performed %d queries in %d seconds" % (count, calculateDeltaSeconds(start)) + logger.debug(debugMsg) + + if len(finalValue) != ( int(length) - len(resumedValue) ): + warnMsg = "the total length of the query is not " + warnMsg += "right, sqlmap is going to retrieve the " + warnMsg += "query value from the beginning now" + logger.warn(warnMsg) + + return None + + return "%s%s" % (resumedValue, finalValue) + + return None + except: + errMsg = "invalid resume value for expression: '%s'" % expression + logger.error(errMsg) + return None diff --git a/tamper/charencode.py b/tamper/charencode.py index 79fd03789..cf522e820 100644 --- a/tamper/charencode.py +++ b/tamper/charencode.py @@ -8,6 +8,7 @@ from lib.core.exception import sqlmapUnsupportedFeatureException value -> urlencode of nonencoded chars in value """ def tamper(place, value): + raise sqlmapUnsupportedFeatureException, "can't use tampering module 'charencode.py' with 'URI' type injections" retVal = value if value: if place != "URI": diff --git a/tamper/randomcase.py b/tamper/randomcase.py index 35ba51120..28b5f0a52 100644 --- a/tamper/randomcase.py +++ b/tamper/randomcase.py @@ -6,7 +6,7 @@ from lib.core.common import randomRange from lib.core.exception import sqlmapUnsupportedFeatureException """ -value -> random case of chars in value +value -> chars from value with random case """ def tamper(place, value): retVal = value diff --git a/tamper/space2comment.py b/tamper/space2comment.py index 9d64d095e..8c9b1250a 100644 --- a/tamper/space2comment.py +++ b/tamper/space2comment.py @@ -10,8 +10,7 @@ def tamper(place, value): if value: if place != "URI": value = urldecode(value) - while value.find(" ") > -1: - value = value.replace(" ", "/**/") + value = value.replace(" ", "/**/") if place != "URI": value = urlencode(value) return value