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
2012-01-11 18:59:46 +04:00
Copyright ( c ) 2006 - 2012 sqlmap developers ( http : / / www . sqlmap . org / )
2010-10-15 03:18:29 +04:00
See the file ' doc/COPYING ' for copying permission
2008-10-15 19:38:22 +04:00
"""
2011-05-16 02:21:38 +04:00
import os
2010-10-15 04:34:16 +04:00
import re
2008-10-15 19:38:22 +04:00
from lib . controller . action import action
from lib . controller . checks import checkSqlInjection
from lib . controller . checks import checkDynParam
from lib . controller . checks import checkStability
from lib . controller . checks import checkString
2008-12-12 22:06:31 +03:00
from lib . controller . checks import checkRegexp
2008-10-15 19:38:22 +04:00
from lib . controller . checks import checkConnection
2010-09-16 12:43:10 +04:00
from lib . controller . checks import checkNullConnection
2011-07-06 09:44:47 +04:00
from lib . controller . checks import checkWaf
2011-01-03 11:32:06 +03:00
from lib . controller . checks import heuristicCheckSqlInjection
from lib . controller . checks import simpletonCheckSqlInjection
2010-11-28 21:10:54 +03:00
from lib . core . agent import agent
2011-03-29 02:48:00 +04:00
from lib . core . common import extractRegexResult
2011-01-14 19:12:44 +03:00
from lib . core . common import getFilteredPageContent
2011-05-16 02:21:38 +04:00
from lib . core . common import getPublicTypeMembers
2010-06-02 16:45:40 +04:00
from lib . core . common import getUnicode
2011-02-14 00:58:48 +03:00
from lib . core . common import intersect
2010-03-05 18:25:53 +03:00
from lib . core . common import parseTargetUrl
2011-03-29 02:48:00 +04:00
from lib . core . common import randomStr
2008-10-15 19:38:22 +04:00
from lib . core . common import readInput
2011-01-02 10:37:47 +03:00
from lib . core . common import showHttpErrorCodes
2011-03-03 13:39:04 +03:00
from lib . core . convert import urlencode
from lib . core . convert import urldecode
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
2011-12-28 17:50:03 +04:00
from lib . core . enums import HASHDB_KEYS
2011-11-29 23:17:07 +04:00
from lib . core . enums import HTTPHEADER
2010-11-08 12:44:32 +03:00
from lib . core . enums import HTTPMETHOD
2010-11-28 21:10:54 +03:00
from lib . core . enums import PAYLOAD
2010-11-08 12:44:32 +03:00
from lib . core . enums import PLACE
2010-03-16 15:14:02 +03:00
from lib . core . exception import exceptionsTuple
2011-05-24 21:15:25 +04:00
from lib . core . exception import sqlmapNoneDataException
2008-10-15 19:38:22 +04:00
from lib . core . exception import sqlmapNotVulnerableException
2010-10-12 19:49:04 +04:00
from lib . core . exception import sqlmapSilentQuitException
2010-11-28 21:10:54 +03:00
from lib . core . exception import sqlmapValueException
2010-09-30 23:45:23 +04:00
from lib . core . exception import sqlmapUserQuitException
2008-10-15 19:38:22 +04:00
from lib . core . session import setInjection
2012-01-11 18:28:08 +04:00
from lib . core . settings import DEFAULT_COOKIE_DELIMITER
2011-11-22 01:31:08 +04:00
from lib . core . settings import DEFAULT_GET_POST_DELIMITER
2011-03-29 02:48:00 +04:00
from lib . core . settings import EMPTY_FORM_FIELDS_REGEX
2011-04-13 23:01:02 +04:00
from lib . core . settings import IGNORE_PARAMETERS
2011-05-27 00:48:18 +04:00
from lib . core . settings import LOW_TEXT_PERCENT
2011-12-20 16:52:41 +04:00
from lib . core . settings import HOST_ALIASES
2011-02-14 00:58:48 +03:00
from lib . core . settings import REFERER_ALIASES
from lib . core . settings import USER_AGENT_ALIASES
2010-03-15 14:55:13 +03:00
from lib . core . target import initTargetEnv
from lib . core . target import setupTargetEnv
2011-01-02 11:43:38 +03:00
from extra . pagerank . pagerank import get_pagerank
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
def __selectInjection ( ) :
2008-10-15 19:38:22 +04:00
"""
Selection function for injection place , parameters and type .
"""
2011-07-04 23:58:41 +04:00
points = { }
2008-10-15 19:38:22 +04:00
2011-07-04 23:58:41 +04:00
for injection in kb . injections :
place = injection . place
parameter = injection . parameter
ptype = injection . ptype
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
point = ( place , parameter , ptype )
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
if point not in points :
2011-07-04 23:58:41 +04:00
points [ point ] = injection
else :
for key in points [ point ] . keys ( ) :
if key != ' data ' :
points [ point ] [ key ] = points [ point ] [ key ] or injection [ key ]
points [ point ] [ ' data ' ] . update ( injection [ ' data ' ] )
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
if len ( points ) == 1 :
kb . injection = kb . injections [ 0 ]
2010-11-30 17:48:13 +03:00
2010-11-28 21:10:54 +03:00
elif len ( points ) > 1 :
message = " there were multiple injection points, please select "
message + = " the one to use for following injections: \n "
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
points = [ ]
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
for i in xrange ( 0 , len ( kb . injections ) ) :
place = kb . injections [ i ] . place
parameter = kb . injections [ i ] . parameter
ptype = kb . injections [ i ] . ptype
point = ( place , parameter , ptype )
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
if point not in points :
points . append ( point )
2010-11-29 04:04:42 +03:00
ptype = PAYLOAD . PARAMETER [ ptype ] if isinstance ( ptype , int ) else ptype
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
message + = " [ %d ] place: %s , parameter: " % ( i , place )
2010-11-29 04:04:42 +03:00
message + = " %s , type: %s " % ( parameter , ptype )
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
if i == 0 :
message + = " (default) "
2008-10-15 19:38:22 +04:00
2010-11-28 21:10:54 +03:00
message + = " \n "
message + = " [q] Quit "
select = readInput ( message , default = " 0 " )
if select . isdigit ( ) and int ( select ) < len ( kb . injections ) and int ( select ) > = 0 :
index = int ( select )
elif select [ 0 ] in ( " Q " , " q " ) :
raise sqlmapUserQuitException
else :
errMsg = " invalid choice "
2010-11-29 02:33:51 +03:00
raise sqlmapValueException , errMsg
2010-11-28 21:10:54 +03:00
kb . injection = kb . injections [ index ]
def __formatInjection ( inj ) :
2010-11-29 00:27:47 +03:00
data = " Place: %s \n " % inj . place
data + = " Parameter: %s \n " % inj . parameter
2010-11-28 21:10:54 +03:00
for stype , sdata in inj . data . items ( ) :
2011-08-03 14:34:50 +04:00
title = sdata . title
2012-02-10 19:34:04 +04:00
vector = sdata . vector
2011-08-03 14:34:50 +04:00
if stype == PAYLOAD . TECHNIQUE . UNION :
count = re . sub ( r " \ (.+ \ ) " , " " , sdata . payload ) . count ( " , " ) + 1
title = re . sub ( r " \ d+ to \ d+ " , str ( count ) , title )
2012-02-22 13:41:58 +04:00
vector = agent . forgeInbandQuery ( " [QUERY] " , vector [ 0 ] , vector [ 1 ] , vector [ 2 ] , None , None , vector [ 5 ] , vector [ 6 ] )
2011-08-03 14:34:50 +04:00
if count == 1 :
title = title . replace ( " columns " , " column " )
2010-12-03 19:11:35 +03:00
data + = " Type: %s \n " % PAYLOAD . SQLINJECTION [ stype ]
2011-08-03 14:34:50 +04:00
data + = " Title: %s \n " % title
2012-02-10 19:59:11 +04:00
data + = " Payload: %s \n " % ( sdata . payload if stype not in ( PAYLOAD . TECHNIQUE . TIME , PAYLOAD . TECHNIQUE . STACKED ) else sdata . payload . replace ( " [SLEEPTIME] " , str ( conf . timeSec ) ) )
2012-02-10 19:34:04 +04:00
data + = " Vector: %s \n \n " % vector if conf . verbose > 1 else " \n "
2010-11-28 21:10:54 +03:00
2010-11-29 00:27:47 +03:00
return data
2010-11-28 21:10:54 +03:00
def __showInjections ( ) :
2011-01-12 01:18:47 +03:00
header = " sqlmap identified the following injection points with "
header + = " a total of %d HTTP(s) requests " % kb . testQueryCount
2010-11-29 00:27:47 +03:00
2011-07-04 23:58:41 +04:00
data = " " . join ( set ( map ( lambda x : __formatInjection ( x ) , kb . injections ) ) ) . rstrip ( " \n " )
2010-11-30 17:48:13 +03:00
2011-01-01 15:23:02 +03:00
conf . dumper . technic ( header , data )
2008-10-15 19:38:22 +04:00
2011-06-09 13:58:42 +04:00
if conf . tamper :
infoMsg = " changes made by tampering scripts are not "
infoMsg + = " included in shown payload content(s) "
logger . info ( infoMsg )
2011-04-11 15:38:41 +04:00
def __randomFillBlankFields ( value ) :
retVal = value
if extractRegexResult ( EMPTY_FORM_FIELDS_REGEX , value ) :
message = " do you want to fill blank fields with random values? [Y/n] "
test = readInput ( message , default = " Y " )
if not test or test [ 0 ] in ( " y " , " Y " ) :
while extractRegexResult ( EMPTY_FORM_FIELDS_REGEX , retVal ) :
item = extractRegexResult ( EMPTY_FORM_FIELDS_REGEX , retVal )
2011-11-22 01:31:08 +04:00
if item [ - 1 ] == DEFAULT_GET_POST_DELIMITER :
retVal = retVal . replace ( item , " %s %s %s " % ( item [ : - 1 ] , randomStr ( ) , DEFAULT_GET_POST_DELIMITER ) )
2011-04-11 15:38:41 +04:00
else :
retVal = retVal . replace ( item , " %s %s " % ( item , randomStr ( ) ) )
return retVal
2010-11-29 20:18:38 +03:00
def __saveToSessionFile ( ) :
for inj in kb . injections :
2010-12-01 01:40:25 +03:00
if inj . place is None or inj . parameter is None :
continue
2010-11-29 20:18:38 +03:00
setInjection ( inj )
2011-12-22 16:20:21 +04:00
def __saveToHashDB ( ) :
2011-12-28 17:50:03 +04:00
_ = conf . hashDB . retrieve ( HASHDB_KEYS . KB_ABS_FILE_PATHS , True ) or set ( )
_ . update ( kb . absFilePaths )
conf . hashDB . write ( HASHDB_KEYS . KB_ABS_FILE_PATHS , _ , True )
if not conf . hashDB . retrieve ( HASHDB_KEYS . KB_CHARS ) :
conf . hashDB . write ( HASHDB_KEYS . KB_CHARS , kb . chars , True )
2011-12-22 16:20:21 +04:00
2011-05-16 02:21:38 +04:00
def __saveToResultsFile ( ) :
if not conf . resultsFP :
return
found = False
results = { }
2011-06-08 19:31:27 +04:00
techniques = dict ( map ( lambda x : ( x [ 1 ] , x [ 0 ] ) , getPublicTypeMembers ( PAYLOAD . TECHNIQUE ) ) )
2011-05-16 02:21:38 +04:00
for inj in kb . injections :
if inj . place is None or inj . parameter is None :
continue
key = ( inj . place , inj . parameter )
if key not in results :
results [ key ] = [ ]
results [ key ] . extend ( inj . data . keys ( ) )
for key , value in results . items ( ) :
place , parameter = key
line = " %s , %s , %s , %s %s " % ( conf . url , place , parameter , " " . join ( map ( lambda x : techniques [ x ] [ 0 ] . upper ( ) , sorted ( value ) ) ) , os . linesep )
conf . resultsFP . writelines ( line )
if not results :
line = " %s ,,, %s " % ( conf . url , os . linesep )
conf . resultsFP . writelines ( line )
2011-06-08 18:15:34 +04:00
2008-10-15 19:38:22 +04:00
def start ( ) :
"""
This function calls a function that performs checks on both URL
stability and all GET , POST , Cookie and User - Agent parameters to
check if they are dynamic and SQL injection affected
"""
2010-03-16 15:14:02 +03:00
if not conf . start :
2010-09-26 18:56:55 +04:00
return False
2010-03-16 15:14:02 +03:00
2010-03-27 02:23:25 +03:00
if conf . direct :
initTargetEnv ( )
setupTargetEnv ( )
action ( )
2010-09-26 18:56:55 +04:00
return True
2010-03-27 02:23:25 +03:00
2011-06-24 09:40:03 +04:00
if conf . url and not any ( [ conf . forms , conf . crawlDepth ] ) :
2010-11-15 14:34:57 +03:00
kb . targetUrls . add ( ( conf . url , conf . method , conf . data , conf . cookie ) )
2008-10-15 19:38:22 +04:00
if conf . configFile and not kb . targetUrls :
2011-04-30 17:20:05 +04:00
errMsg = " you did not edit the configuration file properly, set "
2008-11-20 20:56:09 +03:00
errMsg + = " the target url, list of targets or google dork "
2008-10-15 19:38:22 +04:00
logger . error ( errMsg )
2010-09-26 18:56:55 +04:00
return False
2008-10-15 19:38:22 +04:00
2008-11-28 01:33:33 +03:00
if kb . targetUrls and len ( kb . targetUrls ) > 1 :
infoMsg = " sqlmap got a total of %d targets " % len ( kb . targetUrls )
logger . info ( infoMsg )
2011-04-30 17:20:05 +04:00
hostCount = 0
cookieStr = " "
2008-10-15 19:38:22 +04:00
2008-11-28 01:33:33 +03:00
for targetUrl , targetMethod , targetData , targetCookie in kb . targetUrls :
2010-03-16 15:14:02 +03:00
try :
2011-04-30 17:20:05 +04:00
conf . url = targetUrl
2010-03-16 15:14:02 +03:00
conf . method = targetMethod
2011-04-30 17:20:05 +04:00
conf . data = targetData
2010-03-16 15:14:02 +03:00
conf . cookie = targetCookie
2010-10-15 13:54:29 +04:00
2010-10-15 04:34:16 +04:00
initTargetEnv ( )
parseTargetUrl ( )
2010-10-15 13:54:29 +04:00
2010-10-15 04:34:16 +04:00
testSqlInj = False
2011-04-22 01:15:23 +04:00
2011-09-20 17:08:35 +04:00
if PLACE . GET in conf . parameters and not any ( [ conf . data , conf . testParameter ] ) :
2011-10-07 02:29:49 +04:00
for parameter in re . findall ( r " ([^=]+)=([^ %s ]+ %s ?| \ Z) " % ( conf . pDel or " ; " , conf . pDel or " ; " ) , conf . parameters [ PLACE . GET ] ) :
2011-04-11 15:38:41 +04:00
paramKey = ( conf . hostname , conf . path , PLACE . GET , parameter [ 0 ] )
2011-04-22 01:15:23 +04:00
2010-10-15 04:34:16 +04:00
if paramKey not in kb . testedParams :
testSqlInj = True
break
2010-10-15 13:54:29 +04:00
else :
paramKey = ( conf . hostname , conf . path , None , None )
if paramKey not in kb . testedParams :
testSqlInj = True
2010-12-23 14:28:13 +03:00
testSqlInj & = ( conf . hostname , conf . path , None , None ) not in kb . testedParams
2011-01-07 18:41:09 +03:00
2010-10-15 04:34:16 +04:00
if not testSqlInj :
infoMsg = " skipping ' %s ' " % targetUrl
logger . info ( infoMsg )
continue
2010-03-16 15:14:02 +03:00
if conf . multipleTargets :
hostCount + = 1
2011-04-22 01:15:23 +04:00
2010-11-15 14:50:33 +03:00
if conf . forms :
2010-11-29 15:46:18 +03:00
message = " [# %d ] form: \n %s %s " % ( hostCount , conf . method or HTTPMETHOD . GET , targetUrl )
2010-11-15 14:50:33 +03:00
else :
2011-03-23 14:57:57 +03:00
message = " url %d : \n %s %s %s " % ( hostCount , conf . method or HTTPMETHOD . GET , targetUrl , " (PageRank: %s ) " % get_pagerank ( targetUrl ) if conf . googleDork and conf . pageRank else " " )
2008-11-28 01:33:33 +03:00
2010-03-16 15:14:02 +03:00
if conf . cookie :
message + = " \n Cookie: %s " % conf . cookie
2008-11-28 01:33:33 +03:00
2010-03-16 15:14:02 +03:00
if conf . data :
2011-03-03 13:39:04 +03:00
message + = " \n POST data: %s " % urlencode ( conf . data ) if conf . data else " "
2010-11-15 14:34:57 +03:00
if conf . forms :
if conf . method == HTTPMETHOD . GET and targetUrl . find ( " ? " ) == - 1 :
continue
message + = " \n do you want to test this form? [Y/n/q] "
test = readInput ( message , default = " Y " )
if not test or test [ 0 ] in ( " y " , " Y " ) :
if conf . method == HTTPMETHOD . POST :
2011-04-02 02:19:42 +04:00
message = " Edit POST data [default: %s ] %s : " % ( urlencode ( conf . data ) if conf . data else " None " , " (Warning: blank fields detected) " if conf . data and extractRegexResult ( EMPTY_FORM_FIELDS_REGEX , conf . data ) else " " )
2011-03-29 02:48:00 +04:00
conf . data = readInput ( message , default = conf . data )
2011-04-11 15:38:41 +04:00
conf . data = __randomFillBlankFields ( conf . data )
2011-11-22 01:31:08 +04:00
conf . data = urldecode ( conf . data ) if conf . data and urlencode ( DEFAULT_GET_POST_DELIMITER , None ) not in conf . data else conf . data
2010-11-15 14:34:57 +03:00
elif conf . method == HTTPMETHOD . GET :
2011-04-11 15:38:41 +04:00
if targetUrl . find ( " ? " ) > - 1 :
firstPart = targetUrl [ : targetUrl . find ( " ? " ) ]
secondPart = targetUrl [ targetUrl . find ( " ? " ) + 1 : ]
2010-11-15 14:34:57 +03:00
message = " Edit GET data [default: %s ]: " % secondPart
test = readInput ( message , default = secondPart )
2011-04-11 15:38:41 +04:00
test = __randomFillBlankFields ( test )
2010-11-15 14:34:57 +03:00
conf . url = " %s ? %s " % ( firstPart , test )
2011-04-11 15:38:41 +04:00
parseTargetUrl ( )
2010-11-15 14:34:57 +03:00
elif test [ 0 ] in ( " n " , " N " ) :
continue
elif test [ 0 ] in ( " q " , " Q " ) :
break
2008-10-15 19:38:22 +04:00
2010-12-23 17:06:22 +03:00
elif conf . realTest :
2010-12-20 13:48:53 +03:00
logger . info ( message )
else :
2010-11-15 14:34:57 +03:00
message + = " \n do you want to test this url? [Y/n/q] "
test = readInput ( message , default = " Y " )
2008-11-28 01:33:33 +03:00
2010-11-15 14:34:57 +03:00
if not test or test [ 0 ] in ( " y " , " Y " ) :
pass
elif test [ 0 ] in ( " n " , " N " ) :
continue
elif test [ 0 ] in ( " q " , " Q " ) :
break
2008-10-15 19:38:22 +04:00
2011-04-30 19:29:59 +04:00
infoMsg = " testing url %s " % targetUrl
logger . info ( infoMsg )
2010-03-16 18:21:42 +03:00
2010-03-16 15:14:02 +03:00
setupTargetEnv ( )
2010-12-03 16:19:34 +03:00
if not checkConnection ( suppressOutput = conf . forms ) or not checkString ( ) or not checkRegexp ( ) :
2008-10-15 19:38:22 +04:00
continue
2011-07-06 09:44:47 +04:00
if conf . checkWaf :
checkWaf ( )
2010-10-17 01:52:16 +04:00
if conf . nullConnection :
2010-09-16 14:01:33 +04:00
checkNullConnection ( )
2010-09-16 12:43:10 +04:00
2011-05-11 01:33:06 +04:00
if ( len ( kb . injections ) == 0 or ( len ( kb . injections ) == 1 and kb . injections [ 0 ] . place is None ) ) \
and ( kb . injection . place is None or kb . injection . parameter is None ) :
2011-05-05 20:38:46 +04:00
2011-10-22 02:21:41 +04:00
if not conf . string and not conf . regexp and PAYLOAD . TECHNIQUE . BOOLEAN in conf . tech :
2010-03-16 15:14:02 +03:00
# NOTE: this is not needed anymore, leaving only to display
# a warning message to the user in case the page is not stable
checkStability ( )
2009-04-22 15:48:07 +04:00
2010-11-08 02:37:15 +03:00
# Do a little prioritization reorder of a testable parameter list
parameters = conf . parameters . keys ( )
2010-11-08 15:36:48 +03:00
2011-03-28 20:14:08 +04:00
# Order of testing list (last to first)
2011-03-29 10:25:17 +04:00
orderList = ( PLACE . URI , PLACE . GET , PLACE . POST )
2011-03-28 20:14:08 +04:00
for place in orderList :
2010-11-08 02:37:15 +03:00
if place in parameters :
parameters . remove ( place )
parameters . insert ( 0 , place )
2010-12-01 01:40:25 +03:00
proceed = True
2010-11-08 02:37:15 +03:00
for place in parameters :
2011-02-14 00:08:42 +03:00
# Test User-Agent and Referer headers only if
# --level >= 3
2011-03-29 10:38:19 +04:00
skip = ( place == PLACE . UA and conf . level < 3 )
skip | = ( place == PLACE . REFERER and conf . level < 3 )
2011-12-20 16:52:41 +04:00
# Test Host header only if
# --level >= 5
skip | = ( place == PLACE . HOST and conf . level < 5 )
2011-02-14 00:08:42 +03:00
# Test Cookie header only if --level >= 2
2011-03-29 10:38:19 +04:00
skip | = ( place == PLACE . COOKIE and conf . level < 2 )
2010-11-29 19:33:20 +03:00
2011-08-29 17:47:32 +04:00
skip | = ( place == PLACE . UA and intersect ( USER_AGENT_ALIASES , conf . skip , True ) not in ( [ ] , None ) )
skip | = ( place == PLACE . REFERER and intersect ( REFERER_ALIASES , conf . skip , True ) not in ( [ ] , None ) )
2012-02-12 23:22:33 +04:00
skip | = ( place == PLACE . COOKIE and intersect ( PLACE . COOKIE , conf . skip , True ) not in ( [ ] , None ) )
2011-08-29 17:47:32 +04:00
skip & = not ( place == PLACE . UA and intersect ( USER_AGENT_ALIASES , conf . testParameter , True ) )
skip & = not ( place == PLACE . REFERER and intersect ( REFERER_ALIASES , conf . testParameter , True ) )
2011-12-20 16:52:41 +04:00
skip & = not ( place == PLACE . HOST and intersect ( HOST_ALIASES , conf . testParameter , True ) )
2011-02-14 00:58:48 +03:00
2011-03-29 10:38:19 +04:00
if skip :
2010-11-29 19:33:20 +03:00
continue
2010-03-16 15:14:02 +03:00
if not conf . paramDict . has_key ( place ) :
continue
2009-04-22 15:48:07 +04:00
2010-03-16 15:14:02 +03:00
paramDict = conf . paramDict [ place ]
2011-04-22 01:53:35 +04:00
2010-03-16 15:14:02 +03:00
for parameter , value in paramDict . items ( ) :
2010-12-31 18:00:19 +03:00
if not proceed :
break
2011-05-24 21:15:25 +04:00
kb . vainRun = False
testSqlInj = True
2011-06-08 19:31:27 +04:00
paramKey = ( conf . hostname , conf . path , place , parameter )
2011-05-24 21:15:25 +04:00
2010-07-30 00:01:04 +04:00
if paramKey in kb . testedParams :
testSqlInj = False
2010-10-15 04:34:16 +04:00
infoMsg = " skipping previously processed %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
2011-08-29 17:29:42 +04:00
elif parameter in conf . testParameter :
pass
2011-08-29 16:50:52 +04:00
elif parameter == conf . rParam :
testSqlInj = False
infoMsg = " skipping randomizing %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
2011-08-29 17:29:42 +04:00
elif parameter in conf . skip :
testSqlInj = False
infoMsg = " skipping %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
2011-06-16 18:11:30 +04:00
2011-08-02 21:35:43 +04:00
# Ignore session-like parameters for --level < 4
elif conf . level < 4 and parameter . upper ( ) in IGNORE_PARAMETERS :
2011-04-13 23:01:02 +04:00
testSqlInj = False
infoMsg = " ignoring %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
2011-06-16 18:11:30 +04:00
elif conf . realTest :
2010-03-16 15:14:02 +03:00
pass
2010-10-15 04:34:16 +04:00
2011-10-22 02:21:41 +04:00
elif PAYLOAD . TECHNIQUE . BOOLEAN in conf . tech :
if not checkDynParam ( place , parameter , value ) :
warnMsg = " %s parameter ' %s ' appears to be not dynamic " % ( place , parameter )
logger . warn ( warnMsg )
2010-10-15 04:34:16 +04:00
2011-10-22 02:21:41 +04:00
else :
infoMsg = " %s parameter ' %s ' is dynamic " % ( place , parameter )
logger . info ( infoMsg )
2008-10-15 19:38:22 +04:00
2010-07-30 00:01:04 +04:00
kb . testedParams . add ( paramKey )
2010-03-16 15:14:02 +03:00
if testSqlInj :
2011-01-15 16:15:10 +03:00
check = heuristicCheckSqlInjection ( place , parameter )
2011-04-22 01:53:35 +04:00
2011-07-10 19:16:58 +04:00
if not check :
if conf . smart or conf . realTest and not simpletonCheckSqlInjection ( place , parameter , value ) :
infoMsg = " skipping %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
continue
2010-10-15 04:34:16 +04:00
2011-04-30 19:29:59 +04:00
infoMsg = " testing sql injection on %s " % place
infoMsg + = " parameter ' %s ' " % parameter
logger . info ( infoMsg )
2010-10-15 04:34:16 +04:00
2010-11-28 21:10:54 +03:00
injection = checkSqlInjection ( place , parameter , value )
2010-12-22 02:55:55 +03:00
proceed = not kb . endDetection
2010-12-01 01:40:25 +03:00
if injection is not None and injection . place is not None :
2010-11-28 21:10:54 +03:00
kb . injections . append ( injection )
2010-12-01 01:40:25 +03:00
2010-12-22 16:15:44 +03:00
# In case when user wants to end detection phase (Ctrl+C)
if not proceed :
break
2010-12-01 01:40:25 +03:00
msg = " %s parameter ' %s ' " % ( injection . place , injection . parameter )
2012-02-13 15:18:47 +04:00
msg + = " is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
test = readInput ( msg , default = " N " )
2010-12-01 01:40:25 +03:00
2012-02-13 15:18:47 +04:00
if test [ 0 ] not in ( " y " , " Y " ) :
2010-12-01 01:40:25 +03:00
proceed = False
2010-12-23 14:28:13 +03:00
paramKey = ( conf . hostname , conf . path , None , None )
kb . testedParams . add ( paramKey )
2010-11-28 21:10:54 +03:00
else :
2011-01-12 01:18:47 +03:00
warnMsg = " %s parameter ' %s ' is not " % ( place , parameter )
2010-03-16 15:14:02 +03:00
warnMsg + = " injectable "
logger . warn ( warnMsg )
2008-11-22 04:57:22 +03:00
2010-12-01 01:40:25 +03:00
if len ( kb . injections ) == 0 or ( len ( kb . injections ) == 1 and kb . injections [ 0 ] . place is None ) :
2011-05-24 21:15:25 +04:00
if kb . vainRun and not conf . multipleTargets :
2011-11-15 15:17:39 +04:00
errMsg = " no parameter(s) found for testing in the provided data "
2011-05-24 21:15:25 +04:00
errMsg + = " (e.g. GET parameter ' id ' in ' www.site.com/index.php?id=1 ' ) "
raise sqlmapNoneDataException , errMsg
elif not conf . realTest :
2011-05-27 00:48:18 +04:00
errMsg = " all parameters appear to be not injectable. "
2011-04-06 18:41:44 +04:00
2011-04-22 02:04:20 +04:00
if conf . level < 5 or conf . risk < 3 :
errMsg + = " Try to increase --level/--risk values "
errMsg + = " to perform more tests. "
if isinstance ( conf . tech , list ) and len ( conf . tech ) < 5 :
2012-02-01 18:49:42 +04:00
errMsg + = " Rerun without providing the option ' --technique ' . "
2011-01-16 02:11:36 +03:00
2011-01-14 19:12:44 +03:00
if not conf . textOnly and kb . originalPage :
2011-01-16 21:11:35 +03:00
percent = ( 100.0 * len ( getFilteredPageContent ( kb . originalPage ) ) / len ( kb . originalPage ) )
2011-05-27 00:48:18 +04:00
if kb . dynamicParameters :
2011-06-15 21:37:28 +04:00
errMsg + = " You can give it a go with the --text-only "
errMsg + = " switch if the target page has a low percentage "
errMsg + = " of textual content (~ %.2f %% of " % percent
2011-05-27 00:48:18 +04:00
errMsg + = " page content is text). "
2011-05-27 12:21:02 +04:00
elif percent < LOW_TEXT_PERCENT and not kb . errorIsNone :
2011-05-27 01:08:46 +04:00
errMsg + = " Please retry with the --text-only switch "
2011-05-27 00:58:24 +04:00
errMsg + = " (along with --technique=BU) as this case "
errMsg + = " looks like a perfect candidate "
2011-05-27 00:48:18 +04:00
errMsg + = " (low textual content along with inability "
errMsg + = " of comparison engine to detect at least "
errMsg + = " one dynamic parameter). "
2011-04-22 01:31:16 +04:00
2011-06-15 21:37:28 +04:00
if kb . heuristicTest :
errMsg + = " As heuristic test turned out positive you are "
errMsg + = " strongly advised to continue on with the tests. "
errMsg + = " Please, consider usage of tampering scripts as "
errMsg + = " your target might filter the queries. "
2011-04-22 01:31:16 +04:00
if not conf . string and not conf . regexp :
2011-06-15 21:37:28 +04:00
errMsg + = " Also, you can try to rerun by providing "
errMsg + = " either a valid --string "
2011-05-11 01:33:06 +04:00
errMsg + = " or a valid --regexp, refer to the user ' s "
errMsg + = " manual for details "
2011-04-22 01:31:16 +04:00
elif conf . string :
2011-06-15 21:37:28 +04:00
errMsg + = " Also, you can try to rerun by providing a "
errMsg + = " valid --string as perhaps the string you "
errMsg + = " have choosen does not match "
errMsg + = " exclusively True responses "
2011-04-22 01:31:16 +04:00
elif conf . regexp :
2011-06-15 21:37:28 +04:00
errMsg + = " Also, you can try to rerun by providing a "
errMsg + = " valid --regexp as perhaps the regular "
errMsg + = " expression that you have choosen "
errMsg + = " does not match exclusively True responses "
2011-01-16 02:11:36 +03:00
2010-12-21 03:25:03 +03:00
raise sqlmapNotVulnerableException , errMsg
else :
errMsg = " it seems that all parameters are not injectable "
2011-01-14 19:12:44 +03:00
raise sqlmapNotVulnerableException , errMsg
2010-11-28 21:10:54 +03:00
else :
2011-01-12 01:18:47 +03:00
# Flush the flag
kb . testMode = False
2010-11-28 21:10:54 +03:00
__saveToSessionFile ( )
2011-05-16 02:21:38 +04:00
__saveToResultsFile ( )
2011-12-22 16:20:21 +04:00
__saveToHashDB ( )
2010-11-28 21:10:54 +03:00
__showInjections ( )
__selectInjection ( )
2008-10-15 19:38:22 +04:00
2010-12-01 20:09:52 +03:00
if kb . injection . place is not None and kb . injection . parameter is not None :
2011-01-02 00:11:29 +03:00
if kb . testQueryCount == 0 and conf . realTest :
condition = False
elif conf . multipleTargets :
2010-03-16 15:14:02 +03:00
message = " do you want to exploit this SQL injection? [Y/n] "
exploit = readInput ( message , default = " Y " )
2008-10-15 19:38:22 +04:00
2010-03-16 15:14:02 +03:00
condition = not exploit or exploit [ 0 ] in ( " y " , " Y " )
else :
condition = True
if condition :
action ( )
2010-11-05 18:59:25 +03:00
except KeyboardInterrupt :
2010-11-05 19:03:12 +03:00
if conf . multipleTargets :
2011-04-08 14:39:07 +04:00
warnMsg = " user aborted in multiple target mode "
2010-11-05 19:03:12 +03:00
logger . warn ( warnMsg )
2010-11-05 18:59:25 +03:00
2010-11-07 19:23:03 +03:00
message = " do you want to skip to the next target in list? [Y/n/q] "
2010-11-05 19:03:12 +03:00
test = readInput ( message , default = " Y " )
2010-11-05 18:59:25 +03:00
2010-11-05 19:03:12 +03:00
if not test or test [ 0 ] in ( " y " , " Y " ) :
pass
elif test [ 0 ] in ( " n " , " N " ) :
return False
elif test [ 0 ] in ( " q " , " Q " ) :
raise sqlmapUserQuitException
else :
raise
2010-11-05 18:59:25 +03:00
2010-09-30 23:45:23 +04:00
except sqlmapUserQuitException :
raise
2010-11-10 22:44:51 +03:00
except sqlmapSilentQuitException :
raise
2010-03-16 15:14:02 +03:00
except exceptionsTuple , e :
2010-06-02 16:45:40 +04:00
e = getUnicode ( e )
2008-10-15 19:38:22 +04:00
2010-03-16 15:14:02 +03:00
if conf . multipleTargets :
2010-11-15 15:19:22 +03:00
e + = " , skipping to the next %s " % ( " form " if conf . forms else " url " )
2010-03-16 15:14:02 +03:00
logger . error ( e )
else :
2010-09-27 17:41:18 +04:00
logger . critical ( e )
2010-09-26 18:56:55 +04:00
return False
2008-10-15 19:38:22 +04:00
2011-01-02 10:37:47 +03:00
finally :
showHttpErrorCodes ( )
2011-05-11 00:44:36 +04:00
if kb . dataOutputFlag and not conf . multipleTargets :
2008-10-15 19:38:22 +04:00
logger . info ( " Fetched data logged to text files under ' %s ' " % conf . outputPath )
2010-11-03 13:08:27 +03:00
2011-06-20 15:32:30 +04:00
if conf . multipleTargets and conf . resultsFilename :
2011-06-08 19:31:27 +04:00
infoMsg = " you can find results of scanning in multiple targets "
infoMsg + = " mode inside the CSV file ' %s ' " % conf . resultsFilename
2011-05-16 02:21:38 +04:00
logger . info ( infoMsg )
2010-09-26 18:56:55 +04:00
return True