Skip to content

Commit 206191d

Browse files
committed
Major bug fix so that when the expected value of a query (count variable)
is an integer and for some reason the resumed value from session file is a string or a binary file, the query is executed again and and its new output saved to the session file
1 parent 03b90e0 commit 206191d

File tree

2 files changed

+31
-26
lines changed

2 files changed

+31
-26
lines changed

lib/request/inject.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def __goInference(payload, expression):
7171
return value
7272

7373

74-
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload):
74+
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None):
7575
outputs = []
7676

7777
for field in expressionFieldsList:
@@ -80,15 +80,20 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
8080
expressionReplaced = expression.replace(expressionFields, field, 1)
8181
output = resume(expressionReplaced, payload)
8282

83-
if not output:
83+
if not output or ( expected == "int" and not output.isdigit() ):
84+
if output:
85+
warnMsg = "expected value type %s, resumed '%s', " % (expected, output)
86+
warnMsg += "sqlmap is going to retrieve the value again"
87+
logger.warn(warnMsg)
88+
8489
output = __goInference(payload, expressionReplaced)
8590

8691
outputs.append(output)
8792

8893
return outputs
8994

9095

91-
def __goInferenceProxy(expression, fromUser=False):
96+
def __goInferenceProxy(expression, fromUser=False, expected=None):
9297
"""
9398
Retrieve the output of a SQL query characted by character taking
9499
advantage of an blind SQL injection vulnerability on the affected
@@ -108,7 +113,7 @@ def __goInferenceProxy(expression, fromUser=False):
108113

109114
output = resume(expression, payload)
110115

111-
if output:
116+
if output and ( expected == None or ( expected == "int" and output.isdigit() ) ):
112117
return output
113118

114119
if kb.dbmsDetected:
@@ -179,7 +184,7 @@ def __goInferenceProxy(expression, fromUser=False):
179184
count = resume(countedExpression, payload)
180185

181186
if not stopLimit:
182-
if not count:
187+
if not count or not count.isdigit():
183188
count = __goInference(payload, countedExpression)
184189

185190
if count.isdigit() and int(count) > 0:
@@ -268,15 +273,15 @@ def __goInferenceProxy(expression, fromUser=False):
268273
limitedExpr += "NOT IN (%s" % (limitStr % num)
269274
limitedExpr += "%s %s)" % (expressionFieldsList[0], fromFrom)
270275

271-
output = __goInferenceFields(limitedExpr, expressionFields, expressionFieldsList, payload)
276+
output = __goInferenceFields(limitedExpr, expressionFields, expressionFieldsList, payload, expected)
272277
outputs.append(output)
273278

274279
return outputs
275280

276281
elif kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
277282
expression = "%s FROM DUAL" % expression
278283

279-
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload)
284+
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected)
280285

281286
returnValue = ", ".join([output for output in outputs])
282287
else:
@@ -285,7 +290,7 @@ def __goInferenceProxy(expression, fromUser=False):
285290
return returnValue
286291

287292

288-
def __goInband(expression):
293+
def __goInband(expression, expected=None):
289294
"""
290295
Retrieve the output of a SQL query taking advantage of an inband SQL
291296
injection vulnerability on the affected parameter.
@@ -304,7 +309,7 @@ def __goInband(expression):
304309
if condition:
305310
output = resume(expression, None)
306311

307-
if not output:
312+
if not output or ( expected == "int" and not output.isdigit() ):
308313
partial = True
309314

310315
if not output:
@@ -355,7 +360,7 @@ def __goInband(expression):
355360
return data
356361

357362

