Skip to content

Commit d5ff557

Browse files
committed
Some more patches for -d
1 parent e23a91f commit d5ff557

9 files changed

Lines changed: 70 additions & 9 deletions

File tree

lib/core/dicts.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@
232232
DBMS.SQLITE: (SQLITE_ALIASES, "python-sqlite", "https://docs.python.org/3/library/sqlite3.html", "sqlite"),
233233
DBMS.ACCESS: (ACCESS_ALIASES, "python-pyodbc", "https://github.com/mkleehammer/pyodbc", "access"),
234234
DBMS.FIREBIRD: (FIREBIRD_ALIASES, "python3-firebirdsql", "https://github.com/nakagami/pyfirebirdsql/", "firebird"),
235-
DBMS.MAXDB: (MAXDB_ALIASES, None, None, "maxdb"),
235+
DBMS.MAXDB: (MAXDB_ALIASES, None, None, None), # 'maxdb'/'sapdb' SQLAlchemy dialect was removed long ago; a dead dialect only produces a misleading warning
236236
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"),
237237
DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
238238
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & https://github.com/jpype-project/jpype", None),

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from thirdparty import six
2121

2222
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
23-
VERSION = "1.10.7.83"
23+
VERSION = "1.10.7.84"
2424
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2525
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2626
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/request/direct.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ def direct(query, content=True):
6060
break
6161

6262
if select:
63-
if re.search(r"(?i)\ASELECT ", query) is None:
63+
# only auto-wrap a bare scalar expression (e.g. 'CURRENT_USER', '48*60') in SELECT; a user-supplied
64+
# complete row-returning statement (--sql-query 'PRAGMA ...' / 'WITH ...' / 'EXPLAIN ...') must be left
65+
# intact, otherwise 'SELECT PRAGMA ...' is a syntax error and silently returns nothing
66+
if re.search(r"(?i)\A\s*(?:SELECT|WITH|PRAGMA|EXPLAIN|DESCRIBE|DESC|SHOW|TABLE|VALUES)\b", query) is None:
6467
query = "SELECT %s" % query
6568

6669
if conf.binaryFields:
@@ -82,7 +85,11 @@ def direct(query, content=True):
8285
output = [tuple(_hexifyBinary(_) for _ in row) if isListLike(row) else _hexifyBinary(row) for row in output]
8386
if state == TIMEOUT_STATE.NORMAL:
8487
hashDBWrite(query, output, True)
85-
elif state == TIMEOUT_STATE.TIMEOUT:
88+
elif state in (TIMEOUT_STATE.TIMEOUT, TIMEOUT_STATE.EXCEPTION):
89+
# a timed-out OR fatally-errored query (e.g. the connector raised SqlmapConnectionException, or the
90+
# connection dropped mid-scan) left the connection unusable; reconnect so the rest of the scan
91+
# recovers instead of every following query being silently swallowed to None (wrong/empty data).
92+
# A genuinely dead DB makes connect() raise here and the scan aborts cleanly, as with TIMEOUT.
8693
conf.dbmsConnector.close()
8794
conf.dbmsConnector.connect()
8895
elif output:

plugins/dbms/access/connector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ def connect(self):
3838
self.checkFileDb()
3939

4040
try:
41-
self.connector = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb)};Dbq=%s;Uid=Admin;Pwd=;' % self.db)
41+
# ACE driver ('*.mdb, *.accdb') handles both legacy Jet .mdb and modern .accdb (the old '*.mdb'-only
42+
# Jet driver is 32-bit-only and absent on modern installs); honor supplied credentials, not Admin/empty
43+
self.connector = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=%s;Uid=%s;Pwd=%s;' % (self.db, self.user or "Admin", self.password or ""))
4244
except (pyodbc.Error, pyodbc.OperationalError) as ex:
4345
raise SqlmapConnectionException(getSafeExString(ex))
4446

