diff --git a/lib/core/agent.py b/lib/core/agent.py index dc3e8a08a..178562570 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -81,6 +81,14 @@ class Agent: return retValue + def fullPayload(self, query): + query = self.prefixQuery(query) + query = self.postfixQuery(query) + payload = self.payload(newValue=query) + + return payload + + def prefixQuery(self, string): """ This method defines how the input string has to be escaped @@ -396,32 +404,32 @@ class Agent: inbandQuery += ", " if element == exprPosition: - if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query: - conditionIndex = query.rindex(" FROM ") - inbandQuery += "%s" % query[:conditionIndex] + if " FROM " in query and not query.startswith("SELECT "): + conditionIndex = query.index(" FROM ") + inbandQuery += query[:conditionIndex] else: - inbandQuery += "%s" % query + inbandQuery += query else: inbandQuery += "NULL" - if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query: - conditionIndex = query.rindex(" FROM ") - inbandQuery += "%s" % query[conditionIndex:] + if " FROM " in query and not query.startswith("SELECT "): + conditionIndex = query.index(" FROM ") + inbandQuery += query[conditionIndex:] + + if " ORDER BY " in inbandQuery and "(SELECT " in inbandQuery: + orderIndex = inbandQuery.index(" ORDER BY ") + inbandQuery += inbandQuery[orderIndex:].replace(")", "") if kb.dbms == "Oracle": if " FROM " not in inbandQuery: inbandQuery += " FROM DUAL" - if " ORDER BY " in inbandQuery: - orderIndex = inbandQuery.index(" ORDER BY ") - inbandQuery = inbandQuery[:orderIndex] - inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment) return inbandQuery - def limitQuery(self, num, query, fieldsList=None): + def limitQuery(self, num, query, field): """ Take in input a query string and return its limited query string. @@ -436,8 +444,8 @@ class Agent: @param query: query to be processed @type query: C{str} - @param fieldsList: list of fields within the query - @type fieldsList: C{list} + @param field: field within the query + @type field: C{list} @return: limited query string @rtype: C{str} @@ -453,13 +461,12 @@ class Agent: limitStr = queries[kb.dbms].limit % (num, 1) limitedQuery += " %s" % limitStr - # TODO: fix for Partial UNION query SQL injection technique both - # Oracle and Microsoft SQL Server + # TODO: fix Partial UNION query SQL injection technique for Oracle elif kb.dbms == "Oracle": if query.startswith("SELECT "): limitedQuery = "%s FROM (%s, %s" % (untilFrom, untilFrom, limitStr) else: - limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, ", ".join(field for field in fieldsList), limitStr) + limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, field, limitStr) limitedQuery = limitedQuery % fromFrom limitedQuery += "=%d" % (num + 1) @@ -469,9 +476,9 @@ class Agent: limitedQuery = limitedQuery[:untilOrderChar] limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1) - limitedQuery = "%s WHERE %s " % (limitedQuery, fieldsList[0]) + limitedQuery = "%s WHERE %s " % (limitedQuery, field) limitedQuery += "NOT IN (%s" % (limitStr % num) - limitedQuery += "%s %s)" % (fieldsList[0], fromFrom) + limitedQuery += "%s %s)" % (field, fromFrom) return limitedQuery diff --git a/lib/request/inject.py b/lib/request/inject.py index ea6b77742..4a6c12e75 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -70,13 +70,23 @@ def __goInference(payload, expression): return value -def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None): - outputs = [] +def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None): + outputs = [] + origExpr = None for field in expressionFieldsList: output = None + if isinstance(num, int): + origExpr = expression + expression = agent.limitQuery(num, expression, field) + expressionReplaced = expression.replace(expressionFields, field, 1) + + if " ORDER BY " in expressionReplaced and "(SELECT " in expressionReplaced: + orderIndex = expressionReplaced.index(" ORDER BY ") + expressionReplaced += expressionReplaced[orderIndex:].replace(")", "") + output = resume(expressionReplaced, payload) if not output or ( expected == "int" and not output.isdigit() ): @@ -87,6 +97,9 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl output = __goInference(payload, expressionReplaced) + if isinstance(num, int): + expression = origExpr + outputs.append(output) return outputs @@ -252,9 +265,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None): return None for num in xrange(startLimit, stopLimit): - limitedExpr = agent.limitQuery(num, expression, expressionFieldsList) - - output = __goInferenceFields(limitedExpr, expressionFields, expressionFieldsList, payload, expected) + output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num) outputs.append(output) return outputs diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 374bf7b57..8cac31351 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -261,7 +261,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False): return for num in xrange(startLimit, stopLimit): - limitedExpr = agent.limitQuery(num, expression, expressionFieldsList) + orderBy = re.search(" ORDER BY ([\w\_]+)", expression, re.I) + + if orderBy: + field = orderBy.group(1) + else: + field = expressionFieldsList[0] + + limitedExpr = agent.limitQuery(num, expression, field) output = unionUse(limitedExpr, direct=True, unescape=False) if output: