Update checks.py

This commit is contained in:
gweeperx 2019-04-25 14:40:48 +03:00 committed by GitHub
parent 83e46b02a8
commit dd89d0afd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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