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

Skip to content

Commit b5e4593

Browse files
committed
sqlmap premiere of blind time based query/bisection
1 parent ad00fe1 commit b5e4593

2 files changed

Lines changed: 82 additions & 11 deletions

File tree

lib/request/inject.py

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
9999
parameter through a bisection algorithm.
100100
"""
101101

102-
if kb.injection.data[1].vector is not None:
103-
vector = agent.cleanupPayload(kb.injection.data[1].vector)
104-
kb.pageTemplate = getPageTemplate(kb.injection.data[1].templatePayload, kb.injection.place)
102+
if kb.technique and kb.injection.data[kb.technique].vector is not None:
103+
vector = agent.cleanupPayload(kb.injection.data[kb.technique].vector)
104+
kb.pageTemplate = getPageTemplate(kb.injection.data[kb.technique].templatePayload, kb.injection.place)
105105
else:
106106
vector = queries[kb.misc.testedDbms].inference.query
107107
kb.pageTemplate = kb.originalPage
@@ -336,6 +336,72 @@ def __goError(expression, resumeValue=True):
336336

337337
return result
338338

339+
def __goTimeBlind(expression, resumeValue=True):
340+
"""
341+
Retrieve the output of a SQL query taking advantage of an error-based
342+
SQL injection vulnerability on the affected parameter.
343+
"""
344+
345+
result = None
346+
347+
if conf.direct:
348+
return direct(expression), None
349+
350+
condition = (
351+
kb.resumedQueries and conf.url in kb.resumedQueries.keys()
352+
and expression in kb.resumedQueries[conf.url].keys()
353+
)
354+
355+
if condition and resumeValue:
356+
result = resume(expression, None)
357+
358+
if not result:
359+
result = timeBlindUse(expression)
360+
dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.url, kb.injection.place, conf.parameters[kb.injection.place], expression, replaceNewlineTabs(result)))
361+
362+
return result
363+
364+
def timeBlindUse(expression):
365+
"""
366+
Retrieve the output of a SQL query taking advantage of an error SQL
367+
injection vulnerability on the affected parameter.
368+
"""
369+
370+
output = None
371+
import pdb
372+
pdb.set_trace()
373+
vector = agent.cleanupPayload(kb.injection.data[5].vector)
374+
query = unescaper.unescape(vector)
375+
query = agent.prefixQuery(query)
376+
query = agent.suffixQuery(query)
377+
check = "%s(?P<result>.*?)%s" % (kb.misc.start, kb.misc.stop)
378+
379+
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
380+
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
381+
382+
if kb.dbms == DBMS.MYSQL:
383+
nulledCastedField = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'
384+
385+
expression = expression.replace(fieldToCastStr, nulledCastedField, 1)
386+
expression = unescaper.unescape(expression)
387+
expression = safeStringFormat(query, expression)
388+
389+
debugMsg = "query: %s" % expression
390+
logger.debug(debugMsg)
391+
392+
payload = agent.payload(newValue=expression)
393+
reqBody, _ = Request.queryPage(payload, content=True)
394+
output = extractRegexResult(check, reqBody, re.DOTALL | re.IGNORECASE)
395+
396+
if output:
397+
output = output.replace(kb.misc.space, " ")
398+
399+
if conf.verbose > 0:
400+
infoMsg = "retrieved: %s" % replaceNewlineTabs(output, stdout=True)
401+
logger.info(infoMsg)
402+
403+
return output
404+
339405
def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True, dump=False):
340406
"""
341407
Retrieve the output of a SQL query taking advantage of an inband SQL
@@ -365,7 +431,7 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr
365431

366432
return data
367433

368-
def getValue(expression, blind=True, inband=True, error=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=False):
434+
def getValue(expression, blind=True, inband=True, error=True, time=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=False):
369435
"""
370436
Called each time sqlmap inject a SQL query on the SQL injection
371437
affected parameter. It can call a function to retrieve the output
@@ -379,7 +445,7 @@ def getValue(expression, blind=True, inband=True, error=True, fromUser=False, ex
379445

380446
if conf.direct:
381447
value = direct(expression)
382-
elif kb.booleanTest is not None or kb.errorTest is not None or kb.unionTest is not None:
448+
elif kb.booleanTest is not None or kb.errorTest is not None or kb.unionTest is not None or kb.timeTest is not None:
383449
expression = cleanQuery(expression)
384450
expression = expandAsteriskForColumns(expression)
385451
value = None
@@ -412,6 +478,10 @@ def getValue(expression, blind=True, inband=True, error=True, fromUser=False, ex
412478
kb.technique = 1
413479
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar)
414480

481+
if time and kb.timeTest and not value:
482+
kb.technique = 5
483+
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar)
484+
415485
kb.unionNegative = oldParamNegative
416486

417487
if value and isinstance(value, basestring):

lib/techniques/blind/inference.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
4444
partialValue = ""
4545
finalValue = ""
4646
asciiTbl = getCharset(charsetType)
47+
timeBasedCompare = (kb.technique == 5)
4748

4849
# Set kb.partRun in case "common prediction" feature (a.k.a. "good
4950
# samaritan") is used
@@ -122,7 +123,7 @@ def tryHint(idx):
122123

123124
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, posValue))
124125
queriesCount[0] += 1
125-
result = Request.queryPage(forgedPayload)
126+
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare)
126127

127128
if result:
128129
return hintValue[idx-1]
@@ -153,7 +154,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
153154
if len(charTbl) == 1:
154155
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, charTbl[0]))
155156
queriesCount[0] += 1
156-
result = Request.queryPage(forgedPayload)
157+
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare)
157158

158159
if result:
159160
return chr(charTbl[0]) if charTbl[0] < 128 else unichr(charTbl[0])
@@ -174,7 +175,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
174175
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
175176

176177
queriesCount[0] += 1
177-
result = Request.queryPage(forgedPayload)
178+
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare)
178179

179180
if kb.dbms in (DBMS.SQLITE, DBMS.MAXDB):
180181
posValue = popValue()
@@ -226,7 +227,7 @@ def getChar(idx, charTbl=asciiTbl, continuousOrder=True, expand=charsetType is N
226227
for retVal in (originalTbl[originalTbl.index(minValue)], originalTbl[originalTbl.index(minValue) + 1]):
227228
forgedPayload = safeStringFormat(payload.replace('%3E', '%3D'), (expressionUnescaped, idx, retVal))
228229
queriesCount[0] += 1
229-
result = Request.queryPage(forgedPayload)
230+
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare)
230231

231232
if result:
232233
return chr(retVal) if retVal < 128 else unichr(retVal)
@@ -444,7 +445,7 @@ def downloadThread():
444445
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (expressionUnescaped, testValue)))
445446
query = agent.suffixQuery(query)
446447
queriesCount[0] += 1
447-
result = Request.queryPage(agent.payload(newValue=query))
448+
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare)
448449

449450
# Did we have luck?
450451
if result:
@@ -468,7 +469,7 @@ def downloadThread():
468469
query = agent.prefixQuery(safeStringFormat("AND (%s) = %s", (subquery, testValue)))
469470
query = agent.suffixQuery(query)
470471
queriesCount[0] += 1
471-
result = Request.queryPage(agent.payload(newValue=query))
472+
result = Request.queryPage(agent.payload(newValue=query), timeBasedCompare=timeBasedCompare)
472473

473474
# Did we have luck?
474475
if result:

0 commit comments

Comments
 (0)