Compare commits

...

6 Commits
1.5.6 ... 1.5.7

Author SHA1 Message Date
Miroslav Stampar
69c679cf06 Fixes #4728 2021-07-04 23:07:55 +02:00
Miroslav Stampar
5ea08b397a Fixes #4710 2021-06-24 21:03:22 +02:00
Miroslav Stampar
7c41967865 Fixes #4719 2021-06-21 17:17:41 +02:00
Miroslav Stampar
255dce8c49 Fixes #4712 2021-06-15 21:04:51 +02:00
Miroslav Stampar
7c7c338705 Fixes #4705 2021-06-11 09:48:00 +02:00
Miroslav Stampar
63073a1873 15% speedup in some cases (avoiding heuristic char detection) 2021-06-08 21:48:43 +02:00
8 changed files with 22 additions and 13 deletions

View File

@@ -26,6 +26,7 @@ from lib.core.common import openFile
from lib.core.common import prioritySortColumns from lib.core.common import prioritySortColumns
from lib.core.common import randomInt from lib.core.common import randomInt
from lib.core.common import safeCSValue from lib.core.common import safeCSValue
from lib.core.common import unArrayizeValue
from lib.core.common import unsafeSQLIdentificatorNaming from lib.core.common import unsafeSQLIdentificatorNaming
from lib.core.compat import xrange from lib.core.compat import xrange
from lib.core.convert import getBytes from lib.core.convert import getBytes
@@ -116,6 +117,9 @@ class Dump(object):
if conf.api: if conf.api:
self._write(data, content_type=content_type) self._write(data, content_type=content_type)
if isListLike(data) and len(data) == 1:
data = unArrayizeValue(data)
if isListLike(data): if isListLike(data):
self.lister(header, data, content_type, sort) self.lister(header, data, content_type, sort)
elif data is not None: elif data is not None:

View File

@@ -29,7 +29,7 @@ class Replication(object):
self.cursor = self.connection.cursor() self.cursor = self.connection.cursor()
except sqlite3.OperationalError as ex: except sqlite3.OperationalError as ex:
errMsg = "error occurred while opening a replication " errMsg = "error occurred while opening a replication "
errMsg += "file '%s' ('%s')" % (self.filepath, getSafeExString(ex)) errMsg += "file '%s' ('%s')" % (dbpath, getSafeExString(ex))
raise SqlmapConnectionException(errMsg) raise SqlmapConnectionException(errMsg)
class DataType(object): class DataType(object):

View File

@@ -16,10 +16,11 @@ import time
from lib.core.enums import DBMS from lib.core.enums import DBMS
from lib.core.enums import DBMS_DIRECTORY_NAME from lib.core.enums import DBMS_DIRECTORY_NAME
from lib.core.enums import OS from lib.core.enums import OS
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.5.6.0" VERSION = "1.5.7.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)
@@ -906,6 +907,9 @@ KB_CHARS_BOUNDARY_CHAR = 'q'
# Letters of lower frequency used in kb.chars # Letters of lower frequency used in kb.chars
KB_CHARS_LOW_FREQUENCY_ALPHABET = "zqxjkvbp" KB_CHARS_LOW_FREQUENCY_ALPHABET = "zqxjkvbp"
# Printable bytes
PRINTABLE_BYTES = set(bytes(string.printable, "ascii") if six.PY3 else string.printable)
# SQL keywords used for splitting in HTTP chunked transfer encoded requests (switch --chunk) # SQL keywords used for splitting in HTTP chunked transfer encoded requests (switch --chunk)
HTTP_CHUNKED_SPLIT_KEYWORDS = ("SELECT", "UPDATE", "INSERT", "FROM", "LOAD_FILE", "UNION", "information_schema", "sysdatabases", "msysaccessobjects", "msysqueries", "sysmodules") HTTP_CHUNKED_SPLIT_KEYWORDS = ("SELECT", "UPDATE", "INSERT", "FROM", "LOAD_FILE", "UNION", "information_schema", "sysdatabases", "msysaccessobjects", "msysqueries", "sysmodules")

View File

@@ -48,6 +48,7 @@ from lib.core.settings import IDENTYWAF_PARSE_LIMIT
from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE from lib.core.settings import MAX_CONNECTION_TOTAL_SIZE
from lib.core.settings import META_CHARSET_REGEX from lib.core.settings import META_CHARSET_REGEX
from lib.core.settings import PARSE_HEADERS_LIMIT from lib.core.settings import PARSE_HEADERS_LIMIT
from lib.core.settings import PRINTABLE_BYTES
from lib.core.settings import SELECT_FROM_TABLE_REGEX from lib.core.settings import SELECT_FROM_TABLE_REGEX
from lib.core.settings import UNICODE_ENCODING from lib.core.settings import UNICODE_ENCODING
from lib.core.settings import VIEWSTATE_REGEX from lib.core.settings import VIEWSTATE_REGEX
@@ -324,7 +325,7 @@ def decodePage(page, contentEncoding, contentType, percentDecode=True):
metaCharset = checkCharEncoding(extractRegexResult(META_CHARSET_REGEX, page)) metaCharset = checkCharEncoding(extractRegexResult(META_CHARSET_REGEX, page))
if (any((httpCharset, metaCharset)) and not all((httpCharset, metaCharset))) or (httpCharset == metaCharset and all((httpCharset, metaCharset))): if (any((httpCharset, metaCharset)) and (not all((httpCharset, metaCharset)) or isinstance(page, six.binary_type) and all(_ in PRINTABLE_BYTES for _ in page))) or (httpCharset == metaCharset and all((httpCharset, metaCharset))):
kb.pageEncoding = httpCharset or metaCharset # Reference: http://bytes.com/topic/html-css/answers/154758-http-equiv-vs-true-header-has-precedence kb.pageEncoding = httpCharset or metaCharset # Reference: http://bytes.com/topic/html-css/answers/154758-http-equiv-vs-true-header-has-precedence
debugMsg = "declared web page charset '%s'" % kb.pageEncoding debugMsg = "declared web page charset '%s'" % kb.pageEncoding
singleTimeLogMessage(debugMsg, logging.DEBUG, debugMsg) singleTimeLogMessage(debugMsg, logging.DEBUG, debugMsg)

