mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-01-24 08:14:24 +03:00
Major bug fix to make it work properly with MSSQL custom limited (SELECT
TOP ...) queries with both inferential blind and Full UNION query injection
This commit is contained in:
parent
2cc3bb2f6a
commit
9c42a883be
|
@ -285,7 +285,7 @@ class Agent:
|
|||
if query.startswith("SELECT ") and "(SELECT " in query:
|
||||
fieldsSelectFrom = None
|
||||
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsToCastList, fieldsToCastStr
|
||||
return fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsToCastList, fieldsToCastStr
|
||||
|
||||
|
||||
def concatQuery(self, query):
|
||||
|
@ -317,7 +317,7 @@ class Agent:
|
|||
concatQuery = ""
|
||||
query = query.replace(", ", ",")
|
||||
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, _, fieldsToCastStr = self.getFields(query)
|
||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, _, fieldsToCastStr = self.getFields(query)
|
||||
castedFields = self.nullCastConcatFields(fieldsToCastStr)
|
||||
concatQuery = query.replace(fieldsToCastStr, castedFields, 1)
|
||||
|
||||
|
@ -348,7 +348,11 @@ class Agent:
|
|||
concatQuery += " FROM DUAL"
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
if fieldsSelectFrom:
|
||||
if fieldsSelectTop:
|
||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatQuery, re.I).group(1)
|
||||
concatQuery = concatQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, temp.start), 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelectFrom:
|
||||
concatQuery = concatQuery.replace("SELECT ", "'%s'+" % temp.start, 1)
|
||||
concatQuery = concatQuery.replace(" FROM ", "+'%s' FROM " % temp.stop, 1)
|
||||
elif fieldsSelect:
|
||||
|
@ -393,6 +397,11 @@ class Agent:
|
|||
|
||||
inbandQuery = self.prefixQuery(" UNION ALL SELECT ")
|
||||
|
||||
if query.startswith("TOP"):
|
||||
topNum = re.search("\ATOP\s+([\d]+)\s+", query, re.I).group(1)
|
||||
query = query[len("TOP %s " % topNum):]
|
||||
inbandQuery += "TOP %s " % topNum
|
||||
|
||||
if not exprPosition:
|
||||
exprPosition = kb.unionPosition
|
||||
|
||||
|
@ -472,10 +481,17 @@ class Agent:
|
|||
if " ORDER BY " in limitedQuery:
|
||||
limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")]
|
||||
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
limitedQuery = "%s WHERE %s " % (limitedQuery, field)
|
||||
limitedQuery += "NOT IN (%s" % (limitStr % num)
|
||||
limitedQuery += "%s %s)" % (field, fromFrom)
|
||||
if not limitedQuery.startswith("SELECT TOP "):
|
||||
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
|
||||
limitedQuery = "%s WHERE %s " % (limitedQuery, field)
|
||||
limitedQuery += "NOT IN (%s" % (limitStr % num)
|
||||
limitedQuery += "%s %s)" % (field, fromFrom)
|
||||
else:
|
||||
topNums = re.search("\ASELECT\s+TOP\s+([\d]+)\s+.+?\s+FROM\s+.+?\s+WHERE\s+.+?\s+NOT\s+IN\s+\(SELECT\s+TOP\s+([\d]+)\s+", limitedQuery, re.I).groups()
|
||||
quantityTopNums = topNums[0]
|
||||
limitedQuery = limitedQuery.replace("SELECT TOP %s" % quantityTopNums, "SELECT TOP 1", 1)
|
||||
startTopNums = topNums[1]
|
||||
limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num)
|
||||
|
||||
return limitedQuery
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import sys
|
|||
|
||||
|
||||
# sqlmap version and site
|
||||
VERSION = "0.6.4-rc3"
|
||||
VERSION = "0.6.4-rc4"
|
||||
VERSION_STRING = "sqlmap/%s" % VERSION
|
||||
SITE = "http://sqlmap.sourceforge.net"
|
||||
|
||||
|
@ -73,6 +73,7 @@ MATCH_RATIO = 0.9
|
|||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
"select ",
|
||||
"select top ",
|
||||
" from ",
|
||||
" from dual",
|
||||
" where ",
|
||||
|
|
|
@ -81,7 +81,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
|
|||
continue
|
||||
|
||||
if isinstance(num, int):
|
||||
origExpr = expression
|
||||
origExpr = expression
|
||||
expression = agent.limitQuery(num, expression, field)
|
||||
|
||||
if "ROWNUM" in expressionFieldsList:
|
||||
|
@ -89,7 +89,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
|
|||
else:
|
||||
expressionReplaced = expression
|
||||
|
||||
output = resume(expressionReplaced, payload)
|
||||
output = resume(expressionReplaced, payload)
|
||||
|
||||
if not output or ( expected == "int" and not output.isdigit() ):
|
||||
if output:
|
||||
|
@ -131,7 +131,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
return output
|
||||
|
||||
if kb.dbmsDetected:
|
||||
_, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
|
||||
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
|
||||
|
||||
if len(expressionFieldsList) > 1:
|
||||
infoMsg = "the SQL query provided has more than a field. "
|
||||
|
@ -159,7 +159,17 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||
limitCond = int(stopLimit) > 1
|
||||
|
||||
elif kb.dbms in ( "Oracle", "Microsoft SQL Server" ):
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
limitGroupStart = queries[kb.dbms].limitgroupstart
|
||||
limitGroupStop = queries[kb.dbms].limitgroupstop
|
||||
|
||||
if limitGroupStart.isdigit():
|
||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||
|
||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||
limitCond = int(stopLimit) > 1
|
||||
|
||||
elif kb.dbms == "Oracle":
|
||||
limitCond = False
|
||||
else:
|
||||
limitCond = True
|
||||
|
@ -178,6 +188,9 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
|
|||
untilLimitChar = expression.index(queries[kb.dbms].limitstring)
|
||||
expression = expression[:untilLimitChar]
|
||||
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
stopLimit += startLimit
|
||||
|
||||
if not stopLimit or stopLimit <= 1:
|
||||
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
|
||||
test = "n"
|
||||
|
|
|
@ -54,12 +54,12 @@ def bisection(payload, expression, length=None):
|
|||
finalValue = ""
|
||||
|
||||
if kb.dbmsDetected:
|
||||
_, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expressionUnescaped = unescaper.unescape(expressionReplaced)
|
||||
_, _, _, _, _, fieldToCastStr = agent.getFields(expression)
|
||||
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
|
||||
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
|
||||
expressionUnescaped = unescaper.unescape(expressionReplaced)
|
||||
else:
|
||||
expressionUnescaped = unescaper.unescape(expression)
|
||||
expressionUnescaped = unescaper.unescape(expression)
|
||||
|
||||
infoMsg = "query: %s" % expressionUnescaped
|
||||
logger.info(infoMsg)
|
||||
|
|
|
@ -159,7 +159,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
conf.paramNegative = True
|
||||
|
||||
if conf.paramNegative == True and direct == False:
|
||||
_, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
||||
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
||||
|
||||
if len(expressionFieldsList) > 1:
|
||||
infoMsg = "the SQL query provided has more than a field. "
|
||||
|
@ -187,7 +187,17 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||
limitCond = int(stopLimit) > 1
|
||||
|
||||
elif kb.dbms in ( "Oracle", "Microsoft SQL Server" ):
|
||||
elif kb.dbms == "Microsoft SQL Server":
|
||||
limitGroupStart = queries[kb.dbms].limitgroupstart
|
||||
limitGroupStop = queries[kb.dbms].limitgroupstop
|
||||
|
||||
if limitGroupStart.isdigit():
|
||||
startLimit = int(limitRegExp.group(int(limitGroupStart)))
|
||||
|
||||
stopLimit = limitRegExp.group(int(limitGroupStop))
|
||||
limitCond = int(stopLimit) > 1
|
||||
|
||||
elif kb.dbms == "Oracle":
|
||||
limitCond = False
|
||||
else:
|
||||
limitCond = True
|
||||
|
@ -287,7 +297,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
|
|||
|
||||
else:
|
||||
# Forge the inband SQL injection request
|
||||
query = agent.forgeInbandQuery(expression)
|
||||
query = agent.forgeInbandQuery(expression)
|
||||
payload = agent.payload(newValue=query)
|
||||
|
||||
infoMsg = "query: %s" % query
|
||||
|
|
Loading…
Reference in New Issue
Block a user