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
2011-04-15 16:33:18 +04:00
Copyright ( c ) 2006 - 2011 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
"""
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-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
2008-10-15 19:38:22 +04:00
from lib . core . common import paramToDict
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
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
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-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 .
"""
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
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 :
points . append ( point )
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 ( ) :
2010-12-03 19:11:35 +03:00
data + = " Type: %s \n " % PAYLOAD . SQLINJECTION [ stype ]
2010-12-01 20:09:52 +03:00
data + = " Title: %s \n " % sdata . title
data + = " Payload: %s \n \n " % sdata . payload
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
data = " "
2010-11-28 21:10:54 +03:00
for inj in kb . injections :
2010-11-29 00:27:47 +03:00
data + = __formatInjection ( inj )
2010-11-30 17:48:13 +03:00
data = data . rstrip ( " \n " )
2011-01-01 15:23:02 +03:00
conf . dumper . technic ( header , data )
2008-10-15 19:38:22 +04:00
2011-05-27 12:16:14 +04:00
if inj . place in ( HTTPMETHOD . GET , HTTPMETHOD . POST ) :
2011-06-08 19:31:27 +04:00
infoMsg = " usage of injected %s payloads requires manual url-encoding " % inj . place
2011-05-27 12:16:14 +04:00
logger . info ( infoMsg )
2011-05-25 15:10:52 +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 )
if item [ - 1 ] == ' & ' :
retVal = retVal . replace ( item , " %s %s & " % ( item [ : - 1 ] , randomStr ( ) ) )
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-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
2010-11-15 14:34:57 +03:00
if conf . url and not conf . forms :
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 = " "
2010-03-27 02:23:25 +03:00
setCookieAsInjectable = True
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
2010-11-08 12:44:32 +03:00
if PLACE . GET in conf . parameters :
2011-04-11 15:38:41 +04:00
for parameter in re . findall ( r " ([^=]+)=([^&]+&?| \ Z) " , conf . parameters [ PLACE . GET ] ) :
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-03-29 02:48:00 +04:00
conf . data = urldecode ( 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
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
2010-09-26 18:02:13 +04:00
if not conf . dropSetCookie and conf . cj :
2010-03-16 15:14:02 +03:00
for _ , cookie in enumerate ( conf . cj ) :
2010-06-02 16:45:40 +04:00
cookie = getUnicode ( cookie )
2011-04-30 17:20:05 +04:00
index = cookie . index ( " for " )
2010-03-16 18:21:42 +03:00
2010-03-16 15:14:02 +03:00
cookieStr + = " %s ; " % cookie [ 8 : index ]
2008-10-15 19:38:22 +04:00
2010-03-16 15:14:02 +03:00
if cookieStr :
cookieStr = cookieStr [ : - 1 ]
2010-03-16 18:21:42 +03:00
2010-11-08 12:44:32 +03:00
if PLACE . COOKIE in conf . parameters :
2011-04-30 17:20:05 +04:00
message = " you provided an HTTP Cookie header value. "
2010-03-16 15:14:02 +03:00
message + = " The target url provided its own Cookie within "
message + = " the HTTP Set-Cookie header. Do you want to "
message + = " continue using the HTTP Cookie values that "
message + = " you provided? [Y/n] "
test = readInput ( message , default = " Y " )
2010-03-16 18:21:42 +03:00
2010-03-16 15:14:02 +03:00
if not test or test [ 0 ] in ( " y " , " Y " ) :
setCookieAsInjectable = False
2010-03-16 18:21:42 +03:00
2010-03-16 15:14:02 +03:00
if setCookieAsInjectable :
2010-11-08 16:26:45 +03:00
conf . httpHeaders . append ( ( " Cookie " , cookieStr ) )
2010-11-08 12:44:32 +03:00
conf . parameters [ PLACE . COOKIE ] = cookieStr
__paramDict = paramToDict ( PLACE . COOKIE , cookieStr )
2010-03-16 18:21:42 +03:00
2010-03-16 15:14:02 +03:00
if __paramDict :
2010-11-08 12:44:32 +03:00
conf . paramDict [ PLACE . COOKIE ] = __paramDict
2010-03-21 03:39:44 +03:00
# TODO: consider the following line in __setRequestParams()
2011-01-15 16:15:10 +03:00
# __testableParameters = True
2008-10-15 19:38:22 +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-02-03 18:55:19 +03:00
if not conf . string and not conf . regexp :
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-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-03-29 10:38:19 +04:00
skip & = not ( place == PLACE . UA and intersect ( USER_AGENT_ALIASES , conf . testParameter ) )
skip & = not ( place == PLACE . REFERER and intersect ( REFERER_ALIASES , conf . testParameter ) )
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-04-13 23:01:02 +04:00
elif parameter . upper ( ) in IGNORE_PARAMETERS :
testSqlInj = False
infoMsg = " ignoring %s parameter ' %s ' " % ( place , parameter )
logger . info ( infoMsg )
2010-03-16 15:14:02 +03:00
# Avoid dinamicity test if the user provided the
# parameter manually
2011-01-02 01:43:15 +03:00
elif parameter in conf . testParameter or conf . realTest :
2010-03-16 15:14:02 +03:00
pass
2010-10-15 04:34:16 +04:00
2010-03-16 15:14:02 +03:00
elif not checkDynParam ( place , parameter , value ) :
2011-05-31 02:47:17 +04:00
warnMsg = " %s parameter ' %s ' appears to be not dynamic " % ( place , parameter )
2010-03-16 15:14:02 +03:00
logger . warn ( warnMsg )
2010-10-15 04:34:16 +04:00
2010-03-16 15:14:02 +03:00
else :
2011-05-27 00:48:18 +04:00
kb . foundDynamicParameter = True
2011-04-30 19:29:59 +04:00
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
if not check and conf . realTest and \
not simpletonCheckSqlInjection ( place , parameter , value ) :
2010-12-20 13:13:14 +03:00
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 )
msg + = " is vulnerable. Do you want to keep testing the others? [y/N] "
test = readInput ( msg , default = " N " )
if test [ 0 ] in ( " n " , " N " ) :
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 :
errMsg = " no testable parameter(s) found in the provided data "
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 :
2011-04-06 18:41:44 +04:00
errMsg + = " Rerun without providing the --technique switch. "
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 ( )
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-05-16 02:21:38 +04:00
if conf . multipleTargets :
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