plugins/dbms/clickhouse/connector.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,51 @@
55
See the file 'LICENSE' for copying permission
66
"""
77

8+
try:
9+
import clickhouse_connect
10+
import clickhouse_connect.dbapi
11+
except:
12+
pass
13+
14+
import logging
15+
16+
from lib.core.common import getSafeExString
17+
from lib.core.data import conf
18+
from lib.core.data import logger
19+
from lib.core.exception import SqlmapConnectionException
820
from plugins.generic.connector import Connector as GenericConnector
921

1022
class Connector(GenericConnector):
11-
pass
23+
"""
24+
Homepage: https://github.com/ClickHouse/clickhouse-connect
25+
User guide: https://clickhouse.com/docs/integrations/python
26+
License: Apache 2.0
27+
"""
28+
29+
def connect(self):
30+
self.initConnection()
31+
32+
try:
33+
self.connector = clickhouse_connect.dbapi.connect(host=self.hostname, port=self.port, username=self.user, password=self.password, database=self.db)
34+
except clickhouse_connect.dbapi.Error as ex:
35+
raise SqlmapConnectionException(getSafeExString(ex))
36+
37+
self.initCursor()
38+
self.printConnected()
39+
40+
def fetchall(self):
41+
try:
42+
return self.cursor.fetchall()
43+
except clickhouse_connect.dbapi.Error as ex:
44+
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
45+
return None
46+
47+
def execute(self, query):
48+
try:
49+
self.cursor.execute(query)
50+
except clickhouse_connect.dbapi.Error as ex:
51+
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % getSafeExString(ex))
52+
53+
def select(self, query):
54+
self.execute(query)
55+
return self.fetchall()

plugins/dbms/db2/connector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def connect(self):
3232
try:
3333
database = "DRIVER={IBM DB2 ODBC DRIVER};DATABASE=%s;HOSTNAME=%s;PORT=%s;PROTOCOL=TCPIP;" % (self.db, self.hostname, self.port)
3434
self.connector = ibm_db_dbi.connect(database, self.user, self.password)
35-
except ibm_db_dbi.OperationalError as ex:
35+
except ibm_db_dbi.Error as ex: # base class: ibm_db_dbi maps wrong-credential (SQLSTATE 28) to ProgrammingError, not OperationalError
3636
raise SqlmapConnectionException(getSafeExString(ex))
3737

3838
self.initCursor()

plugins/dbms/derby/connector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def connect(self):
3030
self.initConnection()
3131

3232
try:
33-
self.connector = drda.connect(host=self.hostname, database=self.db, port=self.port)
33+
self.connector = drda.connect(host=self.hostname, database=self.db, port=self.port, user=self.user or None, password=self.password or None)
3434
except drda.OperationalError as ex:
3535
raise SqlmapConnectionException(getSafeExString(ex))
3636

plugins/dbms/informix/connector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def connect(self):
3232
try:
3333
database = "DATABASE=%s;HOSTNAME=%s;PORT=%s;PROTOCOL=TCPIP;" % (self.db, self.hostname, self.port)
3434
self.connector = ibm_db_dbi.connect(database, self.user, self.password)
35-
except ibm_db_dbi.OperationalError as ex:
35+
except ibm_db_dbi.Error as ex: # base class: ibm_db_dbi maps wrong-credential (SQLSTATE 28) to ProgrammingError, not OperationalError
3636
raise SqlmapConnectionException(getSafeExString(ex))
3737

3838
self.initCursor()

plugins/dbms/snowflake/connector.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def __init__(self):
3232
def connect(self):
3333
self.initConnection()
3434

35+
# Snowflake's mandatory 'account' identifier is carried in the DSN host field
36+
# (e.g. -d "snowflake://user:pass@ACCOUNT/db"); warehouse/schema are optional. These were previously
37+
# read from self.account/self.warehouse/self.schema which were never set anywhere -> AttributeError on
38+
# every attempt.
39+
self.account = self.hostname
40+
self.warehouse = getattr(self, "warehouse", None)
41+
self.schema = getattr(self, "schema", None)
42+
3543
try:
3644
self.connector = snowflake.connector.connect(
3745
user=self.user,

0 commit comments

Comments
 (0)