diff --git a/data/txt/sha256sums.txt b/data/txt/sha256sums.txt
index a5091a6f11d..4f2f0eb6317 100644
--- a/data/txt/sha256sums.txt
+++ b/data/txt/sha256sums.txt
@@ -84,7 +84,7 @@ b0f434f64105bd61ab0f6867b3f681b97fa02b4fb809ac538db382d031f0e609 data/xml/paylo
0648264166455010921df1ec431e4c973809f37ef12cbfea75f95029222eb689 data/xml/payloads/stacked_queries.xml
997556b6170964a64474a2e053abe33cf2cf029fb1acec660d4651cc67a3c7e1 data/xml/payloads/time_blind.xml
40a4878669f318568097719d07dc906a19b8520bc742be3583321fc1e8176089 data/xml/payloads/union_query.xml
-8b63fda09d5c5e43ad8e6db1db90e5b1017fbe02735f3858843fc52118e3a33a data/xml/queries.xml
+45c55b519d72ae69b6de963ba8882e1826b48ab584a6d7b8223281ab3b3f86a0 data/xml/queries.xml
0f5a9c84cb57809be8759f483c7d05f54847115e715521ac0ecf390c0aa68465 doc/AUTHORS
ce20a4b452f24a97fde7ec9ed816feee12ac148e1fde5f1722772cc866b12740 doc/CHANGELOG.md
233fb10dff24a2436eb24496db7fadb46659da6745a0d53c744db701188041ef doc/THANKS.md
@@ -163,20 +163,20 @@ df768bcb9838dc6c46dab9b4a877056cb4742bd6cfaaf438c4a3712c5cc0d264 extra/shutils/
b8411d1035bb49b073476404e61e1be7f4c61e205057730e2f7880beadcd5f60 lib/controller/action.py
6da812281a69c8b7a5181c2f76374dc695e4727b2936042651bacbeda4e6bcc9 lib/controller/checks.py
c1881685bef8504ded32c51abed00ab51849008c84b74e8a66117e5f5041b3df lib/controller/controller.py
-d69e84f1648cdb907f5d2dd454f03874a4613752b07867510145d51d84b3c56f lib/controller/handler.py
+2d930f47eaaa95fa129705751ebbeef374d5c1e39d4ac94bab384c2e1bac28eb lib/controller/handler.py
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/controller/__init__.py
-bc655c5f09a4048e53d2fec5f65e9e45024c2ad9882b8824b0d338917fd6496b lib/core/agent.py
+87bb4e0c6b4fc33b4447756b1f07e660e092528f8efe4b3205c835659997e939 lib/core/agent.py
ca3e5ce56cb1cae0a8e815425ab6810068004bffe8861d1037c7c87c0ae02477 lib/core/bigarray.py
-c91b6b9429a50d28b88334e3f88557d40a01893a7e69c30186c2f6efd0ce9906 lib/core/common.py
+1c1828cae42295c3b6c7fb29cec60b6610b4cc1457d9dabd7966e15148c2ee70 lib/core/common.py
f30b4eccdb574731fa7e6ef48e71ea82d4bc99be70a2e27bff230943e9039313 lib/core/compat.py
e37bfd314a46699b14e1c8a5ea851d546d3a36bea8e5f37466ef2921ff78fefd lib/core/convert.py
c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data.py
6acb645b1f285b21673c70824b03f6209acc5993b50e50da5ed2c713a30626f5 lib/core/datatype.py
70fb2528e580b22564899595b0dff6b1bc257c6a99d2022ce3996a3d04e68e4e lib/core/decorators.py
147823c37596bd6a56d677697781f34b8d1d1671d5a2518fbc9468d623c6d07d lib/core/defaults.py
-2f44a1bfe6f18aafe64147b99e69aa93cf438c0e7befe59f4e2aee9065c8b7b6 lib/core/dicts.py
-8aee07fba24082ee6355a29d01842bc3657194148a7f9062079b5f0a85ec53e3 lib/core/dump.py
-23e33f0b457e2a7114c9171ba9b42e1751b71ee3f384bba7fad39e4490adb803 lib/core/enums.py
+1b0bafa991e74e053d4b3260491d4234c15f877e0f0f6d94630fb7eca52bc2ff lib/core/dicts.py
+926437d5b99f59a10c98d9be7ffd6ae5cc5a93c0538658f334689858067c6ac7 lib/core/dump.py
+278083554dcba168174b8265b077726824b746cf7cfcf336a878a738117f0c5a lib/core/enums.py
5387168e5dfedd94ae22af7bb255f27d6baaca50b24179c6b98f4f325f5cc7b4 lib/core/exception.py
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/core/__init__.py
914a13ee21fd610a6153a37cbe50830fcbd1324c7ebc1e7fc206d5e598b0f7ad lib/core/log.py
@@ -188,7 +188,7 @@ c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data.
48797d6c34dd9bb8a53f7f3794c85f4288d82a9a1d6be7fcf317d388cb20d4b3 lib/core/replication.py
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
-dcd48ee4483e0ef394e4d4f7bb5566b107ea0e0d4b665ad2b0280ecb12799b47 lib/core/settings.py
+18f01b6f22b4d24adf04edb165cff31bc24dfb7eb354594f765a9a40c6a1a234 lib/core/settings.py
cd5a66deee8963ba8e7e9af3dd36eb5e8127d4d68698811c29e789655f507f82 lib/core/shell.py
bcb5d8090d5e3e0ef2a586ba09ba80eef0c6d51feb0f611ed25299fbb254f725 lib/core/subprocessng.py
70ea3768f1b3062b22d20644df41c86238157ec80dd43da40545c620714273c6 lib/core/target.py
@@ -476,7 +476,7 @@ e2e20e4707abe9ed8b6208837332d2daa4eaca282f847412063f2484dcca8fbd plugins/dbms/v
2b2dad6ba1d344215cad11b629546eb9f259d7c996c202edf3de5ab22418787e plugins/dbms/virtuoso/takeover.py
51c44048e4b335b306f8ed1323fd78ad6935a8c0d6e9d6efe195a9a5a24e46dc plugins/generic/connector.py
a967f4ebd101c68a5dcc10ff18c882a8f44a5c3bf06613d951a739ecc3abb9b3 plugins/generic/custom.py
-37351d6fb7418e3659bec5c9a6f9f181a606deae74d3bc9fb8c97f495449471f plugins/generic/databases.py
+511680a3f61a4413131356340cae7722b523fc4d050e63646c73d444de1a24d5 plugins/generic/databases.py
36b7319ac00f8fe1a33496364a76ff165ea2e66db0150f5366a45135366369ca plugins/generic/entries.py
d2de7fc135cf0db3eb4ac4a509c23ebec5250a5d8043face7f8c546a09f301b5 plugins/generic/enumeration.py
a02ac4ebc1cc488a2aa5ae07e6d0c3d5064e99ded7fd529dfa073735692f11df plugins/generic/filesystem.py
@@ -642,3 +642,10 @@ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 thirdparty/ter
b14474d467c70f5fe6cb8ed624f79d881c04fe6aeb7d406455da624fe8b3c0df thirdparty/termcolor/termcolor.py
4db695470f664b0d7cd5e6b9f3c94c8d811c4c550f37f17ed7bdab61bc3bdefc thirdparty/wininetpton/__init__.py
ac055d6ae1f7a99d4334a4e5328dae1758e7a84f01292acd1bb5105ee4f26927 thirdparty/wininetpton/win_inet_pton.py
+def1d902bf9528b2b769e603683e45c9691bd5f60968a806de6ab8c08c3f51fe plugins/dbms/hana/__init__.py
+6d95111e148c2f2f8f41167e85fc83a19a16aa0320e2d0d23c78025181480537 plugins/dbms/hana/connector.py
+de1312a5febbbe2676344c61c454652b6689103a3c41c3624acca795ad9ce882 plugins/dbms/hana/enumeration.py
+9a955691b626aad6b7d571a6857a3c16759856d3939c1d92ef3864b437744780 plugins/dbms/hana/filesystem.py
+41d741679664e5fad09bfcf640f0c8db16ed46238b795e20633dce6f95f6a755 plugins/dbms/hana/fingerprint.py
+4878e83ef8e33915412f2fac17d92f1b1f6f18b47d31500cd93e59d68f8b5752 plugins/dbms/hana/syntax.py
+ea3eda65047c9c20961b02fdd67c0bb922c83230d34dc052eb143a75d36719c9 plugins/dbms/hana/takeover.py
diff --git a/data/xml/queries.xml b/data/xml/queries.xml
index e2f28405781..16d19006e6f 100644
--- a/data/xml/queries.xml
+++ b/data/xml/queries.xml
@@ -1906,4 +1906,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/controller/handler.py b/lib/controller/handler.py
index 23e7bb441b4..0721cd1253b 100644
--- a/lib/controller/handler.py
+++ b/lib/controller/handler.py
@@ -25,6 +25,7 @@
from lib.core.settings import FIREBIRD_ALIASES
from lib.core.settings import FRONTBASE_ALIASES
from lib.core.settings import H2_ALIASES
+from lib.core.settings import HANA_ALIASES
from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import INFORMIX_ALIASES
from lib.core.settings import MAXDB_ALIASES
@@ -57,6 +58,7 @@
from plugins.dbms.firebird import FirebirdMap
from plugins.dbms.frontbase import FrontBaseMap
from plugins.dbms.h2 import H2Map
+from plugins.dbms.hana import HANAMap
from plugins.dbms.hsqldb import HSQLDBMap
from plugins.dbms.informix import InformixMap
from plugins.dbms.maxdb import MaxDBMap
@@ -113,6 +115,7 @@ def setHandler():
(DBMS.VIRTUOSO, VIRTUOSO_ALIASES, VirtuosoMap, "plugins.dbms.virtuoso.connector"),
(DBMS.SNOWFLAKE, SNOWFLAKE_ALIASES, SnowflakeMap, "plugins.dbms.snowflake.connector"),
(DBMS.SPANNER, SPANNER_ALIASES, SpannerMap, "plugins.dbms.spanner.connector"),
+ (DBMS.HANA, HANA_ALIASES, HANAMap, "plugins.dbms.hana.connector"),
]
_ = max(_ if (conf.get("dbms") or Backend.getIdentifiedDbms() or kb.heuristicExtendedDbms or "").lower() in _[1] else () for _ in items)
diff --git a/lib/core/agent.py b/lib/core/agent.py
index 9c109238acd..45096f985a9 100644
--- a/lib/core/agent.py
+++ b/lib/core/agent.py
@@ -727,7 +727,7 @@ def concatQuery(self, query, unpack=True):
elif fieldsNoSelect:
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.chars.start, concatenatedQuery, kb.chars.stop)
- elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO, DBMS.SNOWFLAKE, DBMS.SPANNER):
+ elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE, DBMS.DB2, DBMS.FIREBIRD, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.DERBY, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.CRATEDB, DBMS.CUBRID, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO, DBMS.SNOWFLAKE, DBMS.SPANNER, DBMS.HANA):
if fieldsExists:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.chars.start, 1)
concatenatedQuery += "||'%s'" % kb.chars.stop
@@ -1048,7 +1048,7 @@ def limitQuery(self, num, query, field=None, uniqueField=None):
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
limitedQuery += " %s" % limitStr
- elif Backend.getIdentifiedDbms() in (DBMS.H2, DBMS.CRATEDB, DBMS.CLICKHOUSE, DBMS.SNOWFLAKE, DBMS.SPANNER):
+ elif Backend.getIdentifiedDbms() in (DBMS.H2, DBMS.CRATEDB, DBMS.CLICKHOUSE, DBMS.SNOWFLAKE, DBMS.SPANNER, DBMS.HANA):
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (1, num)
limitedQuery += " %s" % limitStr
diff --git a/lib/core/common.py b/lib/core/common.py
index e486a6fe149..aad5263f814 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -4324,7 +4324,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
retVal = "`%s`" % retVal
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO, DBMS.SNOWFLAKE, DBMS.FIREBIRD, DBMS.DERBY, DBMS.MAXDB):
retVal = "\"%s\"" % retVal
- elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
+ elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.HANA):
retVal = "\"%s\"" % retVal.upper()
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
if isTable:
@@ -4363,7 +4363,7 @@ def unsafeSQLIdentificatorNaming(name):
retVal = name.replace("`", "")
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX, DBMS.MONETDB, DBMS.VERTICA, DBMS.MCKOI, DBMS.PRESTO, DBMS.CRATEDB, DBMS.CACHE, DBMS.EXTREMEDB, DBMS.FRONTBASE, DBMS.RAIMA, DBMS.VIRTUOSO, DBMS.SNOWFLAKE, DBMS.FIREBIRD, DBMS.DERBY, DBMS.MAXDB):
retVal = name.replace("\"", "")
- elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL):
+ elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.HANA):
retVal = name.replace("\"", "").upper()
elif Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE):
retVal = name.replace("[", "").replace("]", "")
diff --git a/lib/core/dicts.py b/lib/core/dicts.py
index b53676df0f9..7a5528f9fe6 100644
--- a/lib/core/dicts.py
+++ b/lib/core/dicts.py
@@ -21,6 +21,7 @@
from lib.core.settings import FIREBIRD_ALIASES
from lib.core.settings import FRONTBASE_ALIASES
from lib.core.settings import H2_ALIASES
+from lib.core.settings import HANA_ALIASES
from lib.core.settings import HSQLDB_ALIASES
from lib.core.settings import INFORMIX_ALIASES
from lib.core.settings import MAXDB_ALIASES
@@ -254,6 +255,7 @@
DBMS.VIRTUOSO: (VIRTUOSO_ALIASES, None, None, None),
DBMS.SNOWFLAKE: (SNOWFLAKE_ALIASES, None, None, "snowflake"),
DBMS.SPANNER: (SPANNER_ALIASES, None, None, "spanner"),
+ DBMS.HANA: (HANA_ALIASES, "hdbcli", "https://pypi.org/project/hdbcli/", "hana"),
}
# Reference: https://blog.jooq.org/tag/sysibm-sysdummy1/
@@ -267,7 +269,8 @@
DBMS.INFORMIX: " FROM SYSMASTER:SYSDUAL",
DBMS.DERBY: " FROM SYSIBM.SYSDUMMY1",
DBMS.MIMERSQL: " FROM SYSTEM.ONEROW",
- DBMS.FRONTBASE: " FROM INFORMATION_SCHEMA.IO_STATISTICS"
+ DBMS.FRONTBASE: " FROM INFORMATION_SCHEMA.IO_STATISTICS",
+ DBMS.HANA: " FROM DUMMY"
}
HEURISTIC_NULL_EVAL = {
@@ -295,6 +298,7 @@
DBMS.CLICKHOUSE: "halfMD5(NULL)",
DBMS.SNOWFLAKE: "BOOLNOT(NULL)",
DBMS.SPANNER: "FARM_FINGERPRINT(NULL)",
+ DBMS.HANA: "MAP(NULL,NULL,NULL,NULL,NULL)",
}
SQL_STATEMENTS = {
diff --git a/lib/core/dump.py b/lib/core/dump.py
index d55291e5129..3245e7f7901 100644
--- a/lib/core/dump.py
+++ b/lib/core/dump.py
@@ -175,7 +175,7 @@ def currentUser(self, data):
self.string("current user", data, content_type=CONTENT_TYPE.CURRENT_USER)
def currentDb(self, data):
- if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE, DBMS.SNOWFLAKE):
+ if Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.PGSQL, DBMS.HSQLDB, DBMS.H2, DBMS.MONETDB, DBMS.VERTICA, DBMS.CRATEDB, DBMS.CACHE, DBMS.FRONTBASE, DBMS.SNOWFLAKE, DBMS.HANA):
self.string("current database (equivalent to schema on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
elif Backend.getIdentifiedDbms() in (DBMS.ALTIBASE, DBMS.DB2, DBMS.MIMERSQL, DBMS.MAXDB, DBMS.VIRTUOSO):
self.string("current database (equivalent to owner on %s)" % Backend.getIdentifiedDbms(), data, content_type=CONTENT_TYPE.CURRENT_DB)
diff --git a/lib/core/enums.py b/lib/core/enums.py
index 2e1881f19be..4f96a1960df 100644
--- a/lib/core/enums.py
+++ b/lib/core/enums.py
@@ -62,6 +62,7 @@ class DBMS(object):
VIRTUOSO = "Virtuoso"
SNOWFLAKE = "Snowflake"
SPANNER = "Spanner"
+ HANA = "SAP HANA"
class DBMS_DIRECTORY_NAME(object):
ACCESS = "access"
@@ -94,6 +95,7 @@ class DBMS_DIRECTORY_NAME(object):
VIRTUOSO = "virtuoso"
SNOWFLAKE = "snowflake"
SPANNER = "spanner"
+ HANA = "hana"
class FORK(object):
MARIADB = "MariaDB"
diff --git a/lib/core/settings.py b/lib/core/settings.py
index a3996818094..11fa656d07b 100644
--- a/lib/core/settings.py
+++ b/lib/core/settings.py
@@ -299,6 +299,7 @@
VIRTUOSO_SYSTEM_DBS = ("",)
SNOWFLAKE_SYSTEM_DBS = ("INFORMATION_SCHEMA",)
SPANNER_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SPANNER_SYS")
+HANA_SYSTEM_DBS = ("SYS", "SYSTEM", "_SYS_BI", "_SYS_BIC", "_SYS_REPO", "_SYS_STATISTICS", "_SYS_XS", "HANA_XS_BASE")
# Note: () + ()
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
@@ -331,20 +332,21 @@
VIRTUOSO_ALIASES = ("virtuoso", "openlink virtuoso")
SNOWFLAKE_ALIASES = ("snowflake",)
SPANNER_ALIASES = ("spanner", "google cloud spanner", "google spanner")
+HANA_ALIASES = ("hana", "sap hana", "saphana", "hdb")
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
-SUPPORTED_DBMS = set(MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES + MIMERSQL_ALIASES + CLICKHOUSE_ALIASES + CRATEDB_ALIASES + CUBRID_ALIASES + CACHE_ALIASES + EXTREMEDB_ALIASES + RAIMA_ALIASES + VIRTUOSO_ALIASES + SNOWFLAKE_ALIASES + SPANNER_ALIASES)
+SUPPORTED_DBMS = set(MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + H2_ALIASES + INFORMIX_ALIASES + MONETDB_ALIASES + DERBY_ALIASES + VERTICA_ALIASES + MCKOI_ALIASES + PRESTO_ALIASES + ALTIBASE_ALIASES + MIMERSQL_ALIASES + CLICKHOUSE_ALIASES + CRATEDB_ALIASES + CUBRID_ALIASES + CACHE_ALIASES + EXTREMEDB_ALIASES + RAIMA_ALIASES + VIRTUOSO_ALIASES + SNOWFLAKE_ALIASES + SPANNER_ALIASES + HANA_ALIASES)
SUPPORTED_OS = ("linux", "windows")
-DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES), (DBMS.MIMERSQL, MIMERSQL_ALIASES), (DBMS.CLICKHOUSE, CLICKHOUSE_ALIASES), (DBMS.CRATEDB, CRATEDB_ALIASES), (DBMS.CUBRID, CUBRID_ALIASES), (DBMS.CACHE, CACHE_ALIASES), (DBMS.EXTREMEDB, EXTREMEDB_ALIASES), (DBMS.FRONTBASE, FRONTBASE_ALIASES), (DBMS.RAIMA, RAIMA_ALIASES), (DBMS.VIRTUOSO, VIRTUOSO_ALIASES), (DBMS.SNOWFLAKE, SNOWFLAKE_ALIASES), (DBMS.SPANNER, SPANNER_ALIASES))
+DBMS_ALIASES = ((DBMS.MSSQL, MSSQL_ALIASES), (DBMS.MYSQL, MYSQL_ALIASES), (DBMS.PGSQL, PGSQL_ALIASES), (DBMS.ORACLE, ORACLE_ALIASES), (DBMS.SQLITE, SQLITE_ALIASES), (DBMS.ACCESS, ACCESS_ALIASES), (DBMS.FIREBIRD, FIREBIRD_ALIASES), (DBMS.MAXDB, MAXDB_ALIASES), (DBMS.SYBASE, SYBASE_ALIASES), (DBMS.DB2, DB2_ALIASES), (DBMS.HSQLDB, HSQLDB_ALIASES), (DBMS.H2, H2_ALIASES), (DBMS.INFORMIX, INFORMIX_ALIASES), (DBMS.MONETDB, MONETDB_ALIASES), (DBMS.DERBY, DERBY_ALIASES), (DBMS.VERTICA, VERTICA_ALIASES), (DBMS.MCKOI, MCKOI_ALIASES), (DBMS.PRESTO, PRESTO_ALIASES), (DBMS.ALTIBASE, ALTIBASE_ALIASES), (DBMS.MIMERSQL, MIMERSQL_ALIASES), (DBMS.CLICKHOUSE, CLICKHOUSE_ALIASES), (DBMS.CRATEDB, CRATEDB_ALIASES), (DBMS.CUBRID, CUBRID_ALIASES), (DBMS.CACHE, CACHE_ALIASES), (DBMS.EXTREMEDB, EXTREMEDB_ALIASES), (DBMS.FRONTBASE, FRONTBASE_ALIASES), (DBMS.RAIMA, RAIMA_ALIASES), (DBMS.VIRTUOSO, VIRTUOSO_ALIASES), (DBMS.SNOWFLAKE, SNOWFLAKE_ALIASES), (DBMS.SPANNER, SPANNER_ALIASES), (DBMS.HANA, HANA_ALIASES))
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
REFERER_ALIASES = ("ref", "referer", "referrer")
HOST_ALIASES = ("host",)
# DBMSes with upper case identifiers
-UPPER_CASE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.H2, DBMS.HSQLDB, DBMS.DERBY, DBMS.ALTIBASE, DBMS.SNOWFLAKE))
+UPPER_CASE_DBMSES = set((DBMS.ORACLE, DBMS.DB2, DBMS.FIREBIRD, DBMS.MAXDB, DBMS.H2, DBMS.HSQLDB, DBMS.DERBY, DBMS.ALTIBASE, DBMS.SNOWFLAKE, DBMS.HANA))
# Default schemas to use (when unable to enumerate)
H2_DEFAULT_SCHEMA = HSQLDB_DEFAULT_SCHEMA = "PUBLIC"
diff --git a/plugins/dbms/hana/__init__.py b/plugins/dbms/hana/__init__.py
new file mode 100644
index 00000000000..81dbccf257c
--- /dev/null
+++ b/plugins/dbms/hana/__init__.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from lib.core.enums import DBMS
+from lib.core.settings import HANA_SYSTEM_DBS
+from lib.core.unescaper import unescaper
+from plugins.dbms.hana.enumeration import Enumeration
+from plugins.dbms.hana.filesystem import Filesystem
+from plugins.dbms.hana.fingerprint import Fingerprint
+from plugins.dbms.hana.syntax import Syntax
+from plugins.dbms.hana.takeover import Takeover
+from plugins.generic.misc import Miscellaneous
+
+class HANAMap(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
+ """
+ This class defines SAP HANA methods
+ """
+
+ def __init__(self):
+ self.excludeDbsList = HANA_SYSTEM_DBS
+
+ for cls in self.__class__.__bases__:
+ cls.__init__(self)
+
+ unescaper[DBMS.HANA] = Syntax.escape
diff --git a/plugins/dbms/hana/connector.py b/plugins/dbms/hana/connector.py
new file mode 100644
index 00000000000..b01385ce82a
--- /dev/null
+++ b/plugins/dbms/hana/connector.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+try:
+ from hdbcli import dbapi
+except ImportError:
+ pass
+
+from lib.core.common import getSafeExString
+from lib.core.data import logger
+from lib.core.exception import SqlmapConnectionException
+from plugins.generic.connector import Connector as GenericConnector
+
+class Connector(GenericConnector):
+ """
+ Homepage: https://pypi.org/project/hdbcli/
+ User guide: https://help.sap.com/docs/SAP_HANA_PLATFORM/f1b440ded6144a54ada97ff95dac7adf/4fe9978ebac44f35b9369ef5a4a6d73e.html
+ API: https://help.sap.com/docs/SAP_HANA_CLIENT/f1b440ded6144a54ada97ff95dac7adf/39eb663beaab4f7b94850834e6cb6280.html
+ Debian package: not available
+ License: SAP Developer License
+ """
+
+ def connect(self):
+ self.initConnection()
+
+ try:
+ self.connector = dbapi.connect(address=self.hostname, port=self.port, user=self.user, password=self.password, databaseName=self.db)
+ except Exception as ex:
+ raise SqlmapConnectionException(getSafeExString(ex))
+
+ self.initCursor()
+ self.printConnected()
+
+ def fetchall(self):
+ try:
+ return self.cursor.fetchall()
+ except dbapi.Error as ex:
+ logger.warning(getSafeExString(ex))
+ return None
+
+ def execute(self, query):
+ retVal = False
+
+ try:
+ self.cursor.execute(query)
+ retVal = True
+ except dbapi.Error as ex:
+ logger.warning(("(remote) '%s'" % getSafeExString(ex)).strip())
+
+ self.connector.commit()
+
+ return retVal
+
+ def select(self, query):
+ retVal = None
+
+ if self.execute(query):
+ retVal = self.fetchall()
+
+ return retVal
diff --git a/plugins/dbms/hana/enumeration.py b/plugins/dbms/hana/enumeration.py
new file mode 100644
index 00000000000..24e6e5d3808
--- /dev/null
+++ b/plugins/dbms/hana/enumeration.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from lib.core.data import logger
+from plugins.generic.enumeration import Enumeration as GenericEnumeration
+
+class Enumeration(GenericEnumeration):
+ def getPasswordHashes(self):
+ warnMsg = "on SAP HANA it is not possible to enumerate the user password hashes"
+ logger.warning(warnMsg)
+
+ return {}
diff --git a/plugins/dbms/hana/filesystem.py b/plugins/dbms/hana/filesystem.py
new file mode 100644
index 00000000000..5992ee66aff
--- /dev/null
+++ b/plugins/dbms/hana/filesystem.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from lib.core.exception import SqlmapUnsupportedFeatureException
+from plugins.generic.filesystem import Filesystem as GenericFilesystem
+
+class Filesystem(GenericFilesystem):
+ def readFile(self, remoteFile):
+ errMsg = "on SAP HANA reading of files is not supported"
+ raise SqlmapUnsupportedFeatureException(errMsg)
+
+ def writeFile(self, localFile, remoteFile, fileType=None, forceCheck=False):
+ errMsg = "on SAP HANA writing of files is not supported"
+ raise SqlmapUnsupportedFeatureException(errMsg)
diff --git a/plugins/dbms/hana/fingerprint.py b/plugins/dbms/hana/fingerprint.py
new file mode 100644
index 00000000000..bd292f3f8dd
--- /dev/null
+++ b/plugins/dbms/hana/fingerprint.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from lib.core.common import Backend
+from lib.core.common import Format
+from lib.core.data import conf
+from lib.core.data import kb
+from lib.core.data import logger
+from lib.core.enums import DBMS
+from lib.core.session import setDbms
+from lib.core.settings import HANA_ALIASES
+from lib.request import inject
+from plugins.generic.fingerprint import Fingerprint as GenericFingerprint
+
+class Fingerprint(GenericFingerprint):
+ def __init__(self):
+ GenericFingerprint.__init__(self, DBMS.HANA)
+
+ def getFingerprint(self):
+ value = ""
+ wsOsFp = Format.getOs("web server", kb.headersFp)
+
+ if wsOsFp:
+ value += "%s\n" % wsOsFp
+
+ if kb.data.banner:
+ dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp)
+
+ if dbmsOsFp:
+ value += "%s\n" % dbmsOsFp
+
+ value += "back-end DBMS: "
+
+ if not conf.extensiveFp:
+ value += DBMS.HANA
+ return value
+
+ actVer = Format.getDbms()
+ blank = " " * 15
+ value += "active fingerprint: %s" % actVer
+
+ if kb.bannerFp:
+ banVer = kb.bannerFp.get("dbmsVersion")
+
+ if banVer:
+ banVer = Format.getDbms([banVer])
+ value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer)
+
+ htmlErrorFp = Format.getErrorParsedDBMSes()
+
+ if htmlErrorFp:
+ value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp)
+
+ return value
+
+ def checkDbms(self):
+ if not conf.extensiveFp and Backend.isDbmsWithin(HANA_ALIASES):
+ setDbms(DBMS.HANA)
+
+ self.getBanner()
+
+ return True
+
+ infoMsg = "testing %s" % DBMS.HANA
+ logger.info(infoMsg)
+
+ result = inject.checkBooleanExpression("MAP(1,1,'[RANDSTR1]','[RANDSTR2]')='[RANDSTR1]'")
+
+ if result:
+ infoMsg = "confirming %s" % DBMS.HANA
+ logger.info(infoMsg)
+
+ result = inject.checkBooleanExpression("(SELECT CURRENT_SCHEMA FROM DUMMY) IS NOT NULL")
+
+ if not result:
+ warnMsg = "the back-end DBMS is not %s" % DBMS.HANA
+ logger.warning(warnMsg)
+
+ return False
+
+ setDbms(DBMS.HANA)
+
+ self.getBanner()
+
+ return True
+ else:
+ warnMsg = "the back-end DBMS is not %s" % DBMS.HANA
+ logger.warning(warnMsg)
+
+ return False
diff --git a/plugins/dbms/hana/syntax.py b/plugins/dbms/hana/syntax.py
new file mode 100644
index 00000000000..17a0a02c257
--- /dev/null
+++ b/plugins/dbms/hana/syntax.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from plugins.generic.syntax import Syntax as GenericSyntax
+
+class Syntax(GenericSyntax):
+ @staticmethod
+ def escape(expression, quote=True):
+ """
+ >>> Syntax.escape("SELECT 'abcdefgh' FROM foobar") == "SELECT 'abcdefgh' FROM foobar"
+ True
+ """
+
+ return expression
diff --git a/plugins/dbms/hana/takeover.py b/plugins/dbms/hana/takeover.py
new file mode 100644
index 00000000000..b21c4f7e858
--- /dev/null
+++ b/plugins/dbms/hana/takeover.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+"""
+Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
+See the file 'LICENSE' for copying permission
+"""
+
+from lib.core.exception import SqlmapUnsupportedFeatureException
+from plugins.generic.takeover import Takeover as GenericTakeover
+
+class Takeover(GenericTakeover):
+ def osCmd(self):
+ errMsg = "on SAP HANA it is not possible to execute commands"
+ raise SqlmapUnsupportedFeatureException(errMsg)
+
+ def osShell(self):
+ errMsg = "on SAP HANA it is not possible to execute commands"
+ raise SqlmapUnsupportedFeatureException(errMsg)
+
+ def osPwn(self):
+ errMsg = "on SAP HANA it is not possible to establish an "
+ errMsg += "out-of-band connection"
+ raise SqlmapUnsupportedFeatureException(errMsg)
+
+ def osSmb(self):
+ errMsg = "on SAP HANA it is not possible to establish an "
+ errMsg += "out-of-band connection"
+ raise SqlmapUnsupportedFeatureException(errMsg)
diff --git a/plugins/generic/databases.py b/plugins/generic/databases.py
index f5d5987f62e..2f6a4df833a 100644
--- a/plugins/generic/databases.py
+++ b/plugins/generic/databases.py
@@ -639,7 +639,7 @@ def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None, dumpMod
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(conf.db), unsafeSQLIdentificatorNaming(conf.db))
query += condQuery
- elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.SNOWFLAKE):
+ elif Backend.getIdentifiedDbms() in (DBMS.ORACLE, DBMS.DB2, DBMS.DERBY, DBMS.ALTIBASE, DBMS.MIMERSQL, DBMS.SNOWFLAKE, DBMS.HANA):
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl.upper()), unsafeSQLIdentificatorNaming(conf.db.upper()))
query += condQuery