Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 411f56e

Browse files
committed
Initial implementation for #3283
1 parent fb95ab8 commit 411f56e

18 files changed

Lines changed: 480 additions & 27 deletions

lib/controller/checks.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
from lib.core.settings import MAX_DIFFLIB_SEQUENCE_LENGTH
9090
from lib.core.settings import NON_SQLI_CHECK_PREFIX_SUFFIX_LENGTH
9191
from lib.core.settings import PRECONNECT_INCOMPATIBLE_SERVERS
92+
from lib.core.settings import SINGLE_QUOTE_MARKER
9293
from lib.core.settings import SLEEP_TIME_MARKER
9394
from lib.core.settings import SUHOSIN_MAX_VALUE_LENGTH
9495
from lib.core.settings import SUPPORTED_DBMS
@@ -859,8 +860,8 @@ def heuristicCheckDbms(injection):
859860
if conf.noEscape and dbms not in FROM_DUMMY_TABLE:
860861
continue
861862

862-
if checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr1)):
863-
if not checkBooleanExpression("(SELECT '%s'%s)='%s'" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), randStr2)):
863+
if checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr1, SINGLE_QUOTE_MARKER)):
864+
if not checkBooleanExpression("(SELECT '%s'%s)=%s%s%s" % (randStr1, FROM_DUMMY_TABLE.get(dbms, ""), SINGLE_QUOTE_MARKER, randStr2, SINGLE_QUOTE_MARKER)):
864865
retVal = dbms
865866
break
866867

lib/controller/handler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from lib.core.settings import SYBASE_ALIASES
2222
from lib.core.settings import DB2_ALIASES
2323
from lib.core.settings import HSQLDB_ALIASES
24+
from lib.core.settings import H2_ALIASES
2425
from lib.core.settings import INFORMIX_ALIASES
2526
from lib.utils.sqlalchemy import SQLAlchemy
2627

@@ -46,6 +47,8 @@
4647
from plugins.dbms.db2.connector import Connector as DB2Conn
4748
from plugins.dbms.hsqldb import HSQLDBMap
4849
from plugins.dbms.hsqldb.connector import Connector as HSQLDBConn
50+
from plugins.dbms.h2 import H2Map
51+
from plugins.dbms.h2.connector import Connector as H2Conn
4952
from plugins.dbms.informix import InformixMap
5053
from plugins.dbms.informix.connector import Connector as InformixConn
5154

@@ -67,6 +70,7 @@ def setHandler():
6770
(DBMS.SYBASE, SYBASE_ALIASES, SybaseMap, SybaseConn),
6871
(DBMS.DB2, DB2_ALIASES, DB2Map, DB2Conn),
6972
(DBMS.HSQLDB, HSQLDB_ALIASES, HSQLDBMap, HSQLDBConn),
73+
(DBMS.H2, H2_ALIASES, H2Map, H2Conn),
7074
(DBMS.INFORMIX, INFORMIX_ALIASES, InformixMap, InformixConn),
7175
]
7276

lib/core/agent.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from lib.core.settings import NULL
4444
from lib.core.settings import PAYLOAD_DELIMITER
4545
from lib.core.settings import REPLACEMENT_MARKER
46+
from lib.core.settings import SINGLE_QUOTE_MARKER
4647
from lib.core.settings import SLEEP_TIME_MARKER
4748
from lib.core.unescaper import unescaper
4849

@@ -348,6 +349,7 @@ def adjustLateValues(self, payload):
348349

349350
if payload:
350351
payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))
352+
payload = payload.replace(SINGLE_QUOTE_MARKER, "'")
351353

352354
for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)):
353355
payload = payload.replace(_, str(randomInt()))
@@ -821,7 +823,7 @@ def limitCondition(self, expression, dump=False):
821823
limitRegExp2 = None
822824

823825
if (limitRegExp or limitRegExp2) or (Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) and topLimit):
824-
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
826+
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
825827
limitGroupStart = queries[Backend.getIdentifiedDbms()].limitgroupstart.query
826828
limitGroupStop = queries[Backend.getIdentifiedDbms()].limitgroupstop.query
827829