358-
def getValue(expression, blind=True, inband=True, fromUser=False):
363+
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None):
359364
"""
360365
Called each time sqlmap inject a SQL query on the SQL injection
361366
affected parameter. It can call a function to retrieve the output
@@ -368,9 +373,9 @@ def getValue(expression, blind=True, inband=True, fromUser=False):
368373
value = None
369374

370375
if inband and conf.unionUse and kb.dbms:
371-
value = __goInband(expression)
376+
value = __goInband(expression, expected)
372377

373378
if blind and not value:
374-
value = __goInferenceProxy(expression, fromUser)
379+
value = __goInferenceProxy(expression, fromUser, expected)
375380

376381
return value

plugins/generic/enumeration.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ def getUsers(self):
135135
query = rootQuery["blind"]["count2"]
136136
else:
137137
query = rootQuery["blind"]["count"]
138-
count = inject.getValue(query, inband=False)
138+
count = inject.getValue(query, inband=False, expected="int")
139139

140-
if not len(count) or count == "0":
140+
if not count.isdigit() or not len(count) or count == "0":
141141
errMsg = "unable to retrieve the number of database users"
142142
raise sqlmapNoneDataException, errMsg
143143

@@ -228,9 +228,9 @@ def getPasswordHashes(self):
228228
query = rootQuery["blind"]["count2"] % user
229229
else:
230230
query = rootQuery["blind"]["count"] % user
231-
count = inject.getValue(query, inband=False)
231+
count = inject.getValue(query, inband=False, expected="int")
232232

233-
if not len(count) or count == "0":
233+
if not count.isdigit() or not len(count) or count == "0":
234234
warnMsg = "unable to retrieve the number of password "
235235
warnMsg += "hashes for user '%s'" % user
236236
logger.warn(warnMsg)
@@ -458,9 +458,9 @@ def getPrivileges(self):
458458
query = rootQuery["blind"]["count"] % (conditionChar, queryUser)
459459
else:
460460
query = rootQuery["blind"]["count"] % queryUser
461-
count = inject.getValue(query, inband=False)
461+
count = inject.getValue(query, inband=False, expected="int")
462462

463-
if not len(count) or count == "0":
463+
if not count.isdigit() or not len(count) or count == "0":
464464
warnMsg = "unable to retrieve the number of "
465465
warnMsg += "privileges for user '%s'" % user
466466
logger.warn(warnMsg)
@@ -572,9 +572,9 @@ def getDbs(self):
572572
query = rootQuery["blind"]["count2"]
573573
else:
574574
query = rootQuery["blind"]["count"]
575-
count = inject.getValue(query, inband=False)
575+
count = inject.getValue(query, inband=False, expected="int")
576576

577-
if not len(count) or count == "0":
577+
if not count.isdigit() or not len(count) or count == "0":
578578
errMsg = "unable to retrieve the number of databases"
579579
raise sqlmapNoneDataException, errMsg
580580

@@ -662,9 +662,9 @@ def getTables(self):
662662
logger.info(logMsg)
663663

664664
query = rootQuery["blind"]["count"] % db
665-
count = inject.getValue(query, inband=False)
665+
count = inject.getValue(query, inband=False, expected="int")
666666

667-
if not len(count) or count == "0":
667+
if not count.isdigit() or not len(count) or count == "0":
668668
warnMsg = "unable to retrieve the number of "
669669
warnMsg += "tables for database '%s'" % db
670670
logger.warn(warnMsg)
@@ -756,9 +756,9 @@ def getColumns(self, onlyColNames=False):
756756
elif kb.dbms == "Microsoft SQL Server":
757757
query = rootQuery["blind"]["count"] % (conf.db, conf.db, conf.tbl)
758758

759-
count = inject.getValue(query, inband=False)
759+
count = inject.getValue(query, inband=False, expected="int")
760760

761-
if not len(count) or count == "0":
761+
if not count.isdigit() or not len(count) or count == "0":
762762
errMsg = "unable to retrieve the number of columns "
763763
errMsg += "for table '%s' " % conf.tbl
764764
errMsg += "on database '%s'" % conf.db
@@ -905,9 +905,9 @@ def dumpTable(self):
905905
query = rootQuery["blind"]["count"] % conf.tbl.upper()
906906
else:
907907
query = rootQuery["blind"]["count"] % (conf.db, conf.tbl)
908-
count = inject.getValue(query, inband=False)
908+
count = inject.getValue(query, inband=False, expected="int")
909909

910-
if not len(count) or count == "0":
910+
if not count.isdigit() or not len(count) or count == "0":
911911
errMsg = "unable to retrieve the number of "
912912
if conf.col:
913913
errMsg += "columns '%s' " % colString

0 commit comments

Comments
 (0)