mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-06 12:41:30 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4585243175 | ||
|
|
fbfed061b8 | ||
|
|
fdbc323aa6 | ||
|
|
6336389322 | ||
|
|
a7b59243e2 | ||
|
|
c8eea24ac4 | ||
|
|
1be7a5aea8 | ||
|
|
d0d4cf4f6d | ||
|
|
1f83076e70 | ||
|
|
b0a1efaa44 | ||
|
|
de527f1814 | ||
|
|
96adc7c098 | ||
|
|
7940b572ef |
@@ -489,7 +489,7 @@ class Agent(object):
|
||||
if field and Backend.getIdentifiedDbms():
|
||||
rootQuery = queries[Backend.getIdentifiedDbms()]
|
||||
|
||||
if field.startswith("(CASE") or field.startswith("(IIF") or conf.noCast:
|
||||
if field.startswith("(CASE") or field.startswith("(IIF") or conf.noCast and not (field.startswith("COUNT(") and getTechnique() in (PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.UNION) and Backend.getIdentifiedDbms() == DBMS.MSSQL):
|
||||
nulledCastedField = field
|
||||
else:
|
||||
if not (Backend.isDbms(DBMS.SQLITE) and not isDBMSVersionAtLeast('3')):
|
||||
@@ -596,6 +596,9 @@ class Agent(object):
|
||||
if not _:
|
||||
fieldsSelectFrom = None
|
||||
|
||||
if re.search(r"\bWHERE\b.+(MIN|MAX)", query, re.I):
|
||||
fieldsMinMaxstr = None
|
||||
|
||||
fieldsToCastStr = fieldsNoSelect
|
||||
|
||||
if fieldsSubstr:
|
||||
|
||||
@@ -1696,11 +1696,20 @@ def _cleanupOptions():
|
||||
try:
|
||||
conf.ignoreCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.ignoreCode)]
|
||||
except ValueError:
|
||||
errMsg = "options '--ignore-code' should contain a list of integer values or a wildcard value '%s'" % IGNORE_CODE_WILDCARD
|
||||
errMsg = "option '--ignore-code' should contain a list of integer values or a wildcard value '%s'" % IGNORE_CODE_WILDCARD
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
else:
|
||||
conf.ignoreCode = []
|
||||
|
||||
if conf.abortCode:
|
||||
try:
|
||||
conf.abortCode = [int(_) for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.abortCode)]
|
||||
except ValueError:
|
||||
errMsg = "option '--abort-code' should contain a list of integer values"
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
else:
|
||||
conf.abortCode = []
|
||||
|
||||
if conf.paramFilter:
|
||||
conf.paramFilter = [_.strip() for _ in re.split(PARAMETER_SPLITTING_REGEX, conf.paramFilter.upper())]
|
||||
else:
|
||||
@@ -2655,6 +2664,9 @@ def _basicOptionValidation():
|
||||
raise SqlmapSyntaxException(errMsg)
|
||||
|
||||
if conf.paramExclude:
|
||||
if re.search(r"\A\w+,", conf.paramExclude):
|
||||
conf.paramExclude = r"\A(%s)\Z" % ('|'.join(re.escape(_).strip() for _ in conf.paramExclude.split(',')))
|
||||
|
||||
try:
|
||||
re.compile(conf.paramExclude)
|
||||
except Exception as ex:
|
||||
|
||||
@@ -39,6 +39,7 @@ optDict = {
|
||||
"authType": "string",
|
||||
"authCred": "string",
|
||||
"authFile": "string",
|
||||
"abortCode": "string",
|
||||
"ignoreCode": "string",
|
||||
"ignoreProxy": "boolean",
|
||||
"ignoreRedirects": "boolean",
|
||||
@@ -204,6 +205,7 @@ optDict = {
|
||||
|
||||
"General": {
|
||||
"trafficFile": "string",
|
||||
"abortOnEmpty": "boolean",
|
||||
"answers": "string",
|
||||
"batch": "boolean",
|
||||
"base64Parameter": "string",
|
||||
|
||||
@@ -20,7 +20,7 @@ from thirdparty import six
|
||||
from thirdparty.six import unichr as _unichr
|
||||
|
||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||
VERSION = "1.7"
|
||||
VERSION = "1.7.2.0"
|
||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||
|
||||
@@ -201,8 +201,11 @@ def cmdLineParser(argv=None):
|
||||
request.add_argument("--auth-file", dest="authFile",
|
||||
help="HTTP authentication PEM cert/private key file")
|
||||
|
||||
request.add_argument("--abort-code", dest="abortCode",
|
||||
help="Abort on (problematic) HTTP error code(s) (e.g. 401)")
|
||||
|
||||
request.add_argument("--ignore-code", dest="ignoreCode",
|
||||
help="Ignore (problematic) HTTP error code (e.g. 401)")
|
||||
help="Ignore (problematic) HTTP error code(s) (e.g. 401)")
|
||||
|
||||
request.add_argument("--ignore-proxy", dest="ignoreProxy", action="store_true",
|
||||
help="Ignore system default proxy settings")
|
||||
@@ -628,6 +631,9 @@ def cmdLineParser(argv=None):
|
||||
general.add_argument("-t", dest="trafficFile",
|
||||
help="Log all HTTP traffic into a textual file")
|
||||
|
||||
general.add_argument("--abort-on-empty", dest="abortOnEmpty", action="store_true",
|
||||
help="Abort data retrieval on empty results")
|
||||
|
||||
general.add_argument("--answers", dest="answers",
|
||||
help="Set predefined answers (e.g. \"quit=N,follow=N\")")
|
||||
|
||||
|
||||
@@ -767,6 +767,11 @@ class Connect(object):
|
||||
if not multipart:
|
||||
logger.log(CUSTOM_LOGGING.TRAFFIC_IN, responseMsg)
|
||||
|
||||
if code in conf.abortCode:
|
||||
errMsg = "aborting due to detected HTTP code '%d'" % code
|
||||
singleTimeLogMessage(errMsg, logging.CRITICAL)
|
||||
raise SystemExit
|
||||
|
||||
if ex.code not in (conf.ignoreCode or []):
|
||||
if ex.code == _http_client.UNAUTHORIZED:
|
||||
errMsg = "not authorized, try to provide right HTTP "
|
||||
@@ -921,6 +926,12 @@ class Connect(object):
|
||||
errMsg += "function '%s' ('%s')" % (function.__name__, getSafeExString(ex))
|
||||
raise SqlmapGenericException(errMsg)
|
||||
|
||||
for _ in (getattr(conn, "redcode", None), code):
|
||||
if _ is not None and _ in conf.abortCode:
|
||||
errMsg = "aborting due to detected HTTP code '%d'" % _
|
||||
singleTimeLogMessage(errMsg, logging.CRITICAL)
|
||||
raise SystemExit
|
||||
|
||||
threadData.lastPage = page
|
||||
threadData.lastCode = code
|
||||
|
||||
|
||||
@@ -501,10 +501,15 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
||||
kb.safeCharEncode = False
|
||||
|
||||
if not any((kb.testMode, conf.dummy, conf.offline, conf.noCast, conf.hexConvert)) and value is None and Backend.getDbms() and conf.dbmsHandler and kb.fingerprinted:
|
||||
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
||||
warnMsg += "a switch '--no-cast' "
|
||||
warnMsg += "or switch '--hex'" if hasattr(queries[Backend.getIdentifiedDbms()], "hex") else ""
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
if conf.abortOnEmpty:
|
||||
errMsg = "aborting due to empty data retrieval"
|
||||
logger.critical(errMsg)
|
||||
raise SystemExit
|
||||
else:
|
||||
warnMsg = "in case of continuous data retrieval problems you are advised to try "
|
||||
warnMsg += "a switch '--no-cast' "
|
||||
warnMsg += "or switch '--hex'" if hasattr(queries[Backend.getIdentifiedDbms()], "hex") else ""
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
# Dirty patch (MSSQL --binary-fields with 0x31003200...)
|
||||
if Backend.isDbms(DBMS.MSSQL) and conf.binaryFields:
|
||||
|
||||
@@ -21,7 +21,7 @@ try:
|
||||
if hasattr(module, "dialects"):
|
||||
_sqlalchemy = module
|
||||
warnings.simplefilter(action="ignore", category=_sqlalchemy.exc.SAWarning)
|
||||
except ImportError:
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
sys.path = _path
|
||||
@@ -39,6 +39,7 @@ from lib.core.exception import SqlmapFilePathException
|
||||
from lib.core.exception import SqlmapMissingDependence
|
||||
from plugins.generic.connector import Connector as GenericConnector
|
||||
from thirdparty import six
|
||||
from thirdparty.six.moves import urllib as _urllib
|
||||
|
||||
def getSafeExString(ex, encoding=None): # Cross-referenced function
|
||||
raise NotImplementedError
|
||||
@@ -50,6 +51,14 @@ class SQLAlchemy(GenericConnector):
|
||||
self.dialect = dialect
|
||||
self.address = conf.direct
|
||||
|
||||
if conf.dbmsUser:
|
||||
self.address = self.address.replace("'%s':" % conf.dbmsUser, "%s:" % _urllib.parse.quote(conf.dbmsUser))
|
||||
self.address = self.address.replace("%s:" % conf.dbmsUser, "%s:" % _urllib.parse.quote(conf.dbmsUser))
|
||||
|
||||
if conf.dbmsPass:
|
||||
self.address = self.address.replace(":'%s'@" % conf.dbmsPass, ":%s@" % _urllib.parse.quote(conf.dbmsPass))
|
||||
self.address = self.address.replace(":%s@" % conf.dbmsPass, ":%s@" % _urllib.parse.quote(conf.dbmsPass))
|
||||
|
||||
if self.dialect:
|
||||
self.address = re.sub(r"\A.+://", "%s://" % self.dialect, self.address)
|
||||
|
||||
|
||||
@@ -101,8 +101,12 @@ authCred =
|
||||
# Syntax: key_file
|
||||
authFile =
|
||||
|
||||
# Abort on (problematic) HTTP error code (e.g. 401).
|
||||
# Valid: string
|
||||
abortCode =
|
||||
|
||||
# Ignore (problematic) HTTP error code (e.g. 401).
|
||||
# Valid: integer
|
||||
# Valid: string
|
||||
ignoreCode =
|
||||
|
||||
# Ignore system default proxy settings.
|
||||
@@ -702,6 +706,9 @@ sessionFile =
|
||||
# Log all HTTP traffic into a textual file.
|
||||
trafficFile =
|
||||
|
||||
# Abort data retrieval on empty results.
|
||||
abortOnEmpty = False
|
||||
|
||||
# Set predefined answers (e.g. "quit=N,follow=N").
|
||||
answers =
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ try:
|
||||
from lib.core.common import setPaths
|
||||
from lib.core.common import weAreFrozen
|
||||
from lib.core.convert import getUnicode
|
||||
from lib.core.common import MKSTEMP_PREFIX
|
||||
from lib.core.common import setColor
|
||||
from lib.core.common import unhandledExceptionMessage
|
||||
from lib.core.compat import LooseVersion
|
||||
@@ -73,6 +72,7 @@ try:
|
||||
from lib.core.data import conf
|
||||
from lib.core.data import kb
|
||||
from lib.core.datatype import OrderedSet
|
||||
from lib.core.enums import MKSTEMP_PREFIX
|
||||
from lib.core.exception import SqlmapBaseException
|
||||
from lib.core.exception import SqlmapShellQuitException
|
||||
from lib.core.exception import SqlmapSilentQuitException
|
||||
|
||||
67
tamper/if2case.py
Normal file
67
tamper/if2case.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2006-2023 sqlmap developers (https://sqlmap.org/)
|
||||
See the file 'doc/COPYING' for copying permission
|
||||
"""
|
||||
|
||||
from lib.core.compat import xrange
|
||||
from lib.core.enums import PRIORITY
|
||||
|
||||
__priority__ = PRIORITY.HIGHEST
|
||||
|
||||
def dependencies():
|
||||
pass
|
||||
|
||||
def tamper(payload, **kwargs):
|
||||
"""
|
||||
Replaces instances like 'IF(A, B, C)' with 'CASE WHEN (A) THEN (B) ELSE (C) END' counterpart
|
||||
|
||||
Requirement:
|
||||
* MySQL
|
||||
* SQLite (possibly)
|
||||
* SAP MaxDB (possibly)
|
||||
|
||||
Tested against:
|
||||
* MySQL 5.0 and 5.5
|
||||
|
||||
Notes:
|
||||
* Useful to bypass very weak and bespoke web application firewalls
|
||||
that filter the IF() functions
|
||||
|
||||
>>> tamper('IF(1, 2, 3)')
|
||||
'CASE WHEN (1) THEN (2) ELSE (3) END'
|
||||
>>> tamper('SELECT IF((1=1), (SELECT "foo"), NULL)')
|
||||
'SELECT CASE WHEN (1=1) THEN (SELECT "foo") ELSE (NULL) END'
|
||||
"""
|
||||
|
||||
if payload and payload.find("IF") > -1:
|
||||
while payload.find("IF(") > -1:
|
||||
index = payload.find("IF(")
|
||||
depth = 1
|
||||
commas, end = [], None
|
||||
|
||||
for i in xrange(index + len("IF("), len(payload)):
|
||||
if depth == 1 and payload[i] == ',':
|
||||
commas.append(i)
|
||||
|
||||
elif depth == 1 and payload[i] == ')':
|
||||
end = i
|
||||
break
|
||||
|
||||
elif payload[i] == '(':
|
||||
depth += 1
|
||||
|
||||
elif payload[i] == ')':
|
||||
depth -= 1
|
||||
|
||||
if len(commas) == 2 and end:
|
||||
a = payload[index + len("IF("):commas[0]].strip("()")
|
||||
b = payload[commas[0] + 1:commas[1]].lstrip().strip("()")
|
||||
c = payload[commas[1] + 1:end].lstrip().strip("()")
|
||||
newVal = "CASE WHEN (%s) THEN (%s) ELSE (%s) END" % (a, b, c)
|
||||
payload = payload[:index] + newVal + payload[end + 1:]
|
||||
else:
|
||||
break
|
||||
|
||||
return payload
|
||||
Reference in New Issue
Block a user