diff --git a/doc/ChangeLog b/doc/ChangeLog index e93edf120..9beb30ef7 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -17,6 +17,8 @@ sqlmap (0.6.4-1) stable; urgency=low --is-dba query at the moment; * Major bug fix to avoid tracebacks when multiple targets are specified and one of them is not reachable; + * Minor bug fix to make the Partial UNION query SQL injection technique + work properly also on Oracle and Microsoft SQL Server; * Minor bug fix to make the --postfix work even if --prefix is not provided; diff --git a/lib/core/agent.py b/lib/core/agent.py index 178562570..a006c98e0 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -416,10 +416,6 @@ class Agent: 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" @@ -461,19 +457,20 @@ class Agent: limitStr = queries[kb.dbms].limit % (num, 1) limitedQuery += " %s" % limitStr - # TODO: fix Partial UNION query SQL injection technique for Oracle elif kb.dbms == "Oracle": + if " ORDER BY " in limitedQuery and "(SELECT " in limitedQuery: + limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] + if query.startswith("SELECT "): limitedQuery = "%s FROM (%s, %s" % (untilFrom, untilFrom, limitStr) else: - limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, field, limitStr) + limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, ", ".join(f for f in field), limitStr) limitedQuery = limitedQuery % fromFrom limitedQuery += "=%d" % (num + 1) elif kb.dbms == "Microsoft SQL Server": - if re.search(" ORDER BY ", limitedQuery, re.I): - untilOrderChar = limitedQuery.index(" ORDER BY ") - limitedQuery = limitedQuery[:untilOrderChar] + if " ORDER BY " in limitedQuery: + limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1) limitedQuery = "%s WHERE %s " % (limitedQuery, field) diff --git a/lib/core/settings.py b/lib/core/settings.py index 9bc154fde..844b5e7b2 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -74,6 +74,7 @@ SQL_STATEMENTS = { "SQL SELECT statement": ( "select ", " from ", + " from dual", " where ", " group by ", " order by ", diff --git a/lib/request/inject.py b/lib/request/inject.py index 4a6c12e75..bcaa64080 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -82,12 +82,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl 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) + output = resume(expressionReplaced, payload) if not output or ( expected == "int" and not output.isdigit() ): if output: @@ -326,6 +321,9 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None) value = None if inband and conf.unionUse and kb.dbms: + if kb.dbms == "Oracle" and " ORDER BY " in expression: + expression = expression[:expression.index(" ORDER BY ")] + value = __goInband(expression, expected) if not value: diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 8cac31351..d4b8418df 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -261,12 +261,19 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False): return for num in xrange(startLimit, stopLimit): - orderBy = re.search(" ORDER BY ([\w\_]+)", expression, re.I) + if kb.dbms == "Microsoft SQL Server": + orderBy = re.search(" ORDER BY ([\w\_]+)", expression, re.I) + + if orderBy: + field = orderBy.group(1) + else: + field = expressionFieldsList[0] + + elif kb.dbms == "Oracle": + field = expressionFieldsList - if orderBy: - field = orderBy.group(1) else: - field = expressionFieldsList[0] + field = None limitedExpr = agent.limitQuery(num, expression, field) output = unionUse(limitedExpr, direct=True, unescape=False)