mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-07-28 00:50:06 +03:00
Update checks.py
This commit is contained in:
parent
83e46b02a8
commit
dd89d0afd0
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
||||||
|
@ -6,7 +6,6 @@ See the file 'LICENSE' for copying permission
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import httplib
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
|
@ -22,6 +21,7 @@ from lib.core.agent import agent
|
||||||
from lib.core.common import Backend
|
from lib.core.common import Backend
|
||||||
from lib.core.common import extractRegexResult
|
from lib.core.common import extractRegexResult
|
||||||
from lib.core.common import extractTextTagContent
|
from lib.core.common import extractTextTagContent
|
||||||
|
from lib.core.common import filterNone
|
||||||
from lib.core.common import findDynamicContent
|
from lib.core.common import findDynamicContent
|
||||||
from lib.core.common import Format
|
from lib.core.common import Format
|
||||||
from lib.core.common import getFilteredPageContent
|
from lib.core.common import getFilteredPageContent
|
||||||
|
@ -48,7 +48,7 @@ from lib.core.common import unArrayizeValue
|
||||||
from lib.core.common import urlencode
|
from lib.core.common import urlencode
|
||||||
from lib.core.common import wasLastResponseDBMSError
|
from lib.core.common import wasLastResponseDBMSError
|
||||||
from lib.core.common import wasLastResponseHTTPError
|
from lib.core.common import wasLastResponseHTTPError
|
||||||
from lib.core.convert import unicodeencode
|
from lib.core.compat import xrange
|
||||||
from lib.core.defaults import defaults
|
from lib.core.defaults import defaults
|
||||||
from lib.core.data import conf
|
from lib.core.data import conf
|
||||||
from lib.core.data import kb
|
from lib.core.data import kb
|
||||||
|
@ -99,6 +99,7 @@ from lib.core.settings import SUPPORTED_DBMS
|
||||||
from lib.core.settings import UNICODE_ENCODING
|
from lib.core.settings import UNICODE_ENCODING
|
||||||
from lib.core.settings import URI_HTTP_HEADER
|
from lib.core.settings import URI_HTTP_HEADER
|
||||||
from lib.core.settings import UPPER_RATIO_BOUND
|
from lib.core.settings import UPPER_RATIO_BOUND
|
||||||
|
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
||||||
from lib.core.threads import getCurrentThreadData
|
from lib.core.threads import getCurrentThreadData
|
||||||
from lib.request.connect import Connect as Request
|
from lib.request.connect import Connect as Request
|
||||||
from lib.request.comparison import comparison
|
from lib.request.comparison import comparison
|
||||||
|
@ -106,7 +107,8 @@ from lib.request.inject import checkBooleanExpression
|
||||||
from lib.request.templates import getPageTemplate
|
from lib.request.templates import getPageTemplate
|
||||||
from lib.techniques.union.test import unionTest
|
from lib.techniques.union.test import unionTest
|
||||||
from lib.techniques.union.use import configUnion
|
from lib.techniques.union.use import configUnion
|
||||||
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
from thirdparty import six
|
||||||
|
from thirdparty.six.moves import http_client as _http_client
|
||||||
|
|
||||||
def checkSqlInjection(place, parameter, value):
|
def checkSqlInjection(place, parameter, value):
|
||||||
# Store here the details about boundaries and payload used to
|
# Store here the details about boundaries and payload used to
|
||||||
|
@ -580,7 +582,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
else:
|
else:
|
||||||
errorSet = set()
|
errorSet = set()
|
||||||
|
|
||||||
candidates = filter(None, (_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet - errorSet)))
|
candidates = filterNone(_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet - errorSet))
|
||||||
|
|
||||||
if candidates:
|
if candidates:
|
||||||
candidates = sorted(candidates, key=lambda _: len(_))
|
candidates = sorted(candidates, key=lambda _: len(_))
|
||||||
|
@ -594,7 +596,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if not any((conf.string, conf.notString)):
|
if not any((conf.string, conf.notString)):
|
||||||
candidates = filter(None, (_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet)))
|
candidates = filterNone(_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet))
|
||||||
|
|
||||||
if candidates:
|
if candidates:
|
||||||
candidates = sorted(candidates, key=lambda _: len(_))
|
candidates = sorted(candidates, key=lambda _: len(_))
|
||||||
|
@ -693,7 +695,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# Test for UNION query SQL injection
|
# Test for UNION query SQL injection
|
||||||
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
|
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
|
||||||
|
|
||||||
if isinstance(reqPayload, basestring):
|
if isinstance(reqPayload, six.string_types):
|
||||||
infoMsg = "%s parameter '%s' is '%s' injectable" % (paramType, parameter, title)
|
infoMsg = "%s parameter '%s' is '%s' injectable" % (paramType, parameter, title)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
|
@ -920,17 +922,17 @@ def checkFalsePositives(injection):
|
||||||
|
|
||||||
# Just in case if DBMS hasn't properly recovered from previous delayed request
|
# Just in case if DBMS hasn't properly recovered from previous delayed request
|
||||||
if PAYLOAD.TECHNIQUE.BOOLEAN not in injection.data:
|
if PAYLOAD.TECHNIQUE.BOOLEAN not in injection.data:
|
||||||
checkBooleanExpression("%d%s%d" % (randInt1,INFERENCE_EQUALS_CHAR, randInt2))
|
checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt2))
|
||||||
|
|
||||||
if checkBooleanExpression("%d%s%d" % (randInt1,INFERENCE_EQUALS_CHAR, randInt3)): # this must not be evaluated to True
|
if checkBooleanExpression("%d%s%d" % (randInt1, INFERENCE_EQUALS_CHAR, randInt3)): # this must not be evaluated to True
|
||||||
retVal = False
|
retVal = False
|
||||||
break
|
break
|
||||||
|
|
||||||
elif checkBooleanExpression("%d%s%d" % (randInt3,INFERENCE_EQUALS_CHAR, randInt2)): # this must not be evaluated to True
|
elif checkBooleanExpression("%d%s%d" % (randInt3, INFERENCE_EQUALS_CHAR, randInt2)): # this must not be evaluated to True
|
||||||
retVal = False
|
retVal = False
|
||||||
break
|
break
|
||||||
|
|
||||||
elif not checkBooleanExpression("%d%s%d" % (randInt2,INFERENCE_EQUALS_CHAR, randInt2)): # this must be evaluated to True
|
elif not checkBooleanExpression("%d%s%d" % (randInt2, INFERENCE_EQUALS_CHAR, randInt2)): # this must be evaluated to True
|
||||||
retVal = False
|
retVal = False
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1338,6 +1340,9 @@ def checkWaf():
|
||||||
if any((conf.string, conf.notString, conf.regexp, conf.dummy, conf.offline, conf.skipWaf)):
|
if any((conf.string, conf.notString, conf.regexp, conf.dummy, conf.offline, conf.skipWaf)):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if kb.originalCode == _http_client.NOT_FOUND:
|
||||||
|
return None
|
||||||
|
|
||||||
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_WAF_RESULT, True)
|
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_WAF_RESULT, True)
|
||||||
if _ is not None:
|
if _ is not None:
|
||||||
if _:
|
if _:
|
||||||
|
@ -1422,17 +1427,24 @@ def identifyWaf():
|
||||||
page, headers, code = None, None, None
|
page, headers, code = None, None, None
|
||||||
try:
|
try:
|
||||||
pushValue(kb.redirectChoice)
|
pushValue(kb.redirectChoice)
|
||||||
|
pushValue(kb.resendPostOnRedirect)
|
||||||
|
|
||||||
kb.redirectChoice = REDIRECTION.YES
|
kb.redirectChoice = REDIRECTION.YES
|
||||||
|
kb.resendPostOnRedirect = True
|
||||||
|
|
||||||
if kwargs.get("get"):
|
if kwargs.get("get"):
|
||||||
kwargs["get"] = urlencode(kwargs["get"])
|
kwargs["get"] = urlencode(kwargs["get"])
|
||||||
kwargs["raise404"] = False
|
kwargs["raise404"] = False
|
||||||
kwargs["silent"] = True
|
kwargs["silent"] = True
|
||||||
kwargs["finalCode"] = True
|
kwargs["finalCode"] = True
|
||||||
|
|
||||||
page, headers, code = Request.getPage(*args, **kwargs)
|
page, headers, code = Request.getPage(*args, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
|
kb.resendPostOnRedirect = popValue()
|
||||||
kb.redirectChoice = popValue()
|
kb.redirectChoice = popValue()
|
||||||
|
|
||||||
return page or "", headers or {}, code
|
return page or "", headers or {}, code
|
||||||
|
|
||||||
retVal = []
|
retVal = []
|
||||||
|
@ -1498,46 +1510,59 @@ def checkNullConnection():
|
||||||
if conf.data:
|
if conf.data:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
infoMsg = "testing NULL connection to the target URL"
|
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_NULL_CONNECTION_RESULT, True)
|
||||||
logger.info(infoMsg)
|
if _ is not None:
|
||||||
|
kb.nullConnection = _
|
||||||
|
|
||||||
pushValue(kb.pageCompress)
|
if _:
|
||||||
kb.pageCompress = False
|
dbgMsg = "resuming NULL connection method '%s'" % _
|
||||||
|
logger.debug(dbgMsg)
|
||||||
|
|
||||||
try:
|
else:
|
||||||
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
|
infoMsg = "testing NULL connection to the target URL"
|
||||||
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
pushValue(kb.pageCompress)
|
||||||
kb.nullConnection = NULLCONNECTION.HEAD
|
kb.pageCompress = False
|
||||||
|
|
||||||
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
|
try:
|
||||||
logger.info(infoMsg)
|
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
|
||||||
else:
|
|
||||||
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
|
|
||||||
|
|
||||||
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
|
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||||
kb.nullConnection = NULLCONNECTION.RANGE
|
kb.nullConnection = NULLCONNECTION.HEAD
|
||||||
|
|
||||||
infoMsg = "NULL connection is supported with GET method ('Range')"
|
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
else:
|
else:
|
||||||
_, headers, _ = Request.getPage(skipRead=True)
|
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
|
||||||
|
|
||||||
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
|
||||||
kb.nullConnection = NULLCONNECTION.SKIP_READ
|
kb.nullConnection = NULLCONNECTION.RANGE
|
||||||
|
|
||||||
infoMsg = "NULL connection is supported with 'skip-read' method"
|
infoMsg = "NULL connection is supported with GET method ('Range')"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
else:
|
||||||
|
_, headers, _ = Request.getPage(skipRead=True)
|
||||||
|
|
||||||
except SqlmapConnectionException:
|
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
|
||||||
pass
|
kb.nullConnection = NULLCONNECTION.SKIP_READ
|
||||||
|
|
||||||
finally:
|
infoMsg = "NULL connection is supported with 'skip-read' method"
|
||||||
kb.pageCompress = popValue()
|
logger.info(infoMsg)
|
||||||
|
|
||||||
return kb.nullConnection is not None
|
except SqlmapConnectionException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
finally:
|
||||||
|
kb.pageCompress = popValue()
|
||||||
|
kb.nullConnection = False if kb.nullConnection is None else kb.nullConnection
|
||||||
|
hashDBWrite(HASHDB_KEYS.CHECK_NULL_CONNECTION_RESULT, kb.nullConnection, True)
|
||||||
|
|
||||||
|
return kb.nullConnection in getPublicTypeMembers(NULLCONNECTION, True)
|
||||||
|
|
||||||
def checkConnection(suppressOutput=False):
|
def checkConnection(suppressOutput=False):
|
||||||
|
threadData = getCurrentThreadData()
|
||||||
|
|
||||||
if not re.search(r"\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z", conf.hostname):
|
if not re.search(r"\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\Z", conf.hostname):
|
||||||
if not any((conf.proxy, conf.tor, conf.dummy, conf.offline)):
|
if not any((conf.proxy, conf.tor, conf.dummy, conf.offline)):
|
||||||
try:
|
try:
|
||||||
|
@ -1562,8 +1587,7 @@ def checkConnection(suppressOutput=False):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
kb.originalPageTime = time.time()
|
kb.originalPageTime = time.time()
|
||||||
page, headers, _ = Request.queryPage(content=True, noteResponseTime=False)
|
Request.queryPage(content=True, noteResponseTime=False)
|
||||||
kb.originalPage = kb.pageTemplate = page
|
|
||||||
|
|
||||||
kb.errorIsNone = False
|
kb.errorIsNone = False
|
||||||
|
|
||||||
|
@ -1586,10 +1610,8 @@ def checkConnection(suppressOutput=False):
|
||||||
else:
|
else:
|
||||||
kb.errorIsNone = True
|
kb.errorIsNone = True
|
||||||
|
|
||||||
threadData = getCurrentThreadData()
|
|
||||||
|
|
||||||
if kb.redirectChoice == REDIRECTION.YES and threadData.lastRedirectURL and threadData.lastRedirectURL[0] == threadData.lastRequestUID:
|
if kb.redirectChoice == REDIRECTION.YES and threadData.lastRedirectURL and threadData.lastRedirectURL[0] == threadData.lastRequestUID:
|
||||||
if (threadData.lastRedirectURL[1] or "").startswith("https://") and unicodeencode(conf.hostname) in threadData.lastRedirectURL[1]:
|
if (threadData.lastRedirectURL[1] or "").startswith("https://") and conf.hostname in getUnicode(threadData.lastRedirectURL[1]):
|
||||||
conf.url = re.sub(r"https?://", "https://", conf.url)
|
conf.url = re.sub(r"https?://", "https://", conf.url)
|
||||||
match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
|
match = re.search(r":(\d+)", threadData.lastRedirectURL[1])
|
||||||
port = match.group(1) if match else 443
|
port = match.group(1) if match else 443
|
||||||
|
@ -1604,7 +1626,7 @@ def checkConnection(suppressOutput=False):
|
||||||
warnMsg += "any addressing issues"
|
warnMsg += "any addressing issues"
|
||||||
singleTimeWarnMessage(warnMsg)
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if any(code in kb.httpErrorCodes for code in (httplib.NOT_FOUND, )):
|
if any(code in kb.httpErrorCodes for code in (_http_client.NOT_FOUND, )):
|
||||||
errMsg = getSafeExString(ex)
|
errMsg = getSafeExString(ex)
|
||||||
logger.critical(errMsg)
|
logger.critical(errMsg)
|
||||||
|
|
||||||
|
@ -1618,6 +1640,9 @@ def checkConnection(suppressOutput=False):
|
||||||
kb.ignoreNotFound = True
|
kb.ignoreNotFound = True
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
finally:
|
||||||
|
kb.originalPage = kb.pageTemplate = threadData.lastPage
|
||||||
|
kb.originalCode = threadData.lastCode
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user