Update checks.py

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

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python2 #!/usr/bin/env python
""" """
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/) Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
@ -6,6 +6,7 @@ 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
@ -21,7 +22,6 @@ 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.compat import xrange from lib.core.convert import unicodeencode
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
@ -106,8 +106,7 @@ 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 thirdparty import six from lib.core.settings import INFERENCE_EQUALS_CHAR
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
@ -581,7 +580,7 @@ def checkSqlInjection(place, parameter, value):
else: else:
errorSet = set() errorSet = set()
candidates = filterNone(_.strip() if _.strip() in trueRawResponse and _.strip() not in falseRawResponse else None for _ in (trueSet - falseSet - errorSet)) candidates = filter(None, (_.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(_))
@ -595,7 +594,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 = filterNone(_.strip() if _.strip() in falseRawResponse and _.strip() not in trueRawResponse else None for _ in (falseSet - trueSet)) candidates = filter(None, (_.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(_))
@ -694,7 +693,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, six.string_types): if isinstance(reqPayload, basestring):
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)
@ -915,23 +914,23 @@ def checkFalsePositives(injection):
if randInt3 > randInt2 > randInt1: if randInt3 > randInt2 > randInt1:
break break
if not checkBooleanExpression("%d=%d" % (randInt1, randInt1)): if not checkBooleanExpression("%d%s%d" % (randInt1,INFERENCE_EQUALS_CHAR, randInt1)):
retVal = False retVal = False
break break
# 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=%d" % (randInt1, randInt2)) checkBooleanExpression("%d%s%d" % (randInt1,INFERENCE_EQUALS_CHAR, randInt2))
if checkBooleanExpression("%d=%d" % (randInt1, 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=%d" % (randInt3, 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=%d" % (randInt2, 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
@ -1339,9 +1338,6 @@ 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 _:
@ -1426,24 +1422,17 @@ 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 = []
@ -1509,59 +1498,46 @@ def checkNullConnection():
if conf.data: if conf.data:
return False return False
_ = hashDBRetrieve(HASHDB_KEYS.CHECK_NULL_CONNECTION_RESULT, True) infoMsg = "testing NULL connection to the target URL"
if _ is not None: logger.info(infoMsg)
kb.nullConnection = _
if _: pushValue(kb.pageCompress)
dbgMsg = "resuming NULL connection method '%s'" % _ kb.pageCompress = False
logger.debug(dbgMsg)
else: try:
infoMsg = "testing NULL connection to the target URL" page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False)
logger.info(infoMsg)
pushValue(kb.pageCompress) if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
kb.pageCompress = False kb.nullConnection = NULLCONNECTION.HEAD
try: infoMsg = "NULL connection is supported with HEAD method ('Content-Length')"
page, headers, _ = Request.getPage(method=HTTPMETHOD.HEAD, raise404=False) logger.info(infoMsg)
else:
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"})
if not page and HTTP_HEADER.CONTENT_LENGTH in (headers or {}): if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}):
kb.nullConnection = NULLCONNECTION.HEAD kb.nullConnection = NULLCONNECTION.RANGE
infoMsg = "NULL connection is supported with HEAD method ('Content-Length')" infoMsg = "NULL connection is supported with GET method ('Range')"
logger.info(infoMsg) logger.info(infoMsg)
else: else:
page, headers, _ = Request.getPage(auxHeaders={HTTP_HEADER.RANGE: "bytes=-1"}) _, headers, _ = Request.getPage(skipRead=True)
if page and len(page) == 1 and HTTP_HEADER.CONTENT_RANGE in (headers or {}): if HTTP_HEADER.CONTENT_LENGTH in (headers or {}):
kb.nullConnection = NULLCONNECTION.RANGE kb.nullConnection = NULLCONNECTION.SKIP_READ
infoMsg = "NULL connection is supported with GET method ('Range')" infoMsg = "NULL connection is supported with 'skip-read' method"
logger.info(infoMsg) logger.info(infoMsg)
else:
_, headers, _ = Request.getPage(skipRead=True)
if HTTP_HEADER.CONTENT_LENGTH in (headers or {}): except SqlmapConnectionException:
kb.nullConnection = NULLCONNECTION.SKIP_READ pass
infoMsg = "NULL connection is supported with 'skip-read' method" finally:
logger.info(infoMsg) kb.pageCompress = popValue()
except SqlmapConnectionException: return kb.nullConnection is not None
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:
@ -1586,7 +1562,8 @@ def checkConnection(suppressOutput=False):
try: try:
kb.originalPageTime = time.time() kb.originalPageTime = time.time()
Request.queryPage(content=True, noteResponseTime=False) page, headers, _ = Request.queryPage(content=True, noteResponseTime=False)
kb.originalPage = kb.pageTemplate = page
kb.errorIsNone = False kb.errorIsNone = False
@ -1609,8 +1586,10 @@ 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 conf.hostname in getUnicode(threadData.lastRedirectURL[1]): if (threadData.lastRedirectURL[1] or "").startswith("https://") and unicodeencode(conf.hostname) in 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
@ -1625,7 +1604,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 (_http_client.NOT_FOUND, )): if any(code in kb.httpErrorCodes for code in (httplib.NOT_FOUND, )):
errMsg = getSafeExString(ex) errMsg = getSafeExString(ex)
logger.critical(errMsg) logger.critical(errMsg)
@ -1639,9 +1618,6 @@ 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