@@ -911,7 +913,7 @@ def limitQuery(self, num, query, field=None, uniqueField=None):
911913
fromFrom = limitedQuery[fromIndex + 1:]
912914
orderBy = None
913915

914-
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE):
916+
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.PGSQL, DBMS.SQLITE, DBMS.H2):
915917
limitStr = queries[Backend.getIdentifiedDbms()].limit.query % (num, 1)
916918
limitedQuery += " %s" % limitStr
917919

lib/core/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3649,7 +3649,7 @@ def safeSQLIdentificatorNaming(name, isTable=False):
36493649

36503650
if Backend.getIdentifiedDbms() in (DBMS.MYSQL, DBMS.ACCESS):
36513651
retVal = "`%s`" % retVal
3652-
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.INFORMIX, DBMS.HSQLDB):
3652+
elif Backend.getIdentifiedDbms() in (DBMS.PGSQL, DBMS.DB2, DBMS.SQLITE, DBMS.HSQLDB, DBMS.H2, DBMS.INFORMIX):
36533653
retVal = "\"%s\"" % retVal
36543654
elif Backend.getIdentifiedDbms() in (DBMS.ORACLE,):
36553655
retVal = "\"%s\"" % retVal.upper()
@@ -4275,7 +4275,7 @@ def _(value):
42754275
retVal = retVal.decode("utf-16-le")
42764276
except UnicodeDecodeError:
42774277
pass
4278-
elif Backend.isDbms(DBMS.HSQLDB):
4278+
elif Backend.getIdentifiedDbms() in (DBMS.HSQLDB, DBMS.H2):
42794279
try:
42804280
retVal = retVal.decode("utf-16-be")
42814281
except UnicodeDecodeError:

lib/core/dicts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from lib.core.settings import SYBASE_ALIASES
2323
from lib.core.settings import DB2_ALIASES
2424
from lib.core.settings import HSQLDB_ALIASES
25+
from lib.core.settings import H2_ALIASES
2526
from lib.core.settings import INFORMIX_ALIASES
2627