View File

@@ -626,7 +626,7 @@ class Connect(object):
if conn: if conn:
code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes) code = (code or conn.code) if conn.code == kb.originalCode else conn.code # do not override redirection code (for comparison purposes)
responseHeaders = conn.info() responseHeaders = conn.info()
responseHeaders[URI_HTTP_HEADER] = conn.geturl() responseHeaders[URI_HTTP_HEADER] = conn.geturl() if hasattr(conn, "geturl") else url
if hasattr(conn, "redurl"): if hasattr(conn, "redurl"):
responseHeaders[HTTP_HEADER.LOCATION] = conn.redurl responseHeaders[HTTP_HEADER.LOCATION] = conn.redurl

View File

@@ -165,7 +165,7 @@ class Response(object):
try: try:
content = response.read() content = response.read()
except _http_client.IncompleteRead: except _http_client.IncompleteRead:
content = raw[raw.find("\r\n\r\n") + 4:].rstrip("\r\n") content = raw[raw.find(b"\r\n\r\n") + 4:].rstrip(b"\r\n")
return cls(httpVersion="HTTP/1.1" if response.version == 11 else "HTTP/1.0", return cls(httpVersion="HTTP/1.1" if response.version == 11 else "HTTP/1.0",
status=response.status, status=response.status,

View File

@@ -618,7 +618,7 @@ class Databases(object):
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db)) query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db))
query += condQuery query += condQuery
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = re.sub("column_type", "data_type", query, flags=re.I) query = re.sub("column_type", "data_type", query, flags=re.I)
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL): elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL):
@@ -1022,7 +1022,7 @@ class Databases(object):
rootQuery = queries[Backend.getIdentifiedDbms()].statements rootQuery = queries[Backend.getIdentifiedDbms()].statements
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = rootQuery.inband.query2 query = rootQuery.inband.query2
else: else:
query = rootQuery.inband.query query = rootQuery.inband.query
@@ -1049,7 +1049,7 @@ class Databases(object):
query = rootQuery.blind.count query = rootQuery.blind.count
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I) query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
@@ -1077,7 +1077,7 @@ class Databases(object):
if isNoneValue(value): if isNoneValue(value):
query = rootQuery.blind.query % index query = rootQuery.blind.query % index
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I) query = re.sub("INFORMATION_SCHEMA", "DATA_DICTIONARY", query, flags=re.I)
value = unArrayizeValue(inject.getValue(query, union=False, error=False)) value = unArrayizeValue(inject.getValue(query, union=False, error=False))

View File

@@ -81,7 +81,7 @@ class Users(object):
if Backend.isDbms(DBMS.MYSQL): if Backend.isDbms(DBMS.MYSQL):
self.getCurrentUser() self.getCurrentUser()
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
kb.data.isDba = "root" in (kb.data.currentUser or "") kb.data.isDba = "root" in (kb.data.currentUser or "")
elif kb.data.currentUser: elif kb.data.currentUser:
query = queries[Backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0] query = queries[Backend.getIdentifiedDbms()].is_dba.query % kb.data.currentUser.split("@")[0]
@@ -106,7 +106,7 @@ class Users(object):
condition |= (Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema) condition |= (Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema)
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = rootQuery.inband.query3 query = rootQuery.inband.query3
elif condition: elif condition:
query = rootQuery.inband.query2 query = rootQuery.inband.query2
@@ -126,7 +126,7 @@ class Users(object):
infoMsg = "fetching number of database users" infoMsg = "fetching number of database users"
logger.info(infoMsg) logger.info(infoMsg)
if Backend.isFork(FORK.DRIZZLE): if Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = rootQuery.blind.count3 query = rootQuery.blind.count3
elif condition: elif condition:
query = rootQuery.blind.count2 query = rootQuery.blind.count2
@@ -147,7 +147,7 @@ class Users(object):
for index in indexRange: for index in indexRange:
if Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB): if Backend.getIdentifiedDbms() in (DBMS.SYBASE, DBMS.MAXDB):
query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ") query = rootQuery.blind.query % (kb.data.cachedUsers[-1] if kb.data.cachedUsers else " ")
elif Backend.isFork(FORK.DRIZZLE): elif Backend.isDbms(DBMS.MYSQL) and Backend.isFork(FORK.DRIZZLE):
query = rootQuery.blind.query3 % index query = rootQuery.blind.query3 % index
elif condition: elif condition:
query = rootQuery.blind.query2 % index query = rootQuery.blind.query2 % index