2008-10-15 19:38:22 +04:00
#!/usr/bin/env python
"""
2008-10-15 19:56:32 +04:00
$ Id $
2008-10-15 19:38:22 +04:00
2010-10-14 18:41:14 +04:00
Copyright ( c ) 2006 - 2010 sqlmap developers ( http : / / sqlmap . sourceforge . net / )
2010-10-15 03:18:29 +04:00
See the file ' doc/COPYING ' for copying permission
2008-10-15 19:38:22 +04:00
"""
import re
import time
from lib . core . agent import agent
2011-01-28 19:36:09 +03:00
from lib . core . common import Backend
2010-05-13 15:05:35 +04:00
from lib . core . common import calculateDeltaSeconds
2008-10-15 19:38:22 +04:00
from lib . core . common import cleanQuery
from lib . core . common import dataToSessionFile
from lib . core . common import expandAsteriskForColumns
2010-12-15 15:10:33 +03:00
from lib . core . common import getPublicTypeMembers
2010-12-18 12:51:34 +03:00
from lib . core . common import initTechnique
2011-01-19 02:02:11 +03:00
from lib . core . common import isNumPosStrValue
2010-12-15 15:10:33 +03:00
from lib . core . common import isTechniqueAvailable
2008-12-10 20:23:07 +03:00
from lib . core . common import parseUnionPage
2010-10-11 17:52:32 +04:00
from lib . core . common import popValue
from lib . core . common import pushValue
2010-10-20 12:56:58 +04:00
from lib . core . common import randomInt
2008-10-15 19:38:22 +04:00
from lib . core . common import readInput
2010-11-12 14:40:37 +03:00
from lib . core . common import replaceNewlineTabs
2010-10-19 16:02:04 +04:00
from lib . core . common import safeStringFormat
2008-10-15 19:38:22 +04:00
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
from lib . core . data import queries
2010-11-08 12:20:02 +03:00
from lib . core . enums import DBMS
2010-12-10 15:30:36 +03:00
from lib . core . enums import EXPECTED
2010-12-08 16:04:48 +03:00
from lib . core . enums import PAYLOAD
2010-11-29 00:27:47 +03:00
from lib . core . exception import sqlmapNotVulnerableException
2011-01-19 02:02:11 +03:00
from lib . core . exception import sqlmapUserQuitException
from lib . core . settings import FROM_TABLE
2010-12-08 15:49:26 +03:00
from lib . core . settings import MIN_TIME_RESPONSES
2010-12-21 18:26:23 +03:00
from lib . core . settings import MAX_TECHNIQUES_PER_VALUE
2011-01-07 19:39:47 +03:00
from lib . core . threads import getCurrentThreadData
2010-12-10 16:20:59 +03:00
from lib . core . unescaper import unescaper
2008-11-12 03:36:50 +03:00
from lib . request . connect import Connect as Request
2010-03-31 14:50:47 +04:00
from lib . request . direct import direct
2008-10-15 19:38:22 +04:00
from lib . techniques . inband . union . use import unionUse
2008-11-13 02:44:09 +03:00
from lib . techniques . blind . inference import bisection
2010-10-20 13:09:04 +04:00
from lib . techniques . error . use import errorUse
2008-10-15 19:38:22 +04:00
from lib . utils . resume import queryOutputLength
from lib . utils . resume import resume
2009-09-26 03:03:45 +04:00
def __goInference ( payload , expression , charsetType = None , firstChar = None , lastChar = None ) :
2008-11-12 03:36:50 +03:00
start = time . time ( )
2008-10-15 19:38:22 +04:00
2011-01-16 20:52:42 +03:00
timeBasedCompare = ( kb . technique in ( PAYLOAD . TECHNIQUE . TIME , PAYLOAD . TECHNIQUE . STACKED ) )
2011-01-28 19:36:09 +03:00
if ( conf . eta or conf . threads > 1 ) and Backend . getIdentifiedDbms ( ) and not timeBasedCompare :
2008-10-15 19:38:22 +04:00
_ , length , _ = queryOutputLength ( expression , payload )
else :
length = None
2010-11-28 21:10:54 +03:00
dataToSessionFile ( " [ %s ][ %s ][ %s ][ %s ][ " % ( conf . url , kb . injection . place , conf . parameters [ kb . injection . place ] , expression ) )
2008-10-16 19:39:25 +04:00
2009-09-26 03:03:45 +04:00
count , value = bisection ( payload , expression , length , charsetType , firstChar , lastChar )
2008-10-15 19:38:22 +04:00
2010-05-13 15:05:35 +04:00
debugMsg = " performed %d queries in %d seconds " % ( count , calculateDeltaSeconds ( start ) )
2009-04-22 15:48:07 +04:00
logger . debug ( debugMsg )
2008-10-15 19:38:22 +04:00
return value
2009-09-26 03:03:45 +04:00
def __goInferenceFields ( expression , expressionFields , expressionFieldsList , payload , expected = None , num = None , resumeValue = True , charsetType = None , firstChar = None , lastChar = None ) :
2011-01-19 02:02:11 +03:00
outputs = [ ]
origExpr = None
2008-10-15 19:38:22 +04:00
for field in expressionFieldsList :
output = None
2008-12-24 02:34:50 +03:00
if field . startswith ( " ROWNUM " ) :
continue
2008-12-22 22:36:01 +03:00
if isinstance ( num , int ) :
2011-01-19 02:02:11 +03:00
origExpr = expression
2008-12-22 22:36:01 +03:00
expression = agent . limitQuery ( num , expression , field )
2008-12-24 02:34:50 +03:00
if " ROWNUM " in expressionFieldsList :
expressionReplaced = expression
2009-01-23 01:28:27 +03:00
else :
expressionReplaced = expression . replace ( expressionFields , field , 1 )
2008-12-24 02:34:50 +03:00
2010-01-02 05:02:12 +03:00
if resumeValue :
2009-04-22 15:48:07 +04:00
output = resume ( expressionReplaced , payload )
2008-10-15 19:38:22 +04:00
2011-01-19 02:02:11 +03:00
if not output or ( expected == EXPECTED . INT and not output . isdigit ( ) ) :
2008-11-02 22:21:19 +03:00
if output :
2011-01-19 02:02:11 +03:00
warnMsg = " expected value type %s , resumed ' %s ' , " % ( expected , output )
2008-11-02 22:21:19 +03:00
warnMsg + = " sqlmap is going to retrieve the value again "
logger . warn ( warnMsg )
2009-09-26 03:03:45 +04:00
output = __goInference ( payload , expressionReplaced , charsetType , firstChar , lastChar )
2008-10-15 19:38:22 +04:00
2008-12-22 22:36:01 +03:00
if isinstance ( num , int ) :
expression = origExpr
2008-10-15 19:38:22 +04:00
outputs . append ( output )
return outputs
2009-09-26 03:03:45 +04:00
def __goInferenceProxy ( expression , fromUser = False , expected = None , batch = False , resumeValue = True , unpack = True , charsetType = None , firstChar = None , lastChar = None ) :
2008-10-15 19:38:22 +04:00
"""
Retrieve the output of a SQL query characted by character taking
advantage of an blind SQL injection vulnerability on the affected
parameter through a bisection algorithm .
"""
2010-10-25 18:11:47 +04:00
2010-12-18 12:51:34 +03:00
initTechnique ( kb . technique )
2010-12-14 00:33:42 +03:00
vector = agent . cleanupPayload ( kb . injection . data [ kb . technique ] . vector )
query = agent . prefixQuery ( vector )
query = agent . suffixQuery ( query )
payload = agent . payload ( newValue = query )
count = None
startLimit = 0
stopLimit = None
outputs = [ ]
test = None
2008-10-15 19:38:22 +04:00
untilLimitChar = None
untilOrderChar = None
2010-01-02 05:02:12 +03:00
if resumeValue :
2009-04-22 15:48:07 +04:00
output = resume ( expression , payload )
else :
output = None
2008-10-15 19:38:22 +04:00
2011-01-19 02:02:11 +03:00
if output and ( expected is None or ( expected == EXPECTED . INT and output . isdigit ( ) ) ) :
2008-10-15 19:38:22 +04:00
return output
2010-01-02 05:02:12 +03:00
if not unpack :
2009-09-26 03:03:45 +04:00
return __goInference ( payload , expression , charsetType , firstChar , lastChar )
2009-04-22 15:48:07 +04:00
2011-01-20 02:06:15 +03:00
_ , _ , _ , _ , _ , expressionFieldsList , expressionFields , _ = agent . getFields ( expression )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
rdbRegExp = re . search ( " RDB \ $GET_CONTEXT \ ([^)]+ \ ) " , expression , re . I )
2011-01-28 19:36:09 +03:00
if rdbRegExp and Backend . getIdentifiedDbms ( ) == DBMS . FIREBIRD :
2011-01-20 02:06:15 +03:00
expressionFieldsList = [ expressionFields ]
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
if len ( expressionFieldsList ) > 1 :
infoMsg = " the SQL query provided has more than a field. "
infoMsg + = " sqlmap will now unpack it into distinct queries "
infoMsg + = " to be able to retrieve the output even if we "
infoMsg + = " are going blind "
logger . info ( infoMsg )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
# If we have been here from SQL query/shell we have to check if
# the SQL query might return multiple entries and in such case
# forge the SQL limiting the query output one entry per time
# NOTE: I assume that only queries that get data from a table
# can return multiple entries
2011-01-28 19:36:09 +03:00
if fromUser and " FROM " in expression . upper ( ) and ( ( Backend . getIdentifiedDbms ( ) not in FROM_TABLE ) or ( Backend . getIdentifiedDbms ( ) in FROM_TABLE and not expression . upper ( ) . endswith ( FROM_TABLE [ Backend . getIdentifiedDbms ( ) ] ) ) ) :
limitRegExp = re . search ( queries [ Backend . getIdentifiedDbms ( ) ] . limitregexp . query , expression , re . I )
2011-01-20 02:06:15 +03:00
topLimit = re . search ( " TOP \ s+([ \ d]+) \ s+ " , expression , re . I )
2009-02-03 02:44:19 +03:00
2011-01-28 19:36:09 +03:00
if limitRegExp or ( Backend . getIdentifiedDbms ( ) in ( DBMS . MSSQL , DBMS . SYBASE ) and topLimit ) :
if Backend . getIdentifiedDbms ( ) in ( DBMS . MYSQL , DBMS . PGSQL ) :
limitGroupStart = queries [ Backend . getIdentifiedDbms ( ) ] . limitgroupstart . query
limitGroupStop = queries [ Backend . getIdentifiedDbms ( ) ] . limitgroupstop . query
2009-02-03 02:44:19 +03:00
2011-01-20 02:06:15 +03:00
if limitGroupStart . isdigit ( ) :
startLimit = int ( limitRegExp . group ( int ( limitGroupStart ) ) )
2009-01-03 02:26:45 +03:00
2011-01-20 02:06:15 +03:00
stopLimit = limitRegExp . group ( int ( limitGroupStop ) )
limitCond = int ( stopLimit ) > 1
2008-10-15 19:38:22 +04:00
2011-01-28 19:36:09 +03:00
elif Backend . getIdentifiedDbms ( ) in ( DBMS . MSSQL , DBMS . SYBASE ) :
2008-10-15 19:38:22 +04:00
if limitRegExp :
2011-01-28 19:36:09 +03:00
limitGroupStart = queries [ Backend . getIdentifiedDbms ( ) ] . limitgroupstart . query
limitGroupStop = queries [ Backend . getIdentifiedDbms ( ) ] . limitgroupstop . query
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
if limitGroupStart . isdigit ( ) :
startLimit = int ( limitRegExp . group ( int ( limitGroupStart ) ) )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
stopLimit = limitRegExp . group ( int ( limitGroupStop ) )
limitCond = int ( stopLimit ) > 1
elif topLimit :
startLimit = 0
stopLimit = int ( topLimit . group ( 1 ) )
limitCond = int ( stopLimit ) > 1
2008-10-15 19:38:22 +04:00
2011-01-28 19:36:09 +03:00
elif Backend . getIdentifiedDbms ( ) == DBMS . ORACLE :
2011-01-20 02:06:15 +03:00
limitCond = False
else :
limitCond = True
# I assume that only queries NOT containing a "LIMIT #, 1"
# (or similar depending on the back-end DBMS) can return
# multiple entries
if limitCond :
if limitRegExp :
stopLimit = int ( stopLimit )
# From now on we need only the expression until the " LIMIT "
# (or similar, depending on the back-end DBMS) word
2011-01-28 19:36:09 +03:00
if Backend . getIdentifiedDbms ( ) in ( DBMS . MYSQL , DBMS . PGSQL ) :
2011-01-20 02:06:15 +03:00
stopLimit + = startLimit
2011-01-28 19:36:09 +03:00
untilLimitChar = expression . index ( queries [ Backend . getIdentifiedDbms ( ) ] . limitstring . query )
2011-01-20 02:06:15 +03:00
expression = expression [ : untilLimitChar ]
2011-01-28 19:36:09 +03:00
elif Backend . getIdentifiedDbms ( ) in ( DBMS . MSSQL , DBMS . SYBASE ) :
2011-01-20 02:06:15 +03:00
stopLimit + = startLimit
if not stopLimit or stopLimit < = 1 :
2011-01-28 19:36:09 +03:00
if Backend . getIdentifiedDbms ( ) in FROM_TABLE and expression . upper ( ) . endswith ( FROM_TABLE [ Backend . getIdentifiedDbms ( ) ] ) :
2011-01-20 02:06:15 +03:00
test = False
else :
test = True
if test :
# Count the number of SQL query entries output
2011-01-28 19:36:09 +03:00
countFirstField = queries [ Backend . getIdentifiedDbms ( ) ] . count . query % expressionFieldsList [ 0 ]
2011-01-20 02:06:15 +03:00
countedExpression = expression . replace ( expressionFields , countFirstField , 1 )
if re . search ( " ORDER BY " , expression , re . I ) :
untilOrderChar = countedExpression . index ( " ORDER BY " )
countedExpression = countedExpression [ : untilOrderChar ]
if resumeValue :
count = resume ( countedExpression , payload )
if not stopLimit :
if not count or not count . isdigit ( ) :
count = __goInference ( payload , countedExpression , 2 , firstChar , lastChar )
if isNumPosStrValue ( count ) :
count = int ( count )
if batch :
stopLimit = count
else :
message = " the SQL query provided can return "
message + = " %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 " )
if not test or test [ 0 ] in ( " a " , " A " ) :
2008-10-15 19:38:22 +04:00
stopLimit = count
2011-01-20 02:06:15 +03:00
elif test [ 0 ] in ( " q " , " Q " ) :
raise sqlmapUserQuitException
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
elif test . isdigit ( ) and int ( test ) > 0 and int ( test ) < = count :
stopLimit = int ( test )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
infoMsg = " sqlmap is now going to retrieve the "
infoMsg + = " first %d query output entries " % stopLimit
logger . info ( infoMsg )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
elif test [ 0 ] in ( " # " , " s " , " S " ) :
message = " how many? "
stopLimit = readInput ( message , default = " 10 " )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
if not stopLimit . isdigit ( ) :
2011-01-19 02:02:11 +03:00
errMsg = " invalid choice "
2009-04-22 15:48:07 +04:00
logger . error ( errMsg )
return None
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
else :
stopLimit = int ( stopLimit )
else :
errMsg = " invalid choice "
logger . error ( errMsg )
2008-12-17 23:11:18 +03:00
2011-01-20 02:06:15 +03:00
return None
2008-12-17 23:11:18 +03:00
2011-01-20 02:06:15 +03:00
elif count and not count . isdigit ( ) :
warnMsg = " it was not possible to count the number "
warnMsg + = " of entries for the SQL query provided. "
warnMsg + = " sqlmap will assume that it returns only "
warnMsg + = " one entry "
logger . warn ( warnMsg )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
stopLimit = 1
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
elif ( not count or int ( count ) == 0 ) :
2011-01-19 02:02:11 +03:00
warnMsg = " the SQL query provided does not "
2008-12-10 20:23:07 +03:00
warnMsg + = " return any output "
2008-10-15 19:38:22 +04:00
logger . warn ( warnMsg )
return None
2011-01-20 02:06:15 +03:00
elif ( not count or int ( count ) == 0 ) and ( not stopLimit or stopLimit == 0 ) :
warnMsg = " the SQL query provided does not "
warnMsg + = " return any output "
logger . warn ( warnMsg )
2011-01-19 02:02:11 +03:00
2011-01-20 02:06:15 +03:00
return None
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
try :
for num in xrange ( startLimit , stopLimit ) :
output = __goInferenceFields ( expression , expressionFields , expressionFieldsList , payload , expected , num , resumeValue = resumeValue , charsetType = charsetType , firstChar = firstChar , lastChar = lastChar )
outputs . append ( output )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
except KeyboardInterrupt :
print
warnMsg = " Ctrl+C detected in dumping phase "
logger . warn ( warnMsg )
2008-10-15 19:38:22 +04:00
2011-01-20 02:06:15 +03:00
return outputs
2011-01-28 19:36:09 +03:00
elif Backend . getIdentifiedDbms ( ) in FROM_TABLE and expression . upper ( ) . startswith ( " SELECT " ) and " FROM " not in expression . upper ( ) :
expression + = FROM_TABLE [ Backend . getIdentifiedDbms ( ) ]
2011-01-20 02:06:15 +03:00
outputs = __goInferenceFields ( expression , expressionFields , expressionFieldsList , payload , expected , resumeValue = resumeValue , charsetType = charsetType , firstChar = firstChar , lastChar = lastChar )
returnValue = " , " . join ( [ output for output in outputs ] )
2008-10-15 19:38:22 +04:00
return returnValue
2011-01-19 02:02:11 +03:00
def __goBooleanProxy ( expression , resumeValue = True ) :
"""
Retrieve the output of a boolean based SQL query
"""
initTechnique ( kb . technique )
vector = kb . injection . data [ kb . technique ] . vector
vector = vector . replace ( " [INFERENCE] " , expression )
vector = agent . cleanupPayload ( vector )
query = agent . prefixQuery ( vector )
query = agent . suffixQuery ( query )
payload = agent . payload ( newValue = query )
timeBasedCompare = kb . technique in ( PAYLOAD . TECHNIQUE . TIME , PAYLOAD . TECHNIQUE . STACKED )
if resumeValue :
output = resume ( expression , payload )
else :
output = None
if not output :
output = Request . queryPage ( payload , timeBasedCompare = timeBasedCompare , raise404 = False )
return output
def __goError ( expression , expected = None , resumeValue = True , dump = False ) :
2010-12-03 13:44:16 +03:00
"""
Retrieve the output of a SQL query taking advantage of an error - based
SQL injection vulnerability on the affected parameter .
"""
2011-02-01 00:22:39 +03:00
output = None
2010-12-03 13:44:16 +03:00
2010-12-15 15:43:56 +03:00
if resumeValue :
2011-02-01 00:22:39 +03:00
output = resume ( expression , None )
2010-12-03 13:44:16 +03:00
2011-02-01 00:22:39 +03:00
if output and expected == EXPECTED . INT and not output . isdigit ( ) :
output = None
2010-12-03 13:44:16 +03:00
2011-02-01 00:22:39 +03:00
if output is None :
output = errorUse ( expression , expected , resumeValue , dump )
return output
2010-12-03 13:44:16 +03:00
2010-04-30 19:48:40 +04:00
def __goInband ( expression , expected = None , sort = True , resumeValue = True , unpack = True , dump = False ) :
2008-10-15 19:38:22 +04:00
"""
Retrieve the output of a SQL query taking advantage of an inband SQL
injection vulnerability on the affected parameter .
"""
2011-01-19 02:02:11 +03:00
output = None
2008-10-15 19:38:22 +04:00
partial = False
2011-01-19 02:02:11 +03:00
data = [ ]
2008-10-15 19:38:22 +04:00
2010-12-15 15:43:56 +03:00
if resumeValue :
2008-10-15 19:38:22 +04:00
output = resume ( expression , None )
2011-02-01 00:22:39 +03:00
if not output or ( output and ( expected == EXPECTED . INT and not output . isdigit ( ) ) ) :
2008-10-15 19:38:22 +04:00
partial = True
2011-02-01 00:22:39 +03:00
if output is None :
2011-02-02 01:07:42 +03:00
output = unionUse ( expression , unpack = unpack , dump = dump )
2008-10-15 19:38:22 +04:00
if output :
2010-12-15 23:51:29 +03:00
data = parseUnionPage ( output , expression , partial , None , sort )
2008-10-15 19:38:22 +04:00
return data
2010-12-09 01:38:26 +03:00
def getValue ( expression , blind = True , inband = True , error = True , time = True , fromUser = False , expected = None , batch = False , unpack = True , sort = True , resumeValue = True , charsetType = None , firstChar = None , lastChar = None , dump = False , suppressOutput = False , expectingNone = False ) :
2008-10-15 19:38:22 +04:00
"""
Called each time sqlmap inject a SQL query on the SQL injection
affected parameter . It can call a function to retrieve the output
through inband SQL injection ( if selected ) and / or blind SQL injection
( if selected ) .
"""
2011-01-07 19:39:47 +03:00
getCurrentThreadData ( ) . disableStdOut = suppressOutput
2010-10-19 16:02:04 +04:00
2010-12-09 01:38:26 +03:00
try :
if conf . direct :
value = direct ( expression )
2010-12-15 15:15:43 +03:00
2011-01-12 01:18:47 +03:00
elif any ( map ( isTechniqueAvailable , getPublicTypeMembers ( PAYLOAD . TECHNIQUE , onlyValues = True ) ) ) :
2010-12-10 18:06:53 +03:00
query = cleanQuery ( expression )
query = expandAsteriskForColumns ( query )
2010-12-10 18:24:25 +03:00
value = None
found = False
2011-01-19 02:02:11 +03:00
2010-12-27 17:17:20 +03:00
if query and not ' COUNT(*) ' in query :
query = query . replace ( " DISTINCT " , " " )
2011-01-19 02:02:11 +03:00
2010-12-21 18:24:14 +03:00
count = 0
2010-12-10 18:06:53 +03:00
2010-12-10 19:03:32 +03:00
if expected == EXPECTED . BOOL :
2010-12-11 20:32:15 +03:00
forgeCaseExpression = booleanExpression = expression
2010-12-14 00:33:42 +03:00
2010-12-11 20:32:15 +03:00
if expression . upper ( ) . startswith ( " SELECT " ) :
booleanExpression = expression [ len ( " SELECT " ) : ]
else :
forgeCaseExpression = agent . forgeCaseStatement ( expression )
2008-10-15 19:38:22 +04:00
2011-01-12 01:18:47 +03:00
if inband and isTechniqueAvailable ( PAYLOAD . TECHNIQUE . UNION ) :
2010-12-09 01:38:26 +03:00
kb . technique = PAYLOAD . TECHNIQUE . UNION
2010-12-14 00:33:42 +03:00
2010-12-11 20:32:15 +03:00
if expected == EXPECTED . BOOL :
value = __goInband ( forgeCaseExpression , expected , sort , resumeValue , unpack , dump )
else :
value = __goInband ( query , expected , sort , resumeValue , unpack , dump )
2008-12-10 20:23:07 +03:00
2010-12-21 18:24:14 +03:00
count + = 1
2010-12-31 15:04:39 +03:00
found = ( value is not None ) or ( value is None and expectingNone ) or count > = MAX_TECHNIQUES_PER_VALUE
2010-12-01 13:57:17 +03:00
2010-12-15 15:10:33 +03:00
if error and isTechniqueAvailable ( PAYLOAD . TECHNIQUE . ERROR ) and not found :
2010-12-09 01:38:26 +03:00
kb . technique = PAYLOAD . TECHNIQUE . ERROR
2010-12-14 00:33:42 +03:00
2010-12-10 19:03:32 +03:00
if expected == EXPECTED . BOOL :
2011-01-19 02:02:11 +03:00
value = __goError ( forgeCaseExpression , expected , resumeValue , dump )
2010-12-10 19:03:32 +03:00
else :
2011-01-19 02:02:11 +03:00
value = __goError ( query , expected , resumeValue , dump )
2010-12-14 00:33:42 +03:00
2010-12-21 18:24:14 +03:00
count + = 1
2010-12-31 15:04:39 +03:00
found = ( value is not None ) or ( value is None and expectingNone ) or count > = MAX_TECHNIQUES_PER_VALUE
2010-12-08 15:49:26 +03:00
2010-12-15 15:10:33 +03:00
if blind and isTechniqueAvailable ( PAYLOAD . TECHNIQUE . BOOLEAN ) and not found :
2010-12-09 01:38:26 +03:00
kb . technique = PAYLOAD . TECHNIQUE . BOOLEAN
2010-12-14 00:33:42 +03:00
2010-12-10 15:30:36 +03:00
if expected == EXPECTED . BOOL :
2010-12-10 18:18:15 +03:00
value = __goBooleanProxy ( booleanExpression , resumeValue )
2010-12-10 00:15:18 +03:00
else :
2010-12-10 18:06:53 +03:00
value = __goInferenceProxy ( query , fromUser , expected , batch , resumeValue , unpack , charsetType , firstChar , lastChar )
2010-12-14 00:33:42 +03:00
2010-12-21 18:24:14 +03:00
count + = 1
2010-12-31 15:04:39 +03:00
found = ( value is not None ) or ( value is None and expectingNone ) or count > = MAX_TECHNIQUES_PER_VALUE
2010-12-08 15:49:26 +03:00
2010-12-15 15:10:33 +03:00
if time and ( isTechniqueAvailable ( PAYLOAD . TECHNIQUE . TIME ) or isTechniqueAvailable ( PAYLOAD . TECHNIQUE . STACKED ) ) and not found :
if isTechniqueAvailable ( PAYLOAD . TECHNIQUE . TIME ) :
2010-12-09 02:52:31 +03:00
kb . technique = PAYLOAD . TECHNIQUE . TIME
2010-12-15 15:10:33 +03:00
else :
2010-12-09 02:52:31 +03:00
kb . technique = PAYLOAD . TECHNIQUE . STACKED
2010-12-08 15:28:54 +03:00
2010-12-10 19:03:32 +03:00
if expected == EXPECTED . BOOL :
value = __goBooleanProxy ( booleanExpression , resumeValue )
else :
value = __goInferenceProxy ( query , fromUser , expected , batch , resumeValue , unpack , charsetType , firstChar , lastChar )
2008-10-15 19:38:22 +04:00
2010-12-09 01:38:26 +03:00
if value and isinstance ( value , basestring ) :
value = value . strip ( )
else :
errMsg = " none of the injection types identified can be "
errMsg + = " leveraged to retrieve queries output "
raise sqlmapNotVulnerableException , errMsg
2010-12-15 15:34:14 +03:00
2010-12-09 01:38:26 +03:00
finally :
2011-01-07 19:39:47 +03:00
getCurrentThreadData ( ) . disableStdOut = False
2010-03-18 20:36:58 +03:00
2010-12-11 20:32:15 +03:00
if value and expected == EXPECTED . BOOL :
if isinstance ( value , basestring ) :
2010-12-15 15:34:14 +03:00
if value . lower ( ) in ( " true " , " false " ) :
2010-12-11 20:32:15 +03:00
value = bool ( value )
2010-12-18 00:01:14 +03:00
elif value . capitalize ( ) == " None " :
value = None
2010-12-11 20:32:15 +03:00
else :
value = value != " 0 "
elif isinstance ( value , int ) :
value = bool ( value )
2008-10-15 19:38:22 +04:00
return value
2008-11-12 03:36:50 +03:00
2009-04-22 15:48:07 +04:00
def goStacked ( expression , silent = False ) :
2010-12-08 16:04:48 +03:00
kb . technique = PAYLOAD . TECHNIQUE . STACKED
2008-12-19 23:09:46 +03:00
expression = cleanQuery ( expression )
2010-03-27 02:23:25 +03:00
if conf . direct :
2011-02-01 00:22:39 +03:00
return direct ( expression )
2010-03-27 02:23:25 +03:00
2011-01-28 19:36:09 +03:00
comment = queries [ Backend . getIdentifiedDbms ( ) ] . comment . query
2010-12-01 20:09:52 +03:00
query = agent . prefixQuery ( " ; %s " % expression )
query = agent . suffixQuery ( " %s ; %s " % ( query , comment ) )
2008-12-17 00:30:24 +03:00
payload = agent . payload ( newValue = query )
2010-12-08 17:33:10 +03:00
page , _ = Request . queryPage ( payload , content = True , silent = silent , noteResponseTime = False )
2008-11-12 03:36:50 +03:00
2008-12-17 00:30:24 +03:00
return payload , page
2010-12-06 21:20:57 +03:00
2010-12-14 12:05:00 +03:00
def checkBooleanExpression ( expression , expectingNone = True ) :
return getValue ( unescaper . unescape ( expression ) , expected = EXPECTED . BOOL , suppressOutput = True , expectingNone = expectingNone )