diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 3b3978d72..c3cc487a7 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -467,6 +467,8 @@ def checkSqlInjection(place, parameter, value): injection.conf.regexp = conf.regexp injection.conf.optimize = conf.optimize + injection.chars = kb.chars + if conf.beep or conf.realTest: beep() diff --git a/lib/core/agent.py b/lib/core/agent.py index 1d2716021..fbed0d024 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -214,11 +214,11 @@ class Agent: payload = payload.replace("[RANDNUM1]", str(randInt1)) payload = payload.replace("[RANDSTR]", randStr) payload = payload.replace("[RANDSTR1]", randStr1) - payload = payload.replace("[DELIMITER_START]", kb.misc.start) - payload = payload.replace("[DELIMITER_STOP]", kb.misc.stop) - payload = payload.replace("[AT_REPLACE]", kb.misc.at) - payload = payload.replace("[SPACE_REPLACE]", kb.misc.space) - payload = payload.replace("[DOLLAR_REPLACE]", kb.misc.dollar) + payload = payload.replace("[DELIMITER_START]", kb.chars.start) + payload = payload.replace("[DELIMITER_STOP]", kb.chars.stop) + payload = payload.replace("[AT_REPLACE]", kb.chars.at) + payload = payload.replace("[SPACE_REPLACE]", kb.chars.space) + payload = payload.replace("[DOLLAR_REPLACE]", kb.chars.dollar) payload = payload.replace("[SLEEPTIME]", str(conf.timeSec)) if origValue is not None: @@ -342,7 +342,7 @@ class Agent: for field in fieldsSplitted: nulledCastedFields.append(self.nullAndCastField(field)) - delimiterStr = "%s'%s'%s" % (dbmsDelimiter, kb.misc.delimiter, dbmsDelimiter) + delimiterStr = "%s'%s'%s" % (dbmsDelimiter, kb.chars.delimiter, dbmsDelimiter) nulledCastedConcatFields = delimiterStr.join([field for field in nulledCastedFields]) return nulledCastedConcatFields @@ -454,71 +454,71 @@ class Agent: if Backend.isDbms(DBMS.MYSQL): if fieldsExists: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1) - concatenatedQuery += ",'%s')" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.chars.start, 1) + concatenatedQuery += ",'%s')" % kb.chars.stop elif fieldsSelectCase: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1) - concatenatedQuery += ",'%s')" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.chars.start, 1) + concatenatedQuery += ",'%s')" % kb.chars.stop elif fieldsSelectFrom: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1) - concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % kb.misc.stop, 1) + concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.chars.start, 1) + concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % kb.chars.stop, 1) elif fieldsSelect: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1) - concatenatedQuery += ",'%s')" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.chars.start, 1) + concatenatedQuery += ",'%s')" % kb.chars.stop elif fieldsNoSelect: - concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop) + concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop) elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2): if fieldsExists: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1) - concatenatedQuery += "||'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) + concatenatedQuery += "||'%s'" % kb.chars.stop elif fieldsSelectCase: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||(SELECT " % kb.misc.start, 1) - concatenatedQuery += ")||'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||(SELECT " % kb.chars.start, 1) + concatenatedQuery += ")||'%s'" % kb.chars.stop elif fieldsSelectFrom: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1) - concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % kb.misc.stop, 1) + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) + concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % kb.chars.stop, 1) elif fieldsSelect: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1) - concatenatedQuery += "||'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1) + concatenatedQuery += "||'%s'" % kb.chars.stop elif fieldsNoSelect: - concatenatedQuery = "'%s'||%s||'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop) + concatenatedQuery = "'%s'||%s||'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop) elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE): if fieldsExists: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1) - concatenatedQuery += "+'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1) + concatenatedQuery += "+'%s'" % kb.chars.stop elif fieldsSelectTop: topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1) - concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.misc.start), 1) - concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 1) + concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.chars.start), 1) + concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1) elif fieldsSelectCase: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1) - concatenatedQuery += "+'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1) + concatenatedQuery += "+'%s'" % kb.chars.stop elif fieldsSelectFrom: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1) - concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 1) + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1) + concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1) elif fieldsSelect: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1) - concatenatedQuery += "+'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1) + concatenatedQuery += "+'%s'" % kb.chars.stop elif fieldsNoSelect: - concatenatedQuery = "'%s'+%s+'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop) + concatenatedQuery = "'%s'+%s+'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop) elif Backend.isDbms(DBMS.ACCESS): if fieldsExists: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.misc.start, 1) - concatenatedQuery += "&'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.chars.start, 1) + concatenatedQuery += "&'%s'" % kb.chars.stop elif fieldsSelectCase: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&(SELECT " % kb.misc.start, 1) - concatenatedQuery += ")&'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&(SELECT " % kb.chars.start, 1) + concatenatedQuery += ")&'%s'" % kb.chars.stop elif fieldsSelectFrom: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.misc.start, 1) - concatenatedQuery = concatenatedQuery.replace(" FROM ", "&'%s' FROM " % kb.misc.stop, 1) + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.chars.start, 1) + concatenatedQuery = concatenatedQuery.replace(" FROM ", "&'%s' FROM " % kb.chars.stop, 1) elif fieldsSelect: - concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.misc.start, 1) - concatenatedQuery += "&'%s'" % kb.misc.stop + concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'&" % kb.chars.start, 1) + concatenatedQuery += "&'%s'" % kb.chars.stop elif fieldsNoSelect: - concatenatedQuery = "'%s'&%s&'%s'" % (kb.misc.start, concatenatedQuery, kb.misc.stop) + concatenatedQuery = "'%s'&%s&'%s'" % (kb.chars.start, concatenatedQuery, kb.chars.stop) else: concatenatedQuery = query diff --git a/lib/core/common.py b/lib/core/common.py index 55ad88023..7898ce9bf 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -453,15 +453,15 @@ class Backend: @staticmethod def forceDbms(dbms, sticky=False): - if not kb.misc.stickyFlag: - kb.misc.forcedDbms = aliasToDbmsEnum(dbms) - kb.misc.stickyFlag = sticky + if not kb.stickyFlag: + kb.forcedDbms = aliasToDbmsEnum(dbms) + kb.stickyFlag = sticky @staticmethod def flushForcedDbms(force=False): - if not kb.misc.stickyFlag or force: - kb.misc.forcedDbms = None - kb.misc.stickyFlag = False + if not kb.stickyFlag or force: + kb.forcedDbms = None + kb.stickyFlag = False @staticmethod def setOs(os): @@ -518,7 +518,7 @@ class Backend: # Get methods @staticmethod def getForcedDbms(): - return aliasToDbmsEnum(kb.misc.forcedDbms) + return aliasToDbmsEnum(kb.forcedDbms) @staticmethod def getDbms(): @@ -1026,7 +1026,7 @@ def replaceNewlineTabs(inpStr, stdout=False): else: replacedString = inpStr.replace("\n", DUMP_NEWLINE_MARKER).replace("\r", DUMP_CR_MARKER).replace("\t", DUMP_TAB_MARKER) - replacedString = replacedString.replace(kb.misc.delimiter, DUMP_DEL_MARKER) + replacedString = replacedString.replace(kb.chars.delimiter, DUMP_DEL_MARKER) return replacedString @@ -1335,12 +1335,12 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True) data = BigArray() - outCond1 = ( output.startswith(kb.misc.start) and output.endswith(kb.misc.stop) ) + outCond1 = ( output.startswith(kb.chars.start) and output.endswith(kb.chars.stop) ) outCond2 = ( output.startswith(DUMP_START_MARKER) and output.endswith(DUMP_STOP_MARKER) ) if outCond1 or outCond2: if outCond1: - regExpr = '%s(.*?)%s' % (kb.misc.start, kb.misc.stop) + regExpr = '%s(.*?)%s' % (kb.chars.start, kb.chars.stop) elif outCond2: regExpr = '%s(.*?)%s' % (DUMP_START_MARKER, DUMP_STOP_MARKER) @@ -1367,7 +1367,7 @@ def parseUnionPage(output, expression, partial=False, condition=None, sort=True) if DUMP_DEL_MARKER in entry: entry = entry.split(DUMP_DEL_MARKER) else: - entry = entry.split(kb.misc.delimiter) + entry = entry.split(kb.chars.delimiter) if len(entry) == 1: data.append(entry[0]) @@ -2478,6 +2478,7 @@ def initTechnique(technique=None): if data: kb.pageTemplate, kb.errorIsNone = getPageTemplate(data.templatePayload, kb.injection.place) kb.matchRatio = data.matchRatio + kb.chars = kb.injection.chars # Restoring stored conf options for key, value in kb.injection.conf.items(): diff --git a/lib/core/option.py b/lib/core/option.py index 493cddc45..d76ae49a5 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1422,6 +1422,7 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.httpErrorCodes = {} kb.explicitSettings = set() kb.errorIsNone = True + kb.forcedDbms = None kb.formNames = [] kb.headersCount = 0 kb.headersFp = {} @@ -1469,6 +1470,7 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.safeCharEncode = False kb.singleLogFlags = set() kb.skipOthersDbms = None + kb.stickyFlag = False kb.suppressSession = False kb.suppressResumeInfo = False kb.technique = None @@ -1479,15 +1481,13 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.uChar = "NULL" kb.xpCmdshellAvailable = False - kb.misc = AttribDict() - kb.misc.delimiter = randomStr(length=6, lowercase=True) - kb.misc.start = ":%s:" % randomStr(length=3, lowercase=True) - kb.misc.stop = ":%s:" % randomStr(length=3, lowercase=True) - kb.misc.at = ":%s:" % randomStr(length=1, lowercase=True) - kb.misc.space = ":%s:" % randomStr(length=1, lowercase=True) - kb.misc.dollar = ":%s:" % randomStr(length=1, lowercase=True) - kb.misc.forcedDbms = None - kb.misc.stickyFlag = False + kb.chars = AttribDict() + kb.chars.delimiter = randomStr(length=6, lowercase=True) + kb.chars.start = ":%s:" % randomStr(length=3, lowercase=True) + kb.chars.stop = ":%s:" % randomStr(length=3, lowercase=True) + kb.chars.at = ":%s:" % randomStr(length=1, lowercase=True) + kb.chars.space = ":%s:" % randomStr(length=1, lowercase=True) + kb.chars.dollar = ":%s:" % randomStr(length=1, lowercase=True) if flushAll: kb.keywords = set(getFileItems(paths.SQL_KEYWORDS)) diff --git a/lib/techniques/error/use.py b/lib/techniques/error/use.py index 0e0346573..ec3ce5eb6 100644 --- a/lib/techniques/error/use.py +++ b/lib/techniques/error/use.py @@ -60,8 +60,8 @@ def __oneShotErrorUse(expression, field): if not retVal: while True: - check = "%s(?P.*?)%s" % (kb.misc.start, kb.misc.stop) - trimcheck = "%s(?P.*?).*?)%s" % (kb.chars.start, kb.chars.stop) + trimcheck = "%s(?P.*?)%s.*%s)" % (kb.misc.start, kb.misc.stop) - trimcheck = "%s(?P.*?)%s.*%s)" % (kb.chars.start, kb.chars.stop) + trimcheck = "%s(?P.*?).*?)%s' % (kb.misc.start, kb.misc.stop), output, re.DOTALL | re.IGNORECASE).split(kb.misc.delimiter) + if all(map(lambda x: x in output, [kb.chars.start, kb.chars.stop])): + items = extractRegexResult(r'%s(?P.*?)%s' % (kb.chars.start, kb.chars.stop), output, re.DOTALL | re.IGNORECASE).split(kb.chars.delimiter) kb.locks.value.acquire() threadData.shared.value.append(items[0] if len(items) == 1 else items) kb.locks.value.release() else: - items = output.replace(kb.misc.start, "").replace(kb.misc.stop, "").split(kb.misc.delimiter) + items = output.replace(kb.chars.start, "").replace(kb.chars.stop, "").split(kb.chars.delimiter) if conf.verbose == 1: status = "[%s] [INFO] retrieved: %s\r\n" % (time.strftime("%X"), safecharencode(",".join(map(lambda x: "\"%s\"" % x, items))))