2728
FIREBIRD_TYPES = {
@@ -195,6 +196,7 @@
195196
DBMS.SYBASE: (SYBASE_ALIASES, "python-pymssql", "https://github.com/pymssql/pymssql", "sybase"),
196197
DBMS.DB2: (DB2_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
197198
DBMS.HSQLDB: (HSQLDB_ALIASES, "python jaydebeapi & python-jpype", "https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/", None),
199+
DBMS.H2: (H2_ALIASES, None, None),
198200
DBMS.INFORMIX: (INFORMIX_ALIASES, "python ibm-db", "https://github.com/ibmdb/python-ibmdb", "ibm_db_sa"),
199201
}
200202

lib/core/enums.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class DBMS:
4343
SQLITE = "SQLite"
4444
SYBASE = "Sybase"
4545
HSQLDB = "HSQLDB"
46+
H2 = "H2"
4647
INFORMIX = "Informix"
4748

4849
class DBMS_DIRECTORY_NAME:
@@ -57,6 +58,7 @@ class DBMS_DIRECTORY_NAME:
5758
SQLITE = "sqlite"
5859
SYBASE = "sybase"
5960
HSQLDB = "hsqldb"
61+
H2 = "h2"
6062
INFORMIX = "informix"
6163

6264
class CUSTOM_LOGGING:

lib/core/settings.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from lib.core.enums import OS
2020

2121
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
22-
VERSION = "1.2.10.20"
22+
VERSION = "1.2.10.21"
2323
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2424
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2525
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
@@ -71,6 +71,7 @@
7171
RANDOM_STRING_MARKER = "[RANDSTR]"
7272
SLEEP_TIME_MARKER = "[SLEEPTIME]"
7373
INFERENCE_MARKER = "[INFERENCE]"
74+
SINGLE_QUOTE_MARKER = "[SINGLE_QUOTE]"
7475

7576
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
7677
CHAR_INFERENCE_MARK = "%c"
@@ -236,6 +237,7 @@
236237
SYBASE_SYSTEM_DBS = ("master", "model", "sybsystemdb", "sybsystemprocs")
237238
DB2_SYSTEM_DBS = ("NULLID", "SQLJ", "SYSCAT", "SYSFUN", "SYSIBM", "SYSIBMADM", "SYSIBMINTERNAL", "SYSIBMTS", "SYSPROC", "SYSPUBLIC", "SYSSTAT", "SYSTOOLS")
238239
HSQLDB_SYSTEM_DBS = ("INFORMATION_SCHEMA", "SYSTEM_LOB")
240+
H2_SYSTEM_DBS = ("INFORMATION_SCHEMA")
239241
INFORMIX_SYSTEM_DBS = ("sysmaster", "sysutils", "sysuser", "sysadmin")
240242

241243
MSSQL_ALIASES = ("microsoft sql server", "mssqlserver", "mssql", "ms")
@@ -249,14 +251,15 @@
249251
SYBASE_ALIASES = ("sybase", "sybase sql server")
250252
DB2_ALIASES = ("db2", "ibm db2", "ibmdb2")
251253
HSQLDB_ALIASES = ("hsql", "hsqldb", "hs", "hypersql")
254+
H2_ALIASES = ("h2",)
252255
INFORMIX_ALIASES = ("informix", "ibm informix", "ibminformix")
253256

254257
DBMS_DIRECTORY_DICT = dict((getattr(DBMS, _), getattr(DBMS_DIRECTORY_NAME, _)) for _ in dir(DBMS) if not _.startswith("_"))
255258

256-
SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIASES + SQLITE_ALIASES + ACCESS_ALIASES + FIREBIRD_ALIASES + MAXDB_ALIASES + SYBASE_ALIASES + DB2_ALIASES + HSQLDB_ALIASES + INFORMIX_ALIASES
259+
SUPPORTED_DBMS = 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
257260
SUPPORTED_OS = ("linux", "windows")
258261

259-
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))
262+
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))
260263

261264
USER_AGENT_ALIASES = ("ua", "useragent", "user-agent")
262265
REFERER_ALIASES = ("ref", "referer", "referrer")

