mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-08 13:41:29 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85f25c90bb | ||
|
|
2ace4ef471 | ||
|
|
02dcf2a926 | ||
|
|
5c55602296 | ||
|
|
aa9cc3987e | ||
|
|
d7ee423fc5 | ||
|
|
1092dfb877 | ||
|
|
bf4f84b70a | ||
|
|
c45cf60fb4 | ||
|
|
3f53b2bc05 |
@@ -34,7 +34,7 @@
|
|||||||
<!-- Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx -->
|
<!-- Reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx -->
|
||||||
|
|
||||||
<regexp value="Windows.*\b10\.0">
|
<regexp value="Windows.*\b10\.0">
|
||||||
<info type="Windows" distrib="2016|2019|10|11"/>
|
<info type="Windows" distrib="2016|2019|2022|10|11"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="Windows.*\b6\.3">
|
<regexp value="Windows.*\b6\.3">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<!-- Microsoft IIS -->
|
<!-- Microsoft IIS -->
|
||||||
|
|
||||||
<regexp value="Microsoft-IIS/(10\.0)">
|
<regexp value="Microsoft-IIS/(10\.0)">
|
||||||
<info technology="Microsoft IIS" tech_version="1" type="Windows" distrib="2019|2016|10"/>
|
<info technology="Microsoft IIS" tech_version="1" type="Windows" distrib="2016|2019|2022|10|11"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="Microsoft-IIS/(8\.5)">
|
<regexp value="Microsoft-IIS/(8\.5)">
|
||||||
@@ -878,7 +878,11 @@
|
|||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<regexp value="Apache/2\.4\.46 \(Ubuntu\)">
|
<regexp value="Apache/2\.4\.46 \(Ubuntu\)">
|
||||||
<info type="Linux" distrib="Ubuntu" release="21.04|21.10" codename="eoan|focal"/>
|
<info type="Linux" distrib="Ubuntu" release="21.04|21.10" codename="hirsute|impish"/>
|
||||||
|
</regexp>
|
||||||
|
|
||||||
|
<regexp value="Apache/2\.4\.52 \(Ubuntu\)">
|
||||||
|
<info type="Linux" distrib="Ubuntu" release="22.04" codename="jammy"/>
|
||||||
</regexp>
|
</regexp>
|
||||||
|
|
||||||
<!-- Nginx -->
|
<!-- Nginx -->
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ class Agent(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
|
prefixRegex = r"(?:\s+(?:FIRST|SKIP|LIMIT(?: \d+)?)\s+\d+)*"
|
||||||
fieldsSelectTop = re.search(r"\ASELECT\s+TOP(\s+[\d]|\s*\([^)]+\))\s+(.+?)\s+FROM", query, re.I)
|
fieldsSelectTop = re.search(r"\ASELECT\s+TOP(\s+\d+|\s*\([^)]+\))\s+(.+?)\s+FROM", query, re.I)
|
||||||
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
|
fieldsSelectRownum = re.search(r"\ASELECT\s+([^()]+?),\s*ROWNUM AS LIMIT FROM", query, re.I)
|
||||||
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
|
fieldsSelectDistinct = re.search(r"\ASELECT%s\s+DISTINCT\((.+?)\)\s+FROM" % prefixRegex, query, re.I)
|
||||||
fieldsSelectCase = re.search(r"\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I)
|
fieldsSelectCase = re.search(r"\ASELECT%s\s+(\(CASE WHEN\s+.+\s+END\))" % prefixRegex, query, re.I)
|
||||||
@@ -729,7 +729,7 @@ class Agent(object):
|
|||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.chars.start, 1)
|
||||||
concatenatedQuery += "+'%s'" % kb.chars.stop
|
concatenatedQuery += "+'%s'" % kb.chars.stop
|
||||||
elif fieldsSelectTop:
|
elif fieldsSelectTop:
|
||||||
topNum = re.search(r"\ASELECT\s+TOP(\s+[\d]|\s*\([^)]+\))\s+", concatenatedQuery, re.I).group(1)
|
topNum = re.search(r"\ASELECT\s+TOP(\s+\d+|\s*\([^)]+\))\s+", concatenatedQuery, re.I).group(1)
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT TOP%s " % topNum, "TOP%s '%s'+" % (topNum, kb.chars.start), 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT TOP%s " % topNum, "TOP%s '%s'+" % (topNum, kb.chars.start), 1)
|
||||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1)
|
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.chars.stop, 1)
|
||||||
elif fieldsSelectCase:
|
elif fieldsSelectCase:
|
||||||
|
|||||||
@@ -4269,6 +4269,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
|
|||||||
retVal = "[%s]" % retVal
|
retVal = "[%s]" % retVal
|
||||||
|
|
||||||
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
|
if _ and DEFAULT_MSSQL_SCHEMA not in retVal and '.' not in re.sub(r"\[[^]]+\]", "", retVal):
|
||||||
|
if (conf.db or "").lower() != "information_schema": # NOTE: https://github.com/sqlmapproject/sqlmap/issues/5192
|
||||||
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
|
retVal = "%s.%s" % (DEFAULT_MSSQL_SCHEMA, retVal)
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ else:
|
|||||||
buffer = buffer
|
buffer = buffer
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from pkg_resources import parse_version as LooseVersion
|
from packaging import version
|
||||||
|
LooseVersion = version.parse
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|||||||
@@ -2166,7 +2166,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||||||
kb.testType = None
|
kb.testType = None
|
||||||
kb.threadContinue = True
|
kb.threadContinue = True
|
||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
kb.tlsSNI = {}
|
|
||||||
kb.uChar = NULL
|
kb.uChar = NULL
|
||||||
kb.udfFail = False
|
kb.udfFail = False
|
||||||
kb.unionDuplicates = False
|
kb.unionDuplicates = False
|
||||||
@@ -2675,7 +2674,7 @@ def _basicOptionValidation():
|
|||||||
logger.warning(warnMsg)
|
logger.warning(warnMsg)
|
||||||
|
|
||||||
|
|
||||||
if conf.cookieDel and len(conf.cookieDel):
|
if conf.cookieDel and len(conf.cookieDel) != 1:
|
||||||
errMsg = "option '--cookie-del' should contain a single character (e.g. ';')"
|
errMsg = "option '--cookie-del' should contain a single character (e.g. ';')"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
@@ -2733,6 +2732,10 @@ def _basicOptionValidation():
|
|||||||
errMsg = "option '--csrf-method' requires usage of option '--csrf-token'"
|
errMsg = "option '--csrf-method' requires usage of option '--csrf-token'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
|
if conf.csrfData and not conf.csrfToken:
|
||||||
|
errMsg = "option '--csrf-data' requires usage of option '--csrf-token'"
|
||||||
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|
||||||
if conf.csrfToken and conf.threads > 1:
|
if conf.csrfToken and conf.threads > 1:
|
||||||
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
|
errMsg = "option '--csrf-url' is incompatible with option '--threads'"
|
||||||
raise SqlmapSyntaxException(errMsg)
|
raise SqlmapSyntaxException(errMsg)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ optDict = {
|
|||||||
"csrfToken": "string",
|
"csrfToken": "string",
|
||||||
"csrfUrl": "string",
|
"csrfUrl": "string",
|
||||||
"csrfMethod": "string",
|
"csrfMethod": "string",
|
||||||
|
"csrfData": "string",
|
||||||
"csrfRetries": "integer",
|
"csrfRetries": "integer",
|
||||||
"forceSSL": "boolean",
|
"forceSSL": "boolean",
|
||||||
"chunked": "boolean",
|
"chunked": "boolean",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from thirdparty import six
|
|||||||
from thirdparty.six import unichr as _unichr
|
from thirdparty.six import unichr as _unichr
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.6.10.0"
|
VERSION = "1.6.11.0"
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
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)
|
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
|
||||||
|
|||||||
@@ -276,6 +276,9 @@ def cmdLineParser(argv=None):
|
|||||||
request.add_argument("--csrf-method", dest="csrfMethod",
|
request.add_argument("--csrf-method", dest="csrfMethod",
|
||||||
help="HTTP method to use during anti-CSRF token page visit")
|
help="HTTP method to use during anti-CSRF token page visit")
|
||||||
|
|
||||||
|
request.add_argument("--csrf-data", dest="csrfData",
|
||||||
|
help="POST data to send during anti-CSRF token page visit")
|
||||||
|
|
||||||
request.add_argument("--csrf-retries", dest="csrfRetries", type=int,
|
request.add_argument("--csrf-retries", dest="csrfRetries", type=int,
|
||||||
help="Retries for anti-CSRF token retrieval (default %d)" % defaults.csrfRetries)
|
help="Retries for anti-CSRF token retrieval (default %d)" % defaults.csrfRetries)
|
||||||
|
|
||||||
@@ -986,7 +989,7 @@ def cmdLineParser(argv=None):
|
|||||||
argv[i] = argv[i].replace("--auth-creds", "--auth-cred", 1)
|
argv[i] = argv[i].replace("--auth-creds", "--auth-cred", 1)
|
||||||
elif argv[i].startswith("--drop-cookie"):
|
elif argv[i].startswith("--drop-cookie"):
|
||||||
argv[i] = argv[i].replace("--drop-cookie", "--drop-set-cookie", 1)
|
argv[i] = argv[i].replace("--drop-cookie", "--drop-set-cookie", 1)
|
||||||
elif any(argv[i].startswith(_) for _ in ("--tamper", "--ignore-code", "--skip")):
|
elif re.search(r"\A(--(tamper|ignore-code|skip))(?!-)", argv[i]):
|
||||||
key = re.search(r"\-?\-(\w+)\b", argv[i]).group(1)
|
key = re.search(r"\-?\-(\w+)\b", argv[i]).group(1)
|
||||||
index = auxIndexes.get(key, None)
|
index = auxIndexes.get(key, None)
|
||||||
if index is None:
|
if index is None:
|
||||||
|
|||||||
@@ -1186,7 +1186,7 @@ class Connect(object):
|
|||||||
warnMsg += ". sqlmap is going to retry the request"
|
warnMsg += ". sqlmap is going to retry the request"
|
||||||
logger.warning(warnMsg)
|
logger.warning(warnMsg)
|
||||||
|
|
||||||
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.data if conf.csrfUrl == conf.url else None, method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
page, headers, code = Connect.getPage(url=conf.csrfUrl or conf.url, data=conf.csrfData or (conf.data if conf.csrfUrl == conf.url else None), method=conf.csrfMethod or (conf.method if conf.csrfUrl == conf.url else None), cookie=conf.parameters.get(PLACE.COOKIE), direct=True, silent=True, ua=conf.parameters.get(PLACE.USER_AGENT), referer=conf.parameters.get(PLACE.REFERER), host=conf.parameters.get(PLACE.HOST))
|
||||||
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
page = urldecode(page) # for anti-CSRF tokens with special characters in their name (e.g. 'foo:bar=...')
|
||||||
|
|
||||||
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
match = re.search(r"(?i)<input[^>]+\bname=[\"']?(?P<name>%s)\b[^>]*\bvalue=[\"']?(?P<value>[^>'\"]*)" % conf.csrfToken, page or "", re.I)
|
||||||
|
|||||||
@@ -63,19 +63,21 @@ class HTTPSConnection(_http_client.HTTPSConnection):
|
|||||||
|
|
||||||
# Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext
|
# Reference(s): https://docs.python.org/2/library/ssl.html#ssl.SSLContext
|
||||||
# https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni
|
# https://www.mnot.net/blog/2014/12/27/python_2_and_tls_sni
|
||||||
if re.search(r"\A[\d.]+\Z", self.host or "") is None and kb.tlsSNI.get(self.host) is not False and hasattr(ssl, "SSLContext"):
|
if hasattr(ssl, "SSLContext"):
|
||||||
for protocol in (_ for _ in _protocols if _ >= ssl.PROTOCOL_TLSv1):
|
for protocol in (_ for _ in _protocols if _ >= ssl.PROTOCOL_TLSv1):
|
||||||
try:
|
try:
|
||||||
sock = create_sock()
|
sock = create_sock()
|
||||||
if protocol not in _contexts:
|
if protocol not in _contexts:
|
||||||
_contexts[protocol] = ssl.SSLContext(protocol)
|
_contexts[protocol] = ssl.SSLContext(protocol)
|
||||||
|
if self.cert_file and self.key_file:
|
||||||
|
_contexts[protocol].load_cert_chain(certfile=self.cert_file, keyfile=self.key_file)
|
||||||
try:
|
try:
|
||||||
# Reference(s): https://askubuntu.com/a/1263098
|
# Reference(s): https://askubuntu.com/a/1263098
|
||||||
# https://askubuntu.com/a/1250807
|
# https://askubuntu.com/a/1250807
|
||||||
_contexts[protocol].set_ciphers("DEFAULT@SECLEVEL=1")
|
_contexts[protocol].set_ciphers("DEFAULT@SECLEVEL=1")
|
||||||
except ssl.SSLError:
|
except ssl.SSLError:
|
||||||
pass
|
pass
|
||||||
result = _contexts[protocol].wrap_socket(sock, do_handshake_on_connect=True, server_hostname=self.host)
|
result = _contexts[protocol].wrap_socket(sock, do_handshake_on_connect=True, server_hostname=self.host if re.search(r"\A[\d.]+\Z", self.host or "") is None else None)
|
||||||
if result:
|
if result:
|
||||||
success = True
|
success = True
|
||||||
self.sock = result
|
self.sock = result
|
||||||
@@ -88,14 +90,11 @@ class HTTPSConnection(_http_client.HTTPSConnection):
|
|||||||
self._tunnel_host = None
|
self._tunnel_host = None
|
||||||
logger.debug("SSL connection error occurred for '%s' ('%s')" % (_lut[protocol], getSafeExString(ex)))
|
logger.debug("SSL connection error occurred for '%s' ('%s')" % (_lut[protocol], getSafeExString(ex)))
|
||||||
|
|
||||||
if kb.tlsSNI.get(self.host) is None:
|
elif hasattr(ssl, "wrap_socket"):
|
||||||
kb.tlsSNI[self.host] = success
|
|
||||||
|
|
||||||
if not success:
|
|
||||||
for protocol in _protocols:
|
for protocol in _protocols:
|
||||||
try:
|
try:
|
||||||
sock = create_sock()
|
sock = create_sock()
|
||||||
_ = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=protocol)
|
_ = ssl.wrap_socket(sock, keyfile=self.key_file, certfile=self.cert_file, ssl_version=protocol)
|
||||||
if _:
|
if _:
|
||||||
success = True
|
success = True
|
||||||
self.sock = _
|
self.sock = _
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ class Fingerprint(GenericFingerprint):
|
|||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
for version, check in (
|
for version, check in (
|
||||||
|
("2022", "CHARINDEX('16.0.',@@VERSION)>0"),
|
||||||
("2019", "CHARINDEX('15.0.',@@VERSION)>0"),
|
("2019", "CHARINDEX('15.0.',@@VERSION)>0"),
|
||||||
("Azure", "@@VERSION LIKE '%Azure%'"),
|
("Azure", "@@VERSION LIKE '%Azure%'"),
|
||||||
("2017", "TRIM(NULL) IS NULL"),
|
("2017", "TRIM(NULL) IS NULL"),
|
||||||
@@ -151,7 +152,7 @@ class Fingerprint(GenericFingerprint):
|
|||||||
"7 or 2008 R2": ("6.1", (1, 0)),
|
"7 or 2008 R2": ("6.1", (1, 0)),
|
||||||
"8 or 2012": ("6.2", (0,)),
|
"8 or 2012": ("6.2", (0,)),
|
||||||
"8.1 or 2012 R2": ("6.3", (0,)),
|
"8.1 or 2012 R2": ("6.3", (0,)),
|
||||||
"10 or 2016 or 2019": ("10.0", (0,))
|
"10 or 11 or 2016 or 2019 or 2022": ("10.0", (0,))
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get back-end DBMS underlying operating system version
|
# Get back-end DBMS underlying operating system version
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ class Fingerprint(GenericFingerprint):
|
|||||||
versions = (
|
versions = (
|
||||||
(80000, 80029), # MySQL 8.0
|
(80000, 80029), # MySQL 8.0
|
||||||
(60000, 60014), # MySQL 6.0
|
(60000, 60014), # MySQL 6.0
|
||||||
(50700, 50737), # MySQL 5.7
|
(50700, 50739), # MySQL 5.7
|
||||||
(50600, 50652), # MySQL 5.6
|
(50600, 50652), # MySQL 5.6
|
||||||
(50500, 50563), # MySQL 5.5
|
(50500, 50563), # MySQL 5.5
|
||||||
(50400, 50404), # MySQL 5.4
|
(50400, 50404), # MySQL 5.4
|
||||||
(50100, 50174), # MySQL 5.1
|
(50100, 50175), # MySQL 5.1
|
||||||
(50000, 50097), # MySQL 5.0
|
(50000, 50097), # MySQL 5.0
|
||||||
(40100, 40131), # MySQL 4.1
|
(40100, 40131), # MySQL 4.1
|
||||||
(40000, 40032), # MySQL 4.0
|
(40000, 40032), # MySQL 4.0
|
||||||
|
|||||||
@@ -131,7 +131,9 @@ class Fingerprint(GenericFingerprint):
|
|||||||
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
|
infoMsg = "actively fingerprinting %s" % DBMS.PGSQL
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
if inject.checkBooleanExpression("GEN_RANDOM_UUID() IS NOT NULL"):
|
if inject.checkBooleanExpression("BIT_COUNT(NULL) IS NULL"):
|
||||||
|
Backend.setVersion(">= 14.0")
|
||||||
|
elif inject.checkBooleanExpression("GEN_RANDOM_UUID() IS NOT NULL"):
|
||||||
Backend.setVersion(">= 13.0")
|
Backend.setVersion(">= 13.0")
|
||||||
elif inject.checkBooleanExpression("SINH(0)=0"):
|
elif inject.checkBooleanExpression("SINH(0)=0"):
|
||||||
Backend.setVersion(">= 12.0")
|
Backend.setVersion(">= 12.0")
|
||||||
|
|||||||
@@ -195,6 +195,9 @@ csrfUrl =
|
|||||||
# HTTP method to use during anti-CSRF token page visit.
|
# HTTP method to use during anti-CSRF token page visit.
|
||||||
csrfMethod =
|
csrfMethod =
|
||||||
|
|
||||||
|
# POST data to send during anti-CSRF token page visit.
|
||||||
|
csrfData =
|
||||||
|
|
||||||
# Retries for anti-CSRF token retrieval.
|
# Retries for anti-CSRF token retrieval.
|
||||||
csrfRetries =
|
csrfRetries =
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ def tamper(payload, **kwargs):
|
|||||||
|
|
||||||
>>> tamper("1' AND SLEEP(5)#")
|
>>> tamper("1' AND SLEEP(5)#")
|
||||||
'1' AND SLEEP(5)#'
|
'1' AND SLEEP(5)#'
|
||||||
|
>>> tamper("1' AND SLEEP(5)#")
|
||||||
|
'1' AND SLEEP(5)#'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return re.sub(r"[^\w]", lambda match: "&#%d;" % ord(match.group(0)), payload) if payload else payload
|
if payload:
|
||||||
|
payload = re.sub(r"&#(\d+);", lambda match: chr(int(match.group(1))), payload) # NOTE: https://github.com/sqlmapproject/sqlmap/issues/5203
|
||||||
|
payload = re.sub(r"[^\w]", lambda match: "&#%d;" % ord(match.group(0)), payload)
|
||||||
|
|
||||||
|
return payload
|
||||||
|
|||||||
35
tamper/scientific.py
Normal file
35
tamper/scientific.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
|
||||||
|
See the file 'LICENSE' for copying permission
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from lib.core.enums import PRIORITY
|
||||||
|
|
||||||
|
__priority__ = PRIORITY.HIGHEST
|
||||||
|
|
||||||
|
def dependencies():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tamper(payload, **kwargs):
|
||||||
|
"""
|
||||||
|
Abuses MySQL scientific notation
|
||||||
|
|
||||||
|
Requirement:
|
||||||
|
* MySQL
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
* Reference: https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/
|
||||||
|
|
||||||
|
>>> tamper('1 AND ORD(MID((CURRENT_USER()),7,1))>1')
|
||||||
|
'1 AND ORD 1.e(MID((CURRENT_USER 1.e( 1.e) 1.e) 1.e,7 1.e,1 1.e) 1.e)>1'
|
||||||
|
"""
|
||||||
|
|
||||||
|
if payload:
|
||||||
|
payload = re.sub(r"[),.*^/|&]", r" 1.e\g<0>", payload)
|
||||||
|
payload = re.sub(r"(\w+)\(", lambda match: "%s 1.e(" % match.group(1) if not re.search(r"(?i)\A(MID|CAST|FROM|COUNT)\Z", match.group(1)) else match.group(0), payload) # NOTE: MID and CAST don't work for sure
|
||||||
|
|
||||||
|
return payload
|
||||||
Reference in New Issue
Block a user