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

Skip to content

Commit 1f7810e

Browse files
committed
Major bug fix to make partial UNION query sql injection work properly
also on Microsoft SQL Server
1 parent 064029c commit 1f7810e

3 files changed

Lines changed: 50 additions & 25 deletions

File tree

lib/core/agent.py

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, negativ
8181
return retValue
8282

8383

84+
def fullPayload(self, query):
85+
query = self.prefixQuery(query)
86+
query = self.postfixQuery(query)
87+
payload = self.payload(newValue=query)
88+
89+
return payload
90+
91+
8492
def prefixQuery(self, string):
8593
"""
8694
This method defines how the input string has to be escaped
@@ -396,32 +404,32 @@ def forgeInbandQuery(self, query, exprPosition=None):
396404
inbandQuery += ", "
397405

398406
if element == exprPosition:
399-
if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query:
400-
conditionIndex = query.rindex(" FROM ")
401-
inbandQuery += "%s" % query[:conditionIndex]
407+
if " FROM " in query and not query.startswith("SELECT "):
408+
conditionIndex = query.index(" FROM ")
409+
inbandQuery += query[:conditionIndex]
402410
else:
403-
inbandQuery += "%s" % query
411+
inbandQuery += query
404412
else:
405413
inbandQuery += "NULL"
406414

407-
if " FROM " in query and not query.startswith("SELECT ") and not "(SELECT " in query:
408-
conditionIndex = query.rindex(" FROM ")
409-
inbandQuery += "%s" % query[conditionIndex:]
415+
if " FROM " in query and not query.startswith("SELECT "):
416+
conditionIndex = query.index(" FROM ")
417+
inbandQuery += query[conditionIndex:]
418+
419+
if " ORDER BY " in inbandQuery and "(SELECT " in inbandQuery:
420+
orderIndex = inbandQuery.index(" ORDER BY ")
421+
inbandQuery += inbandQuery[orderIndex:].replace(")", "")
410422

411423
if kb.dbms == "Oracle":
412424
if " FROM " not in inbandQuery:
413425
inbandQuery += " FROM DUAL"
414426

415-
if " ORDER BY " in inbandQuery:
416-
orderIndex = inbandQuery.index(" ORDER BY ")
417-
inbandQuery = inbandQuery[:orderIndex]
418-
419427
inbandQuery = self.postfixQuery(inbandQuery, kb.unionComment)
420428

421429
return inbandQuery
422430

423431

424-
def limitQuery(self, num, query, fieldsList=None):
432+
def limitQuery(self, num, query, field):
425433
"""
426434
Take in input a query string and return its limited query string.
427435
@@ -436,8 +444,8 @@ def limitQuery(self, num, query, fieldsList=None):
436444
@param query: query to be processed
437445
@type query: C{str}
438446
439-
@param fieldsList: list of fields within the query
440-
@type fieldsList: C{list}
447+
@param field: field within the query
448+
@type field: C{list}
441449
442450
@return: limited query string
443451
@rtype: C{str}
@@ -453,13 +461,12 @@ def limitQuery(self, num, query, fieldsList=None):
453461
limitStr = queries[kb.dbms].limit % (num, 1)
454462
limitedQuery += " %s" % limitStr
455463

456-
# TODO: fix for Partial UNION query SQL injection technique both
457-
# Oracle and Microsoft SQL Server
464+
# TODO: fix Partial UNION query SQL injection technique for Oracle
458465
elif kb.dbms == "Oracle":
459466
if query.startswith("SELECT "):
460467
limitedQuery = "%s FROM (%s, %s" % (untilFrom, untilFrom, limitStr)
461468
else:
462-
limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, ", ".join(field for field in fieldsList), limitStr)
469+
limitedQuery = "%s FROM (SELECT %s, %s" % (untilFrom, field, limitStr)
463470
limitedQuery = limitedQuery % fromFrom
464471
limitedQuery += "=%d" % (num + 1)
465472

@@ -469,9 +476,9 @@ def limitQuery(self, num, query, fieldsList=None):
469476
limitedQuery = limitedQuery[:untilOrderChar]
470477

471478
limitedQuery = limitedQuery.replace("SELECT ", (limitStr % 1), 1)
472-
limitedQuery = "%s WHERE %s " % (limitedQuery, fieldsList[0])
479+
limitedQuery = "%s WHERE %s " % (limitedQuery, field)
473480
limitedQuery += "NOT IN (%s" % (limitStr % num)
474-
limitedQuery += "%s %s)" % (fieldsList[0], fromFrom)
481+
limitedQuery += "%s %s)" % (field, fromFrom)
475482

476483
return limitedQuery
477484

lib/request/inject.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,23 @@ def __goInference(payload, expression):
7070
return value
7171

7272

73-
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None):
74-
outputs = []
73+
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None):
74+
outputs = []
75+
origExpr = None
7576

7677
for field in expressionFieldsList:
7778
output = None
7879

80+
if isinstance(num, int):
81+
origExpr = expression
82+
expression = agent.limitQuery(num, expression, field)
83+
7984
expressionReplaced = expression.replace(expressionFields, field, 1)
85+
86+
if " ORDER BY " in expressionReplaced and "(SELECT " in expressionReplaced:
87+
orderIndex = expressionReplaced.index(" ORDER BY ")
88+
expressionReplaced += expressionReplaced[orderIndex:].replace(")", "")
89+
8090
output = resume(expressionReplaced, payload)
8191

8292
if not output or ( expected == "int" and not output.isdigit() ):
@@ -87,6 +97,9 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
8797

8898
output = __goInference(payload, expressionReplaced)
8999

100+
if isinstance(num, int):
101+
expression = origExpr
102+
90103
outputs.append(output)
91104

92105
return outputs
@@ -252,9 +265,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
252265
return None
253266

254267
for num in xrange(startLimit, stopLimit):
255-
limitedExpr = agent.limitQuery(num, expression, expressionFieldsList)
256-
257-
output = __goInferenceFields(limitedExpr, expressionFields, expressionFieldsList, payload, expected)
268+
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num)
258269
outputs.append(output)
259270

260271
return outputs

lib/techniques/inband/union/use.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,14 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
261261
return
262262

263263
for num in xrange(startLimit, stopLimit):
264-
limitedExpr = agent.limitQuery(num, expression, expressionFieldsList)
264+
orderBy = re.search(" ORDER BY ([\w\_]+)", expression, re.I)
265+
266+
if orderBy:
267+
field = orderBy.group(1)
268+
else:
269+
field = expressionFieldsList[0]
270+
271+
limitedExpr = agent.limitQuery(num, expression, field)
265272
output = unionUse(limitedExpr, direct=True, unescape=False)
266273

267274
if output:

0 commit comments

Comments
 (0)