diff --git a/doc/THANKS b/doc/THANKS index 55c8e6a5b..b71788c09 100644 --- a/doc/THANKS +++ b/doc/THANKS @@ -127,7 +127,8 @@ M Simkin for suggesting a feature Konrads Smelkovs - for reporting two bugs in --sql-shell and --sql-query + for reporting a few bugs in --sql-shell and --sql-query on Microsoft + SQL Server Jason Swan for reporting a bug when enumerating columns on Microsoft SQL Server diff --git a/lib/core/agent.py b/lib/core/agent.py index 5c0de2c75..cc28021da 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -471,10 +471,26 @@ class Agent: limitedQuery += "=%d" % (num + 1) elif kb.dbms == "Microsoft SQL Server": + forgeNotIn = True + if " ORDER BY " in limitedQuery: limitedQuery = limitedQuery[:limitedQuery.index(" ORDER BY ")] - if not limitedQuery.startswith("SELECT TOP ") and not limitedQuery.startswith("TOP "): + if limitedQuery.startswith("SELECT TOP ") or limitedQuery.startswith("TOP "): + topNums = re.search(queries[kb.dbms].limitregexp, limitedQuery, re.I) + + if topNums: + topNums = topNums.groups() + quantityTopNums = topNums[0] + limitedQuery = limitedQuery.replace("TOP %s" % quantityTopNums, "TOP 1", 1) + startTopNums = topNums[1] + limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num) + forgeNotIn = False + else: + topNum = re.search("TOP\s+([\d]+)\s+", limitedQuery, re.I).group(1) + limitedQuery = limitedQuery.replace("TOP %s " % topNum, "") + + if forgeNotIn == True: limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1) if " WHERE " in limitedQuery: limitedQuery = "%s AND %s " % (limitedQuery, field) @@ -482,12 +498,6 @@ class Agent: limitedQuery = "%s WHERE %s " % (limitedQuery, field) limitedQuery += "NOT IN (%s" % (limitStr % num) limitedQuery += "%s %s)" % (field, fromFrom) - else: - topNums = re.search("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("TOP %s" % quantityTopNums, "TOP 1", 1) - startTopNums = topNums[1] - limitedQuery = limitedQuery.replace(" (SELECT TOP %s" % startTopNums, " (SELECT TOP %d" % num) return limitedQuery diff --git a/lib/core/settings.py b/lib/core/settings.py index fb5f040ca..6597a63eb 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -30,7 +30,7 @@ import sys # sqlmap version and site -VERSION = "0.6.4-rc5" +VERSION = "0.6.4-rc6" VERSION_STRING = "sqlmap/%s" % VERSION SITE = "http://sqlmap.sourceforge.net" @@ -73,7 +73,7 @@ MATCH_RATIO = 0.9 SQL_STATEMENTS = { "SQL SELECT statement": ( "select ", - "select top ", + " top ", " from ", " from dual", " where ", diff --git a/lib/request/inject.py b/lib/request/inject.py index c02cc150a..37fd0bdcc 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -147,8 +147,9 @@ def __goInferenceProxy(expression, fromUser=False, expected=None): # can return multiple entries if fromUser and " FROM " in expression: limitRegExp = re.search(queries[kb.dbms].limitregexp, expression, re.I) + topLimit = re.search("TOP\s+([\d]+)\s+", expression, re.I) - if limitRegExp: + if limitRegExp or ( kb.dbms == "Microsoft SQL Server" and topLimit ): if kb.dbms in ( "MySQL", "PostgreSQL" ): limitGroupStart = queries[kb.dbms].limitgroupstart limitGroupStop = queries[kb.dbms].limitgroupstop @@ -160,14 +161,19 @@ def __goInferenceProxy(expression, fromUser=False, expected=None): limitCond = int(stopLimit) > 1 elif kb.dbms == "Microsoft SQL Server": - limitGroupStart = queries[kb.dbms].limitgroupstart - limitGroupStop = queries[kb.dbms].limitgroupstop + if limitRegExp: + limitGroupStart = queries[kb.dbms].limitgroupstart + limitGroupStop = queries[kb.dbms].limitgroupstop - if limitGroupStart.isdigit(): - startLimit = int(limitRegExp.group(int(limitGroupStart))) + if limitGroupStart.isdigit(): + startLimit = int(limitRegExp.group(int(limitGroupStart))) - stopLimit = limitRegExp.group(int(limitGroupStop)) - limitCond = int(stopLimit) > 1 + stopLimit = limitRegExp.group(int(limitGroupStop)) + limitCond = int(stopLimit) > 1 + elif topLimit: + startLimit = 0 + stopLimit = int(topLimit.group(1)) + limitCond = int(stopLimit) > 1 elif kb.dbms == "Oracle": limitCond = False