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
|
|
|
"""
|
|
|
|
|
2008-12-12 22:06:31 +03:00
|
|
|
import re
|
2010-05-21 17:36:49 +04:00
|
|
|
import socket
|
2008-10-15 19:38:22 +04:00
|
|
|
import time
|
|
|
|
|
|
|
|
from lib.core.agent import agent
|
2010-10-25 23:16:42 +04:00
|
|
|
from lib.core.common import beep
|
2010-12-06 18:50:19 +03:00
|
|
|
from lib.core.common import extractRegexResult
|
2010-12-29 22:39:32 +03:00
|
|
|
from lib.core.common import findDynamicContent
|
2011-01-03 11:32:06 +03:00
|
|
|
from lib.core.common import getComparePageRatio
|
2010-12-21 15:56:18 +03:00
|
|
|
from lib.core.common import getCompiledRegex
|
2011-01-02 19:51:21 +03:00
|
|
|
from lib.core.common import getErrorParsedDBMSes
|
|
|
|
from lib.core.common import getErrorParsedDBMSesFormatted
|
2010-12-24 13:55:41 +03:00
|
|
|
from lib.core.common import getInjectionTests
|
2010-06-02 16:45:40 +04:00
|
|
|
from lib.core.common import getUnicode
|
2010-12-04 18:47:02 +03:00
|
|
|
from lib.core.common import popValue
|
|
|
|
from lib.core.common import pushValue
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.common import randomInt
|
|
|
|
from lib.core.common import randomStr
|
2010-10-11 15:47:07 +04:00
|
|
|
from lib.core.common import readInput
|
2010-12-04 13:13:18 +03:00
|
|
|
from lib.core.common import removeDynamicContent
|
2010-10-12 19:49:04 +04:00
|
|
|
from lib.core.common import showStaticWords
|
2010-11-29 18:14:49 +03:00
|
|
|
from lib.core.common import trimAlphaNum
|
2010-11-16 13:42:42 +03:00
|
|
|
from lib.core.common import wasLastRequestDBMSError
|
2010-12-26 16:20:52 +03:00
|
|
|
from lib.core.common import wasLastRequestHTTPError
|
2010-09-13 17:31:01 +04:00
|
|
|
from lib.core.common import DynamicContentItem
|
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-10-07 02:29:52 +04:00
|
|
|
from lib.core.data import paths
|
2010-11-28 21:10:54 +03:00
|
|
|
from lib.core.datatype import advancedDict
|
|
|
|
from lib.core.datatype import injectionDict
|
2010-11-08 12:49:57 +03:00
|
|
|
from lib.core.enums import HTTPMETHOD
|
|
|
|
from lib.core.enums import NULLCONNECTION
|
2010-11-28 21:10:54 +03:00
|
|
|
from lib.core.enums import PAYLOAD
|
2010-12-01 20:09:52 +03:00
|
|
|
from lib.core.enums import PLACE
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.exception import sqlmapConnectionException
|
2010-11-07 03:12:00 +03:00
|
|
|
from lib.core.exception import sqlmapGenericException
|
2010-02-10 12:39:36 +03:00
|
|
|
from lib.core.exception import sqlmapNoneDataException
|
2010-10-11 15:47:07 +04:00
|
|
|
from lib.core.exception import sqlmapUserQuitException
|
2010-12-29 22:48:19 +03:00
|
|
|
from lib.core.session import setDynamicMarkings
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.core.session import setString
|
2008-12-12 22:06:31 +03:00
|
|
|
from lib.core.session import setRegexp
|
2011-01-03 14:06:49 +03:00
|
|
|
from lib.core.session import setTextOnly
|
2011-01-03 11:32:06 +03:00
|
|
|
from lib.core.settings import CONSTANT_RATIO
|
2010-12-29 22:01:29 +03:00
|
|
|
from lib.core.settings import UPPER_RATIO_BOUND
|
2010-12-09 19:49:02 +03:00
|
|
|
from lib.core.unescaper import unescaper
|
2008-10-15 19:38:22 +04:00
|
|
|
from lib.request.connect import Connect as Request
|
2010-12-07 17:35:31 +03:00
|
|
|
from lib.request.templates import getPageTemplate
|
2010-11-28 21:10:54 +03:00
|
|
|
|
|
|
|
def unescape(string, dbms):
|
2010-12-09 03:34:02 +03:00
|
|
|
if dbms in unescaper and "WAITFOR DELAY " not in string:
|
2010-12-01 01:40:25 +03:00
|
|
|
return unescaper[dbms](string)
|
|
|
|
else:
|
|
|
|
return string
|
|
|
|
|
|
|
|
def unescapeDbms(payload, injection, dbms):
|
|
|
|
# If this is a DBMS-specific test (dbms), sqlmap identified the
|
|
|
|
# DBMS during previous a test (injection.dbms) or the user
|
|
|
|
# provided a DBMS (conf.dbms), unescape the strings between single
|
|
|
|
# quotes in the payload
|
|
|
|
if injection.dbms is not None:
|
|
|
|
payload = unescape(payload, injection.dbms)
|
|
|
|
elif dbms is not None:
|
|
|
|
payload = unescape(payload, dbms)
|
|
|
|
elif conf.dbms is not None:
|
|
|
|
payload = unescape(payload, conf.dbms)
|
|
|
|
|
|
|
|
return payload
|
2010-11-28 21:10:54 +03:00
|
|
|
|
|
|
|
def checkSqlInjection(place, parameter, value):
|
|
|
|
# Store here the details about boundaries and payload used to
|
|
|
|
# successfully inject
|
|
|
|
injection = injectionDict()
|
|
|
|
|
2010-12-21 02:34:00 +03:00
|
|
|
# Set the flag for sql injection test mode
|
2010-12-07 16:34:06 +03:00
|
|
|
kb.testMode = True
|
2010-12-04 18:47:02 +03:00
|
|
|
|
2010-12-24 13:55:41 +03:00
|
|
|
for test in getInjectionTests():
|
2011-01-01 22:22:44 +03:00
|
|
|
try:
|
|
|
|
if kb.endDetection:
|
|
|
|
break
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
title = test.title
|
|
|
|
stype = test.stype
|
|
|
|
clause = test.clause
|
|
|
|
|
|
|
|
# Skip test if the user's wants to test only for a specific
|
|
|
|
# technique
|
|
|
|
if conf.technique and isinstance(conf.technique, int) and stype != conf.technique:
|
|
|
|
debugMsg = "skipping test '%s' because the user " % title
|
|
|
|
debugMsg += "specified to test only for "
|
|
|
|
debugMsg += "%s" % PAYLOAD.SQLINJECTION[conf.technique]
|
2010-11-29 17:48:07 +03:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
continue
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Skip test if the risk is higher than the provided (or default)
|
|
|
|
# value
|
|
|
|
# Parse test's <risk>
|
|
|
|
if test.risk > conf.risk:
|
|
|
|
debugMsg = "skipping test '%s' because the risk " % title
|
|
|
|
debugMsg += "is higher than the provided"
|
2010-11-29 17:48:07 +03:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
continue
|
2010-10-07 02:43:04 +04:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Skip test if the level is higher than the provided (or default)
|
|
|
|
# value
|
|
|
|
# Parse test's <level>
|
|
|
|
if test.level > conf.level:
|
|
|
|
debugMsg = "skipping test '%s' because the level " % title
|
|
|
|
debugMsg += "is higher than the provided"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
continue
|
2010-12-03 15:00:03 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Skip DBMS-specific test if it does not match either the
|
|
|
|
# previously identified or the user's provided DBMS
|
|
|
|
if "details" in test and "dbms" in test.details:
|
|
|
|
dbms = test.details.dbms
|
2010-11-29 15:13:42 +03:00
|
|
|
else:
|
2010-12-18 13:42:09 +03:00
|
|
|
dbms = None
|
|
|
|
|
|
|
|
if dbms is not None:
|
|
|
|
if injection.dbms is not None and injection.dbms != dbms:
|
|
|
|
debugMsg = "skipping test '%s' because " % title
|
|
|
|
debugMsg += "the back-end DBMS identified is "
|
|
|
|
debugMsg += "%s" % injection.dbms
|
|
|
|
logger.debug(debugMsg)
|
2010-11-29 15:13:42 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
continue
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if conf.dbms is not None and conf.dbms.lower() != dbms.lower():
|
|
|
|
debugMsg = "skipping test '%s' because " % title
|
|
|
|
debugMsg += "the provided DBMS is %s" % conf.dbms
|
|
|
|
logger.debug(debugMsg)
|
2010-12-01 01:40:25 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
continue
|
|
|
|
|
2011-01-02 19:51:21 +03:00
|
|
|
if getErrorParsedDBMSes() and dbms not in getErrorParsedDBMSes()\
|
2011-01-02 02:38:11 +03:00
|
|
|
and kb.skipTests is None:
|
2011-01-02 19:51:21 +03:00
|
|
|
message = "parsed error message(s) showed that the back-end DBMS could be '%s'." % getErrorParsedDBMSesFormatted()
|
2011-01-02 02:38:11 +03:00
|
|
|
message += " do you want to skip test payloads specific for other DBMSes? [Y/n]"
|
|
|
|
kb.skipTests = conf.realTest or readInput(message, default="Y") not in ("n", "N")
|
|
|
|
|
|
|
|
if kb.skipTests:
|
|
|
|
debugMsg = "skipping test '%s' because " % title
|
2011-01-02 10:09:04 +03:00
|
|
|
debugMsg += "the parsed error message(s) showed "
|
|
|
|
debugMsg += "that the back-end DBMS could be "
|
2011-01-02 19:51:21 +03:00
|
|
|
debugMsg += "%s" % getErrorParsedDBMSesFormatted()
|
2011-01-02 02:38:11 +03:00
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Skip test if it is the same SQL injection type already
|
|
|
|
# identified by another test
|
|
|
|
if injection.data and stype in injection.data:
|
|
|
|
debugMsg = "skipping test '%s' because " % title
|
|
|
|
debugMsg += "the payload for %s has " % PAYLOAD.SQLINJECTION[stype]
|
|
|
|
debugMsg += "already been identified"
|
|
|
|
logger.debug(debugMsg)
|
2010-11-28 21:10:54 +03:00
|
|
|
continue
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Skip test if it does not match the same SQL injection clause
|
|
|
|
# already identified by another test
|
2010-11-28 21:10:54 +03:00
|
|
|
clauseMatch = False
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
for clauseTest in clause:
|
|
|
|
if injection.clause is not None and clauseTest in injection.clause:
|
2010-11-28 21:10:54 +03:00
|
|
|
clauseMatch = True
|
|
|
|
break
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if clause != [ 0 ] and injection.clause and injection.clause != [ 0 ] and not clauseMatch:
|
|
|
|
debugMsg = "skipping test '%s' because the clauses " % title
|
|
|
|
debugMsg += "differs from the clause already identified"
|
|
|
|
logger.debug(debugMsg)
|
2010-11-28 21:10:54 +03:00
|
|
|
continue
|
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
infoMsg = "testing '%s'" % title
|
|
|
|
logger.info(infoMsg)
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Parse test's <request>
|
|
|
|
comment = agent.getComment(test.request)
|
|
|
|
fstPayload = agent.cleanupPayload(test.request.payload, value)
|
|
|
|
fstPayload = unescapeDbms(fstPayload, injection, dbms)
|
|
|
|
fstPayload = "%s%s" % (fstPayload, comment)
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if stype != 4 and clause != [2, 3] and clause != [ 3 ]:
|
|
|
|
space = " "
|
|
|
|
else:
|
|
|
|
space = ""
|
|
|
|
|
|
|
|
if conf.prefix is not None and conf.suffix is not None:
|
|
|
|
# Create a custom boundary object for user's supplied prefix
|
|
|
|
# and suffix
|
|
|
|
boundary = advancedDict()
|
|
|
|
|
|
|
|
boundary.level = 1
|
|
|
|
boundary.clause = [ 0 ]
|
|
|
|
boundary.where = [ 1, 2, 3 ]
|
|
|
|
boundary.prefix = conf.prefix
|
|
|
|
boundary.suffix = conf.suffix
|
|
|
|
|
|
|
|
if " like" in boundary.suffix.lower():
|
|
|
|
if "'" in boundary.suffix.lower():
|
|
|
|
boundary.ptype = 3
|
|
|
|
elif '"' in boundary.suffix.lower():
|
|
|
|
boundary.ptype = 5
|
|
|
|
elif "'" in boundary.suffix:
|
|
|
|
boundary.ptype = 2
|
|
|
|
elif '"' in boundary.suffix:
|
|
|
|
boundary.ptype = 4
|
|
|
|
else:
|
|
|
|
boundary.ptype = 1
|
|
|
|
|
|
|
|
# Prepend user's provided boundaries to all others boundaries
|
|
|
|
conf.boundaries.insert(0, boundary)
|
|
|
|
|
|
|
|
for boundary in conf.boundaries:
|
|
|
|
injectable = False
|
|
|
|
|
|
|
|
# Skip boundary if the level is higher than the provided (or
|
|
|
|
# default) value
|
|
|
|
# Parse boundary's <level>
|
|
|
|
if boundary.level > conf.level:
|
|
|
|
# NOTE: shall we report every single skipped boundary too?
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Skip boundary if it does not match against test's <clause>
|
|
|
|
# Parse test's <clause> and boundary's <clause>
|
|
|
|
clauseMatch = False
|
|
|
|
|
|
|
|
for clauseTest in test.clause:
|
|
|
|
if clauseTest in boundary.clause:
|
|
|
|
clauseMatch = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if test.clause != [ 0 ] and boundary.clause != [ 0 ] and not clauseMatch:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Skip boundary if it does not match against test's <where>
|
|
|
|
# Parse test's <where> and boundary's <where>
|
|
|
|
whereMatch = False
|
|
|
|
|
|
|
|
for where in test.where:
|
|
|
|
if where in boundary.where:
|
|
|
|
whereMatch = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if not whereMatch:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Parse boundary's <prefix>, <suffix> and <ptype>
|
|
|
|
prefix = boundary.prefix if boundary.prefix else ""
|
|
|
|
suffix = boundary.suffix if boundary.suffix else ""
|
|
|
|
ptype = boundary.ptype
|
|
|
|
|
|
|
|
# If the previous injections succeeded, we know which prefix,
|
|
|
|
# suffix and parameter type to use for further tests, no
|
|
|
|
# need to cycle through the boundaries for the following tests
|
|
|
|
condBound = (injection.prefix is not None and injection.suffix is not None)
|
|
|
|
condBound &= (injection.prefix != prefix or injection.suffix != suffix)
|
|
|
|
condType = injection.ptype is not None and injection.ptype != ptype
|
|
|
|
|
|
|
|
if condBound or condType:
|
|
|
|
continue
|
|
|
|
|
|
|
|
# For each test's <where>
|
|
|
|
for where in test.where:
|
|
|
|
templatePayload = None
|
|
|
|
|
|
|
|
# Threat the parameter original value according to the
|
|
|
|
# test's <where> tag
|
|
|
|
if where == 1:
|
|
|
|
origValue = value
|
|
|
|
elif where == 2:
|
|
|
|
origValue = "-%s" % randomInt()
|
|
|
|
# Use different page template than the original one
|
|
|
|
# as we are changing parameters value, which will result
|
|
|
|
# most definitely with a different content
|
|
|
|
templatePayload = agent.payload(place, parameter, value, origValue)
|
|
|
|
elif where == 3:
|
|
|
|
origValue = ""
|
|
|
|
|
2010-12-24 15:13:48 +03:00
|
|
|
kb.pageTemplate, kb.errorIsNone = getPageTemplate(templatePayload, place)
|
2010-12-18 13:42:09 +03:00
|
|
|
|
|
|
|
# Forge request payload by prepending with boundary's
|
|
|
|
# prefix and appending the boundary's suffix to the
|
|
|
|
# test's ' <payload><comment> ' string
|
|
|
|
boundPayload = "%s%s%s%s %s" % (origValue, prefix, space, fstPayload, suffix)
|
|
|
|
boundPayload = boundPayload.strip()
|
|
|
|
boundPayload = agent.cleanupPayload(boundPayload, value)
|
|
|
|
reqPayload = agent.payload(place, parameter, value, boundPayload)
|
|
|
|
|
|
|
|
# Perform the test's request and check whether or not the
|
|
|
|
# payload was successful
|
|
|
|
# Parse test's <response>
|
|
|
|
for method, check in test.response.items():
|
|
|
|
check = agent.cleanupPayload(check, value)
|
|
|
|
|
|
|
|
# In case of boolean-based blind SQL injection
|
|
|
|
if method == PAYLOAD.METHOD.COMPARISON:
|
|
|
|
sndPayload = agent.cleanupPayload(test.response.comparison, value)
|
|
|
|
sndPayload = unescapeDbms(sndPayload, injection, dbms)
|
|
|
|
sndPayload = "%s%s" % (sndPayload, comment)
|
|
|
|
|
|
|
|
# Forge response payload by prepending with
|
|
|
|
# boundary's prefix and appending the boundary's
|
|
|
|
# suffix to the test's ' <payload><comment> '
|
|
|
|
# string
|
|
|
|
boundPayload = "%s%s%s%s %s" % (origValue, prefix, space, sndPayload, suffix)
|
|
|
|
boundPayload = boundPayload.strip()
|
|
|
|
boundPayload = agent.cleanupPayload(boundPayload, value)
|
|
|
|
cmpPayload = agent.payload(place, parameter, value, boundPayload)
|
|
|
|
|
|
|
|
# Useful to set kb.matchRatio at first based on
|
|
|
|
# the False response content
|
|
|
|
kb.matchRatio = None
|
2010-12-24 15:36:00 +03:00
|
|
|
_ = Request.queryPage(cmpPayload, place, raise404=False)
|
2010-12-18 13:42:09 +03:00
|
|
|
|
|
|
|
# Perform the test's True request
|
2010-12-24 15:36:00 +03:00
|
|
|
trueResult = Request.queryPage(reqPayload, place, raise404=False)
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if trueResult:
|
2010-12-24 15:36:00 +03:00
|
|
|
falseResult = Request.queryPage(cmpPayload, place, raise404=False)
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# Perform the test's False request
|
|
|
|
if not falseResult:
|
|
|
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
|
|
|
logger.info(infoMsg)
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
injectable = True
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# In case of error-based or UNION query SQL injections
|
|
|
|
elif method == PAYLOAD.METHOD.GREP:
|
|
|
|
# Perform the test's request and grep the response
|
|
|
|
# body for the test's <grep> regular expression
|
2010-12-24 15:36:00 +03:00
|
|
|
reqBody, _ = Request.queryPage(reqPayload, place, content=True, raise404=False)
|
2010-12-18 13:42:09 +03:00
|
|
|
output = extractRegexResult(check, reqBody, re.DOTALL | re.IGNORECASE)
|
2010-12-07 22:19:12 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if output:
|
|
|
|
result = output.replace(kb.misc.space, " ") == "1"
|
2010-12-17 10:53:58 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
if result:
|
|
|
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
|
|
|
logger.info(infoMsg)
|
2010-12-07 15:33:47 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
injectable = True
|
2010-11-28 21:10:54 +03:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
# In case of time-based blind or stacked queries
|
|
|
|
# SQL injections
|
|
|
|
elif method == PAYLOAD.METHOD.TIME:
|
|
|
|
# Perform the test's request
|
2010-12-24 15:36:00 +03:00
|
|
|
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
|
2010-12-18 13:42:09 +03:00
|
|
|
|
|
|
|
if trueResult:
|
|
|
|
# Confirm test's results
|
2010-12-24 15:36:00 +03:00
|
|
|
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
|
2010-12-18 13:42:09 +03:00
|
|
|
|
|
|
|
if trueResult:
|
|
|
|
infoMsg = "%s parameter '%s' is '%s' injectable " % (place, parameter, title)
|
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
injectable = True
|
|
|
|
|
|
|
|
# If the injection test was successful feed the injection
|
|
|
|
# object with the test's details
|
|
|
|
if injectable is True:
|
|
|
|
# Feed with the boundaries details only the first time a
|
|
|
|
# test has been successful
|
|
|
|
if injection.place is None or injection.parameter is None:
|
|
|
|
if place == PLACE.UA:
|
|
|
|
injection.parameter = conf.agent
|
|
|
|
else:
|
|
|
|
injection.parameter = parameter
|
|
|
|
|
|
|
|
injection.place = place
|
|
|
|
injection.ptype = ptype
|
|
|
|
injection.prefix = prefix
|
|
|
|
injection.suffix = suffix
|
|
|
|
injection.clause = clause
|
|
|
|
|
|
|
|
if "vector" in test and test.vector is not None:
|
|
|
|
vector = "%s%s" % (test.vector, comment)
|
2010-12-01 20:09:52 +03:00
|
|
|
else:
|
2010-12-18 13:42:09 +03:00
|
|
|
vector = None
|
|
|
|
|
|
|
|
# Feed with test details every time a test is successful
|
|
|
|
injection.data[stype] = advancedDict()
|
|
|
|
injection.data[stype].title = title
|
|
|
|
injection.data[stype].payload = agent.removePayloadDelimiters(reqPayload, False)
|
|
|
|
injection.data[stype].where = where
|
|
|
|
injection.data[stype].vector = vector
|
|
|
|
injection.data[stype].comment = comment
|
|
|
|
injection.data[stype].matchRatio = kb.matchRatio
|
|
|
|
injection.data[stype].templatePayload = templatePayload
|
|
|
|
|
|
|
|
if hasattr(test, "details"):
|
|
|
|
for detailKey, detailValue in test.details.items():
|
|
|
|
if detailKey == "dbms" and injection.dbms is None:
|
|
|
|
injection.dbms = detailValue
|
|
|
|
kb.dbms = detailValue
|
|
|
|
elif detailKey == "dbms_version" and injection.dbms_version is None:
|
|
|
|
injection.dbms_version = detailValue
|
|
|
|
kb.dbmsVersion = [ detailValue ]
|
|
|
|
elif detailKey == "os" and injection.os is None:
|
|
|
|
injection.os = detailValue
|
|
|
|
|
2010-12-23 17:06:22 +03:00
|
|
|
if conf.beep or conf.realTest:
|
2010-12-18 13:42:09 +03:00
|
|
|
beep()
|
|
|
|
|
|
|
|
# There is no need to perform this test for other
|
|
|
|
# <where> tags
|
|
|
|
break
|
|
|
|
|
|
|
|
if injectable is True:
|
|
|
|
# There is no need to perform this test with others
|
|
|
|
# boundaries
|
2010-12-01 01:40:25 +03:00
|
|
|
break
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-12-18 13:42:09 +03:00
|
|
|
except KeyboardInterrupt:
|
2010-12-18 13:49:49 +03:00
|
|
|
warnMsg = "Ctrl+C detected in detection phase"
|
2010-12-18 13:42:09 +03:00
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
2010-12-21 02:34:00 +03:00
|
|
|
message = "How do you want to proceed? [(S)kip test/(e)nd detection phase/(n)ext parameter/(q)uit]"
|
2010-12-18 13:42:09 +03:00
|
|
|
test = readInput(message, default="S")
|
|
|
|
|
|
|
|
if not test or test[0] in ("s", "S"):
|
|
|
|
pass
|
2010-12-18 19:28:21 +03:00
|
|
|
elif test[0] in ("n", "N"):
|
2010-12-31 18:00:19 +03:00
|
|
|
return None
|
2010-12-21 02:34:00 +03:00
|
|
|
elif test[0] in ("e", "E"):
|
2010-12-22 02:55:55 +03:00
|
|
|
kb.endDetection = True
|
2010-12-18 13:42:09 +03:00
|
|
|
elif test[0] in ("q", "Q"):
|
|
|
|
raise sqlmapUserQuitException
|
2010-12-31 18:00:19 +03:00
|
|
|
finally:
|
|
|
|
# Flush the flag
|
|
|
|
kb.testMode = False
|
2010-12-04 18:47:02 +03:00
|
|
|
|
2010-12-01 01:40:25 +03:00
|
|
|
# Return the injection object
|
2010-11-29 00:27:47 +03:00
|
|
|
if injection.place is not None and injection.parameter is not None:
|
|
|
|
return injection
|
|
|
|
else:
|
|
|
|
return None
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-10-11 16:26:35 +04:00
|
|
|
def heuristicCheckSqlInjection(place, parameter, value):
|
2010-11-05 16:14:12 +03:00
|
|
|
if kb.nullConnection:
|
|
|
|
debugMsg = "heuristic checking skipped "
|
|
|
|
debugMsg += "because NULL connection used"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
return
|
|
|
|
|
2010-10-11 16:26:35 +04:00
|
|
|
prefix = ""
|
2010-11-18 01:00:09 +03:00
|
|
|
suffix = ""
|
2010-10-11 16:26:35 +04:00
|
|
|
|
2010-11-18 01:00:09 +03:00
|
|
|
if conf.prefix or conf.suffix:
|
2010-10-11 16:26:35 +04:00
|
|
|
if conf.prefix:
|
|
|
|
prefix = conf.prefix
|
|
|
|
|
2010-11-18 01:00:09 +03:00
|
|
|
if conf.suffix:
|
|
|
|
suffix = conf.suffix
|
2010-10-11 16:26:35 +04:00
|
|
|
|
2010-11-18 01:00:09 +03:00
|
|
|
payload = "%s%s%s%s" % (value, prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix)
|
2010-10-27 12:27:31 +04:00
|
|
|
payload = agent.payload(place, parameter, value, payload)
|
2011-01-03 11:32:06 +03:00
|
|
|
Request.queryPage(payload, place, content=True, raise404=False)
|
2010-12-22 22:12:46 +03:00
|
|
|
|
2010-12-22 16:09:04 +03:00
|
|
|
result = wasLastRequestDBMSError()
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-12-06 21:47:22 +03:00
|
|
|
infoMsg = "heuristic test shows that %s " % place
|
2010-11-16 13:52:49 +03:00
|
|
|
infoMsg += "parameter '%s' might " % parameter
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-11 16:26:35 +04:00
|
|
|
if result:
|
2011-01-02 19:51:21 +03:00
|
|
|
infoMsg += "be injectable (possible DBMS: %s)" % (getErrorParsedDBMSesFormatted() or 'Unknown')
|
2010-10-11 16:26:35 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
else:
|
2010-11-16 13:52:49 +03:00
|
|
|
infoMsg += "not be injectable"
|
2010-12-08 17:46:07 +03:00
|
|
|
logger.warn(infoMsg)
|
2010-10-11 16:26:35 +04:00
|
|
|
|
2010-12-20 13:13:14 +03:00
|
|
|
return result
|
|
|
|
|
2011-01-03 11:32:06 +03:00
|
|
|
def simpletonCheckSqlInjection(place, parameter, value):
|
|
|
|
"""
|
|
|
|
This is a function for the quickest and simplest
|
2011-01-03 14:06:49 +03:00
|
|
|
sql injection check (e.g. AND 1=1) - only works
|
|
|
|
with integer parameters
|
2011-01-03 11:32:06 +03:00
|
|
|
"""
|
|
|
|
|
|
|
|
result = False
|
|
|
|
randInt = randomInt()
|
2011-01-03 12:16:42 +03:00
|
|
|
randStr = randomStr()
|
|
|
|
|
|
|
|
if value.isdigit():
|
2011-01-03 13:37:20 +03:00
|
|
|
payload = "%s AND %d=%d" % (value, randInt, randInt)
|
2011-01-03 12:16:42 +03:00
|
|
|
else:
|
2011-01-03 14:06:49 +03:00
|
|
|
return False
|
2011-01-03 12:16:42 +03:00
|
|
|
|
2011-01-03 11:32:06 +03:00
|
|
|
payload = agent.payload(place, parameter, value, payload)
|
|
|
|
firstPage, _ = Request.queryPage(payload, place, content=True, raise404=False)
|
|
|
|
|
|
|
|
if not (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
|
2011-01-03 11:46:20 +03:00
|
|
|
if getComparePageRatio(kb.originalPage, firstPage, filtered=True) > CONSTANT_RATIO:
|
2011-01-03 14:06:49 +03:00
|
|
|
payload = "%s AND %d=%d" % (value, randInt, randInt+1)
|
2011-01-03 12:16:42 +03:00
|
|
|
|
2011-01-03 11:32:06 +03:00
|
|
|
payload = agent.payload(place, parameter, value, payload)
|
|
|
|
secondPage, _ = Request.queryPage(payload, place, content=True, raise404=False)
|
2011-01-03 11:46:20 +03:00
|
|
|
result = getComparePageRatio(firstPage, secondPage, filtered=True) <= CONSTANT_RATIO
|
2011-01-03 11:32:06 +03:00
|
|
|
|
|
|
|
infoMsg = "simpleton test shows that %s " % place
|
|
|
|
infoMsg += "parameter '%s' might " % parameter
|
|
|
|
|
|
|
|
if result:
|
|
|
|
infoMsg += "be injectable"
|
|
|
|
logger.info(infoMsg)
|
|
|
|
else:
|
|
|
|
infoMsg += "not be injectable"
|
|
|
|
logger.warn(infoMsg)
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
2008-10-15 19:38:22 +04:00
|
|
|
def checkDynParam(place, parameter, value):
|
|
|
|
"""
|
|
|
|
This function checks if the url parameter is dynamic. If it is
|
|
|
|
dynamic, the content of the page differs, otherwise the
|
|
|
|
dynamicity might depend on another parameter.
|
|
|
|
"""
|
|
|
|
|
2010-12-18 12:51:34 +03:00
|
|
|
kb.matchRatio = None
|
2010-11-10 01:44:23 +03:00
|
|
|
|
2008-12-09 00:24:24 +03:00
|
|
|
infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
|
|
|
|
logger.info(infoMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
randInt = randomInt()
|
2010-06-02 16:45:40 +04:00
|
|
|
payload = agent.payload(place, parameter, value, getUnicode(randInt))
|
2010-12-21 14:04:49 +03:00
|
|
|
dynResult = Request.queryPage(payload, place, raise404=False)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-11-05 16:14:12 +03:00
|
|
|
if True == dynResult:
|
2008-10-15 19:38:22 +04:00
|
|
|
return False
|
|
|
|
|
2008-12-09 00:24:24 +03:00
|
|
|
infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
|
|
|
|
logger.info(infoMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-11-05 16:14:12 +03:00
|
|
|
randInt = randomInt()
|
|
|
|
payload = agent.payload(place, parameter, value, getUnicode(randInt))
|
2010-12-21 14:04:49 +03:00
|
|
|
dynResult = Request.queryPage(payload, place, raise404=False)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-11-05 16:14:12 +03:00
|
|
|
return not dynResult
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-10-25 14:41:37 +04:00
|
|
|
def checkDynamicContent(firstPage, secondPage):
|
2010-09-14 01:01:46 +04:00
|
|
|
"""
|
2010-12-29 22:39:32 +03:00
|
|
|
This function checks for the dynamic content in the provided pages
|
2010-09-14 01:01:46 +04:00
|
|
|
"""
|
2010-11-04 12:18:32 +03:00
|
|
|
|
2010-11-04 00:51:36 +03:00
|
|
|
if kb.nullConnection:
|
2010-11-04 12:18:32 +03:00
|
|
|
debugMsg = "dynamic content checking skipped "
|
|
|
|
debugMsg += "because NULL connection used"
|
|
|
|
logger.debug(debugMsg)
|
2010-11-04 00:51:36 +03:00
|
|
|
return
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-11-07 11:52:09 +03:00
|
|
|
if conf.longestCommon:
|
|
|
|
debugMsg = "dynamic content checking skipped "
|
|
|
|
debugMsg += "because longest common comparison used"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
return
|
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
conf.seqMatcher.set_seq1(firstPage)
|
|
|
|
conf.seqMatcher.set_seq2(secondPage)
|
2010-10-07 02:29:52 +04:00
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
# In case of an intolerable difference turn on dynamicity removal engine
|
|
|
|
if conf.seqMatcher.quick_ratio() <= UPPER_RATIO_BOUND:
|
|
|
|
findDynamicContent(firstPage, secondPage)
|
2010-10-25 23:45:53 +04:00
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
count = 0
|
|
|
|
while not Request.queryPage():
|
|
|
|
count += 1
|
2010-10-25 14:41:37 +04:00
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
if count > conf.retries:
|
2011-01-03 14:06:49 +03:00
|
|
|
warnMsg = "target url is too dynamic. "
|
|
|
|
warnMsg += "switching to --text-only. "
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
|
|
|
conf.textOnly = True
|
|
|
|
setTextOnly()
|
|
|
|
return
|
2010-10-25 23:45:53 +04:00
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
warnMsg = "target url is heavily dynamic"
|
|
|
|
warnMsg += ", sqlmap is going to retry the request"
|
|
|
|
logger.critical(warnMsg)
|
2010-10-25 23:45:53 +04:00
|
|
|
|
2010-12-29 22:39:32 +03:00
|
|
|
secondPage, _ = Request.queryPage(content=True)
|
|
|
|
findDynamicContent(firstPage, secondPage)
|
2010-09-13 17:31:01 +04:00
|
|
|
|
2010-12-29 22:48:19 +03:00
|
|
|
setDynamicMarkings(kb.dynamicMarkings)
|
|
|
|
|
2008-10-15 19:38:22 +04:00
|
|
|
def checkStability():
|
|
|
|
"""
|
|
|
|
This function checks if the URL content is stable requesting the
|
2010-09-13 19:19:47 +04:00
|
|
|
same page two times with a small delay within each request to
|
2008-10-15 19:38:22 +04:00
|
|
|
assume that it is stable.
|
|
|
|
|
|
|
|
In case the content of the page differs when requesting
|
|
|
|
the same page, the dynamicity might depend on other parameters,
|
|
|
|
like for instance string matching (--string).
|
|
|
|
"""
|
|
|
|
|
2008-12-09 00:24:24 +03:00
|
|
|
infoMsg = "testing if the url is stable, wait a few seconds"
|
|
|
|
logger.info(infoMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-12-06 21:20:57 +03:00
|
|
|
firstPage = kb.originalPage # set inside checkConnection()
|
2008-12-21 19:35:03 +03:00
|
|
|
time.sleep(1)
|
2009-04-28 03:05:11 +04:00
|
|
|
secondPage, _ = Request.queryPage(content=True)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-10-25 17:52:21 +04:00
|
|
|
kb.pageStable = (firstPage == secondPage)
|
2008-12-18 23:48:23 +03:00
|
|
|
|
2010-10-25 17:52:21 +04:00
|
|
|
if kb.pageStable:
|
2010-02-10 12:27:34 +03:00
|
|
|
if firstPage:
|
|
|
|
logMsg = "url is stable"
|
|
|
|
logger.info(logMsg)
|
|
|
|
else:
|
2010-03-16 15:14:02 +03:00
|
|
|
errMsg = "there was an error checking the stability of page "
|
|
|
|
errMsg += "because of lack of content. please check the "
|
|
|
|
errMsg += "page request results (and probable errors) by "
|
|
|
|
errMsg += "using higher verbosity levels"
|
|
|
|
raise sqlmapNoneDataException, errMsg
|
2009-02-09 13:28:03 +03:00
|
|
|
|
2010-10-25 17:52:21 +04:00
|
|
|
else:
|
2008-12-20 04:54:08 +03:00
|
|
|
warnMsg = "url is not stable, sqlmap will base the page "
|
2010-10-16 19:10:48 +04:00
|
|
|
warnMsg += "comparison on a sequence matcher. If no dynamic nor "
|
|
|
|
warnMsg += "injectable parameters are detected, or in case of "
|
|
|
|
warnMsg += "junk results, refer to user's manual paragraph "
|
|
|
|
warnMsg += "'Page comparison' and provide a string or regular "
|
|
|
|
warnMsg += "expression to match on"
|
2008-12-20 04:54:08 +03:00
|
|
|
logger.warn(warnMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2011-01-06 11:54:50 +03:00
|
|
|
message = "how do you want to proceed? [C(ontinue)/s(tring)/r(egex)/t(ext only)q(uit)] "
|
2010-12-23 17:06:22 +03:00
|
|
|
if not conf.realTest:
|
2010-12-20 13:32:58 +03:00
|
|
|
test = readInput(message, default="C")
|
|
|
|
else:
|
|
|
|
test = None
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
if test and test[0] in ("q", "Q"):
|
|
|
|
raise sqlmapUserQuitException
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
elif test and test[0] in ("s", "S"):
|
|
|
|
showStaticWords(firstPage, secondPage)
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
message = "please enter value for parameter 'string': "
|
|
|
|
test = readInput(message)
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
if test:
|
|
|
|
conf.string = test
|
2011-01-06 11:54:50 +03:00
|
|
|
setString()
|
2010-11-04 12:18:32 +03:00
|
|
|
|
|
|
|
if kb.nullConnection:
|
|
|
|
debugMsg = "turning off NULL connection "
|
|
|
|
debugMsg += "support because of string checking"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
|
|
|
kb.nullConnection = None
|
2010-10-12 19:49:04 +04:00
|
|
|
else:
|
2010-11-10 22:44:51 +03:00
|
|
|
errMsg = "Empty value supplied"
|
|
|
|
raise sqlmapNoneDataException, errMsg
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
elif test and test[0] in ("r", "R"):
|
|
|
|
message = "please enter value for parameter 'regex': "
|
|
|
|
test = readInput(message)
|
2010-10-16 19:10:48 +04:00
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
if test:
|
|
|
|
conf.regex = test
|
2011-01-06 11:54:50 +03:00
|
|
|
setRegexp()
|
2010-11-04 12:18:32 +03:00
|
|
|
|
|
|
|
if kb.nullConnection:
|
|
|
|
debugMsg = "turning off NULL connection "
|
|
|
|
debugMsg += "support because of regex checking"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
|
|
|
kb.nullConnection = None
|
2010-10-12 19:49:04 +04:00
|
|
|
else:
|
2010-11-10 22:44:51 +03:00
|
|
|
errMsg = "Empty value supplied"
|
|
|
|
raise sqlmapNoneDataException, errMsg
|
2011-01-06 11:54:50 +03:00
|
|
|
|
|
|
|
elif test and test[0] in ("t", "T"):
|
|
|
|
conf.textOnly = True
|
|
|
|
setTextOnly()
|
|
|
|
|
|
|
|
if kb.nullConnection:
|
|
|
|
debugMsg = "turning off NULL connection "
|
|
|
|
debugMsg += "support because of regex checking"
|
|
|
|
logger.debug(debugMsg)
|
|
|
|
|
|
|
|
kb.nullConnection = None
|
|
|
|
|
2010-10-12 19:49:04 +04:00
|
|
|
else:
|
2010-12-29 22:39:32 +03:00
|
|
|
checkDynamicContent(firstPage, secondPage)
|
2010-11-29 18:25:45 +03:00
|
|
|
|
2010-10-25 17:52:21 +04:00
|
|
|
return kb.pageStable
|
2010-03-12 15:23:05 +03:00
|
|
|
|
2008-10-15 19:38:22 +04:00
|
|
|
def checkString():
|
|
|
|
if not conf.string:
|
|
|
|
return True
|
|
|
|
|
|
|
|
condition = (
|
|
|
|
kb.resumedQueries.has_key(conf.url) and
|
|
|
|
kb.resumedQueries[conf.url].has_key("String") and
|
|
|
|
kb.resumedQueries[conf.url]["String"][:-1] == conf.string
|
|
|
|
)
|
|
|
|
|
|
|
|
if condition:
|
|
|
|
return True
|
|
|
|
|
2008-12-09 00:24:24 +03:00
|
|
|
infoMsg = "testing if the provided string is within the "
|
|
|
|
infoMsg += "target URL page content"
|
|
|
|
logger.info(infoMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2008-12-18 23:48:23 +03:00
|
|
|
page, _ = Request.queryPage(content=True)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
if conf.string in page:
|
|
|
|
setString()
|
|
|
|
else:
|
2010-11-18 01:00:09 +03:00
|
|
|
warnMsg = "you provided '%s' as the string to " % conf.string
|
|
|
|
warnMsg += "match, but such a string is not within the target "
|
|
|
|
warnMsg += "URL page content original request, sqlmap will "
|
|
|
|
warnMsg += "keep going anyway"
|
|
|
|
logger.warn(warnMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2010-11-18 01:00:09 +03:00
|
|
|
return True
|
2008-10-15 19:38:22 +04:00
|
|
|
|
2008-12-12 22:06:31 +03:00
|
|
|
def checkRegexp():
|
|
|
|
if not conf.regexp:
|
|
|
|
return True
|
|
|
|
|
|
|
|
condition = (
|
|
|
|
kb.resumedQueries.has_key(conf.url) and
|
|
|
|
kb.resumedQueries[conf.url].has_key("Regular expression") and
|
|
|
|
kb.resumedQueries[conf.url]["Regular expression"][:-1] == conf.regexp
|
|
|
|
)
|
|
|
|
|
|
|
|
if condition:
|
|
|
|
return True
|
|
|
|
|
|
|
|
infoMsg = "testing if the provided regular expression matches within "
|
|
|
|
infoMsg += "the target URL page content"
|
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2008-12-18 23:48:23 +03:00
|
|
|
page, _ = Request.queryPage(content=True)
|
2008-12-12 22:06:31 +03:00
|
|
|
|
|
|
|
if re.search(conf.regexp, page, re.I | re.M):
|
|
|
|
setRegexp()
|
|
|
|
else:
|
2010-11-18 01:00:09 +03:00
|
|
|
warnMsg = "you provided '%s' as the regular expression to " % conf.regexp
|
|
|
|
warnMsg += "match, but such a regular expression does not have any "
|
|
|
|
warnMsg += "match within the target URL page content, sqlmap "
|
|
|
|
warnMsg += "will keep going anyway"
|
|
|
|
logger.warn(warnMsg)
|
2008-12-12 22:06:31 +03:00
|
|
|
|
2010-11-18 01:00:09 +03:00
|
|
|
return True
|
2008-12-12 22:06:31 +03:00
|
|
|
|
2010-09-16 12:43:10 +04:00
|
|
|
def checkNullConnection():
|
2010-10-15 15:17:17 +04:00
|
|
|
"""
|
|
|
|
Reference: http://www.wisec.it/sectou.php?id=472f952d79293
|
|
|
|
"""
|
|
|
|
|
2010-09-16 12:43:10 +04:00
|
|
|
infoMsg = "testing NULL connection to the target url"
|
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
try:
|
2010-11-08 12:49:57 +03:00
|
|
|
page, headers = Request.getPage(method=HTTPMETHOD.HEAD)
|
2010-12-06 18:50:19 +03:00
|
|
|
|
2010-09-16 12:43:10 +04:00
|
|
|
if not page and 'Content-Length' in headers:
|
2010-11-08 12:49:57 +03:00
|
|
|
kb.nullConnection = NULLCONNECTION.HEAD
|
2010-10-15 14:24:54 +04:00
|
|
|
|
2010-10-15 16:46:41 +04:00
|
|
|
infoMsg = "NULL connection is supported with HEAD header"
|
2010-10-15 14:24:54 +04:00
|
|
|
logger.info(infoMsg)
|
2010-09-16 12:43:10 +04:00
|
|
|
else:
|
2010-11-08 16:26:45 +03:00
|
|
|
page, headers = Request.getPage(auxHeaders={"Range": "bytes=-1"})
|
2010-12-06 18:50:19 +03:00
|
|
|
|
2010-09-16 12:43:10 +04:00
|
|
|
if page and len(page) == 1 and 'Content-Range' in headers:
|
2010-11-08 12:49:57 +03:00
|
|
|
kb.nullConnection = NULLCONNECTION.RANGE
|
2010-09-16 12:43:10 +04:00
|
|
|
|
2010-10-15 16:46:41 +04:00
|
|
|
infoMsg = "NULL connection is supported with GET header "
|
2010-10-15 14:24:54 +04:00
|
|
|
infoMsg += "'%s'" % kb.nullConnection
|
|
|
|
logger.info(infoMsg)
|
2010-12-06 18:50:19 +03:00
|
|
|
|
2010-09-16 12:43:10 +04:00
|
|
|
except sqlmapConnectionException, errMsg:
|
|
|
|
errMsg = getUnicode(errMsg)
|
|
|
|
raise sqlmapConnectionException, errMsg
|
|
|
|
|
|
|
|
return kb.nullConnection is not None
|
|
|
|
|
2010-11-15 15:19:22 +03:00
|
|
|
def checkConnection(suppressOutput=False):
|
2010-05-21 17:36:49 +04:00
|
|
|
try:
|
|
|
|
socket.gethostbyname(conf.hostname)
|
|
|
|
except socket.gaierror:
|
2010-05-21 18:25:38 +04:00
|
|
|
errMsg = "host '%s' does not exist" % conf.hostname
|
2010-05-21 17:36:49 +04:00
|
|
|
raise sqlmapConnectionException, errMsg
|
|
|
|
|
2010-11-15 15:19:22 +03:00
|
|
|
if not suppressOutput:
|
|
|
|
infoMsg = "testing connection to the target url"
|
|
|
|
logger.info(infoMsg)
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
try:
|
2010-11-08 02:25:53 +03:00
|
|
|
page, _ = Request.queryPage(content=True)
|
2010-12-06 21:20:57 +03:00
|
|
|
kb.originalPage = kb.pageTemplate = page
|
2011-01-01 23:19:55 +03:00
|
|
|
|
|
|
|
kb.errorIsNone = False
|
|
|
|
if wasLastRequestDBMSError():
|
|
|
|
warnMsg = "there is an (DBMS) error found in the content of provided target url"
|
|
|
|
warnMsg += " which could interfere with the results of the tests"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
elif wasLastRequestHTTPError():
|
|
|
|
warnMsg = "there is an (HTTP) error found in the content of provided target url"
|
|
|
|
warnMsg += " which could interfere with the results of the tests"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
else:
|
|
|
|
kb.errorIsNone = True
|
2010-03-16 15:14:02 +03:00
|
|
|
except sqlmapConnectionException, errMsg:
|
2010-06-02 16:45:40 +04:00
|
|
|
errMsg = getUnicode(errMsg)
|
2010-03-16 15:14:02 +03:00
|
|
|
raise sqlmapConnectionException, errMsg
|
2008-10-15 19:38:22 +04:00
|
|
|
|
|
|
|
return True
|