plugins/dbms/h2/__init__.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
5+
See the file 'LICENSE' for copying permission
6+
"""
7+
8+
from lib.core.enums import DBMS
9+
from lib.core.settings import H2_SYSTEM_DBS
10+
from lib.core.unescaper import unescaper
11+
from plugins.dbms.h2.enumeration import Enumeration
12+
from plugins.dbms.h2.filesystem import Filesystem
13+
from plugins.dbms.h2.fingerprint import Fingerprint
14+
from plugins.dbms.h2.syntax import Syntax
15+
from plugins.dbms.h2.takeover import Takeover
16+
from plugins.generic.misc import Miscellaneous
17+
18+
class H2Map(Syntax, Fingerprint, Enumeration, Filesystem, Miscellaneous, Takeover):
19+
"""
20+
This class defines H2 methods
21+
"""
22+
23+
def __init__(self):
24+
self.excludeDbsList = H2_SYSTEM_DBS
25+
26+
Syntax.__init__(self)
27+
Fingerprint.__init__(self)
28+
Enumeration.__init__(self)
29+
Filesystem.__init__(self)
30+
Miscellaneous.__init__(self)
31+
Takeover.__init__(self)
32+
33+
unescaper[DBMS.H2] = Syntax.escape

plugins/dbms/h2/connector.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
5+
See the file 'LICENSE' for copying permission
6+
"""
7+
8+
try:
9+
import jaydebeapi
10+
import jpype
11+
except:
12+
pass
13+
14+
import logging
15+
16+
from lib.core.common import checkFile
17+
from lib.core.common import readInput
18+
from lib.core.data import conf
19+
from lib.core.data import logger
20+
from lib.core.exception import SqlmapConnectionException
21+
from plugins.generic.connector import Connector as GenericConnector
22+
23+
class Connector(GenericConnector):
24+
"""
25+
Homepage: https://pypi.python.org/pypi/JayDeBeApi/ & http://jpype.sourceforge.net/
26+
User guide: https://pypi.python.org/pypi/JayDeBeApi/#usage & http://jpype.sourceforge.net/doc/user-guide/userguide.html
27+
API: -
28+
Debian package: -
29+
License: LGPL & Apache License 2.0
30+
"""
31+
32+
def __init__(self):
33+
GenericConnector.__init__(self)
34+
35+
def connect(self):
36+
self.initConnection()
37+
try:
38+
msg = "what's the location of 'hsqldb.jar'? "
39+
jar = readInput(msg)
40+
checkFile(jar)
41+
args = "-Djava.class.path=%s" % jar
42+
jvm_path = jpype.getDefaultJVMPath()
43+
jpype.startJVM(jvm_path, args)
44+
except Exception, msg:
45+
raise SqlmapConnectionException(msg[0])
46+
47+
try:
48+
driver = 'org.hsqldb.jdbc.JDBCDriver'
49+
connection_string = 'jdbc:hsqldb:mem:.' # 'jdbc:hsqldb:hsql://%s/%s' % (self.hostname, self.db)
50+
self.connector = jaydebeapi.connect(driver, connection_string, str(self.user), str(self.password))
51+
except Exception, msg:
52+
raise SqlmapConnectionException(msg[0])
53+
54+
self.initCursor()
55+
self.printConnected()
56+
57+
def fetchall(self):
58+
try:
59+
return self.cursor.fetchall()
60+
except Exception, msg:
61+
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1])
62+
return None
63+
64+
def execute(self, query):
65+
retVal = False
66+
67+
try:
68+
self.cursor.execute(query)
69+
retVal = True
70+
except Exception, msg: # TODO: fix with specific error
71+
logger.log(logging.WARN if conf.dbmsHandler else logging.DEBUG, "(remote) %s" % msg[1])
72+
73+
self.connector.commit()
74+
75+
return retVal
76+
77+
def select(self, query):
78+
retVal = None
79+
80+
upper_query = query.upper()
81+
82+
if query and not (upper_query.startswith("SELECT ") or upper_query.startswith("VALUES ")):
83+
query = "VALUES %s" % query
84+
85+
if query and upper_query.startswith("SELECT ") and " FROM " not in upper_query:
86+
query = "%s FROM (VALUES(0))" % query
87+
88+
self.cursor.execute(query)
89+
retVal = self.cursor.fetchall()
90+
91+
return retVal

plugins/dbms/h2/enumeration.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
Copyright (c) 2006-2018 sqlmap developers (http://sqlmap.org/)
5+
See the file 'LICENSE' for copying permission
6+
"""
7+
8+
from plugins.generic.enumeration import Enumeration as GenericEnumeration
9+
from lib.core.data import conf
10+
from lib.core.data import kb
11+
from lib.core.data import logger
12+
from lib.core.data import queries
13+
from lib.core.common import unArrayizeValue
14+
from lib.core.enums import DBMS
15+
from lib.request import inject
16+
17+
class Enumeration(GenericEnumeration):
18+
def __init__(self):
19+
GenericEnumeration.__init__(self)
20+
21+
def getBanner(self):
22+
if not conf.getBanner:
23+
return
24+
25+
if kb.data.banner is None:
26+
infoMsg = "fetching banner"
27+
logger.info(infoMsg)
28+
29+
query = queries[DBMS.H2].banner.query
30+
kb.data.banner = unArrayizeValue(inject.getValue(query, safeCharEncode=True))
31+
32+
return kb.data.banner
33+
34+
def getPrivileges(self, *args):
35+
warnMsg = "on H2 it is not possible to enumerate the user privileges"
36+
logger.warn(warnMsg)
37+
38+
return {}
39+
40+
def getHostname(self):
41+
warnMsg = "on H2 it is not possible to enumerate the hostname"
42+
logger.warn(warnMsg)

0 commit comments

Comments
 (0)