Updated to sqlmap 0.7 release candidate 1

This commit is contained in:
Bernardo Damele
2009-04-22 11:48:07 +00:00
parent b997df740a
commit 8c0ac767f4
129 changed files with 8386 additions and 1388 deletions

View File

@@ -5,8 +5,8 @@ $Id$
This file is part of the sqlmap project, http://sqlmap.sourceforge.net.
Copyright (c) 2006-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
and Daniele Bellucci <daniele.bellucci@gmail.com>
Copyright (c) 2007-2009 Bernardo Damele A. G. <bernardo.damele@gmail.com>
Copyright (c) 2006 Daniele Bellucci <daniele.bellucci@gmail.com>
sqlmap is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
@@ -39,7 +39,6 @@ from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.data import temp
from lib.core.settings import SECONDS
from lib.request.connect import Connect as Request
from lib.techniques.inband.union.use import unionUse
from lib.techniques.blind.inference import bisection
@@ -47,7 +46,7 @@ from lib.utils.resume import queryOutputLength
from lib.utils.resume import resume
def __goInference(payload, expression):
def __goInference(payload, expression, charsetType=None):
start = time.time()
if ( conf.eta or conf.threads > 1 ) and kb.dbms:
@@ -57,20 +56,20 @@ def __goInference(payload, expression):
dataToSessionFile("[%s][%s][%s][%s][" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], expression))
count, value = bisection(payload, expression, length=length)
count, value = bisection(payload, expression, length, charsetType)
duration = int(time.time() - start)
if conf.eta and length:
infoMsg = "retrieved: %s" % value
logger.info(infoMsg)
infoMsg = "performed %d queries in %d seconds" % (count, duration)
logger.info(infoMsg)
debugMsg = "performed %d queries in %d seconds" % (count, duration)
logger.debug(debugMsg)
return value
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None):
def __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected=None, num=None, resumeValue=True, charsetType=None):
outputs = []
origExpr = None
@@ -89,7 +88,8 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
else:
expressionReplaced = expression.replace(expressionFields, field, 1)
output = resume(expressionReplaced, payload)
if resumeValue == True:
output = resume(expressionReplaced, payload)
if not output or ( expected == "int" and not output.isdigit() ):
if output:
@@ -97,7 +97,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
warnMsg += "sqlmap is going to retrieve the value again"
logger.warn(warnMsg)
output = __goInference(payload, expressionReplaced)
output = __goInference(payload, expressionReplaced, charsetType)
if isinstance(num, int):
expression = origExpr
@@ -107,7 +107,7 @@ def __goInferenceFields(expression, expressionFields, expressionFieldsList, payl
return outputs
def __goInferenceProxy(expression, fromUser=False, expected=None):
def __goInferenceProxy(expression, fromUser=False, expected=None, batch=False, resumeValue=True, unpack=True, charsetType=None):
"""
Retrieve the output of a SQL query characted by character taking
advantage of an blind SQL injection vulnerability on the affected
@@ -125,13 +125,19 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
untilLimitChar = None
untilOrderChar = None
output = resume(expression, payload)
if resumeValue == True:
output = resume(expression, payload)
else:
output = None
if output and ( expected == None or ( expected == "int" and output.isdigit() ) ):
return output
if unpack == False:
return __goInference(payload, expression, charsetType)
if kb.dbmsDetected:
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(expression)
if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. "
@@ -200,6 +206,8 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
if not stopLimit or stopLimit <= 1:
if kb.dbms == "Oracle" and expression.endswith("FROM DUAL"):
test = "n"
elif batch == True:
test = "y"
else:
message = "can the SQL query provided return "
message += "multiple entries? [Y/n] "
@@ -214,54 +222,58 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
untilOrderChar = countedExpression.index(" ORDER BY ")
countedExpression = countedExpression[:untilOrderChar]
count = resume(countedExpression, payload)
if resumeValue == True:
count = resume(countedExpression, payload)
if not stopLimit:
if not count or not count.isdigit():
count = __goInference(payload, countedExpression)
count = __goInference(payload, countedExpression, charsetType)
if count and count.isdigit() and int(count) > 0:
count = int(count)
message = "the SQL query provided can return "
message += "up to %d entries. How many " % count
message += "entries do you want to retrieve?\n"
message += "[a] All (default)\n[#] Specific number\n"
message += "[q] Quit\nChoice: "
test = readInput(message, default="a")
if not test or test[0] in ("a", "A"):
if batch == True:
stopLimit = count
else:
message = "the SQL query provided can return "
message += "up to %d entries. How many " % count
message += "entries do you want to retrieve?\n"
message += "[a] All (default)\n[#] Specific number\n"
message += "[q] Quit"
test = readInput(message, default="a")
elif test[0] in ("q", "Q"):
return "Quit"
if not test or test[0] in ("a", "A"):
stopLimit = count
elif test.isdigit() and int(test) > 0 and int(test) <= count:
stopLimit = int(test)
elif test[0] in ("q", "Q"):
return "Quit"
infoMsg = "sqlmap is now going to retrieve the "
infoMsg += "first %d query output entries" % stopLimit
logger.info(infoMsg)
elif test.isdigit() and int(test) > 0 and int(test) <= count:
stopLimit = int(test)
elif test[0] in ("#", "s", "S"):
message = "How many? "
stopLimit = readInput(message, default="10")
infoMsg = "sqlmap is now going to retrieve the "
infoMsg += "first %d query output entries" % stopLimit
logger.info(infoMsg)
if not stopLimit.isdigit():
elif test[0] in ("#", "s", "S"):
message = "How many? "
stopLimit = readInput(message, default="10")
if not stopLimit.isdigit():
errMsg = "Invalid choice"
logger.error(errMsg)
return None
else:
stopLimit = int(stopLimit)
else:
errMsg = "Invalid choice"
logger.error(errMsg)
return None
else:
stopLimit = int(stopLimit)
else:
errMsg = "Invalid choice"
logger.error(errMsg)
return None
elif count and not count.isdigit():
warnMsg = "it was not possible to count the number "
warnMsg += "of entries for the SQL query provided. "
@@ -286,7 +298,7 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
return None
for num in xrange(startLimit, stopLimit):
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num)
output = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, num, resumeValue=resumeValue, charsetType=charsetType)
outputs.append(output)
return outputs
@@ -294,17 +306,17 @@ def __goInferenceProxy(expression, fromUser=False, expected=None):
elif kb.dbms == "Oracle" and expression.startswith("SELECT ") and " FROM " not in expression:
expression = "%s FROM DUAL" % expression
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected)
outputs = __goInferenceFields(expression, expressionFields, expressionFieldsList, payload, expected, resumeValue=resumeValue, charsetType=charsetType)
returnValue = ", ".join([output for output in outputs])
else:
returnValue = __goInference(payload, expression)
returnValue = __goInference(payload, expression, charsetType)
return returnValue
def __goInband(expression, expected=None):
def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True):
"""
Retrieve the output of a SQL query taking advantage of an inband SQL
injection vulnerability on the affected parameter.
@@ -319,22 +331,22 @@ def __goInband(expression, expected=None):
and expression in kb.resumedQueries[conf.url].keys()
)
if condition:
if condition and resumeValue == True:
output = resume(expression, None)
if not output or ( expected == "int" and not output.isdigit() ):
partial = True
if not output:
output = unionUse(expression, resetCounter=True)
output = unionUse(expression, resetCounter=True, unpack=unpack)
if output:
data = parseUnionPage(output, expression, partial, condition)
data = parseUnionPage(output, expression, partial, condition, sort)
return data
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None):
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None):
"""
Called each time sqlmap inject a SQL query on the SQL injection
affected parameter. It can call a function to retrieve the output
@@ -346,11 +358,11 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
expression = expandAsteriskForColumns(expression)
value = None
if inband and conf.unionUse and kb.dbms:
if inband and kb.unionPosition:
if kb.dbms == "Oracle" and " ORDER BY " in expression:
expression = expression[:expression.index(" ORDER BY ")]
value = __goInband(expression, expected)
value = __goInband(expression, expected, sort, resumeValue, unpack)
if not value:
warnMsg = "for some reasons it was not possible to retrieve "
@@ -358,25 +370,30 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None)
warnMsg += "technique, sqlmap is going blind"
logger.warn(warnMsg)
conf.paramNegative = False
oldParamFalseCond = conf.paramFalseCond
oldParamNegative = conf.paramNegative
conf.paramFalseCond = False
conf.paramNegative = False
if blind and not value:
value = __goInferenceProxy(expression, fromUser, expected)
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType)
conf.paramFalseCond = oldParamFalseCond
conf.paramNegative = oldParamNegative
return value
def goStacked(expression):
"""
TODO: write description
"""
def goStacked(expression, silent=False):
expression = cleanQuery(expression)
debugMsg = "query: %s" % expression
logger.debug(debugMsg)
comment = queries[kb.dbms].comment
query = agent.prefixQuery("; %s" % expression)
query = agent.postfixQuery("%s;%s" % (query, comment))
payload = agent.payload(newValue=query)
page, _ = Request.queryPage(payload, content=True)
page, _ = Request.queryPage(payload, content=True, silent=silent)
return payload, page