Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/plugins/dbms/maxdb/enumeration.py
2992 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
import re
9
10
from lib.core.common import isListLike
11
from lib.core.common import isTechniqueAvailable
12
from lib.core.common import readInput
13
from lib.core.common import safeSQLIdentificatorNaming
14
from lib.core.common import unsafeSQLIdentificatorNaming
15
from lib.core.data import conf
16
from lib.core.data import kb
17
from lib.core.data import logger
18
from lib.core.data import paths
19
from lib.core.data import queries
20
from lib.core.enums import DBMS
21
from lib.core.enums import PAYLOAD
22
from lib.core.exception import SqlmapMissingMandatoryOptionException
23
from lib.core.exception import SqlmapNoneDataException
24
from lib.core.exception import SqlmapUserQuitException
25
from lib.core.settings import CURRENT_DB
26
from lib.utils.brute import columnExists
27
from lib.utils.pivotdumptable import pivotDumpTable
28
from plugins.generic.enumeration import Enumeration as GenericEnumeration
29
from thirdparty import six
30
from thirdparty.six.moves import zip as _zip
31
32
class Enumeration(GenericEnumeration):
33
def __init__(self):
34
GenericEnumeration.__init__(self)
35
36
kb.data.processChar = lambda x: x.replace('_', ' ') if x else x
37
38
def getPasswordHashes(self):
39
warnMsg = "on SAP MaxDB it is not possible to enumerate the user password hashes"
40
logger.warning(warnMsg)
41
42
return {}
43
44
def getDbs(self):
45
if len(kb.data.cachedDbs) > 0:
46
return kb.data.cachedDbs
47
48
infoMsg = "fetching database names"
49
logger.info(infoMsg)
50
51
rootQuery = queries[DBMS.MAXDB].dbs
52
query = rootQuery.inband.query
53
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.schemaname' % kb.aliasName], blind=True)
54
55
if retVal:
56
kb.data.cachedDbs = next(six.itervalues(retVal[0]))
57
58
if kb.data.cachedDbs:
59
kb.data.cachedDbs.sort()
60
61
return kb.data.cachedDbs
62
63
def getTables(self, bruteForce=None):
64
if len(kb.data.cachedTables) > 0:
65
return kb.data.cachedTables
66
67
self.forceDbmsEnum()
68
69
if conf.db == CURRENT_DB:
70
conf.db = self.getCurrentDb()
71
72
if conf.db:
73
dbs = conf.db.split(',')
74
else:
75
dbs = self.getDbs()
76
77
for db in (_ for _ in dbs if _):
78
dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db)
79
80
infoMsg = "fetching tables for database"
81
infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, six.string_types) else db[0] for db in sorted(dbs)))
82
logger.info(infoMsg)
83
84
rootQuery = queries[DBMS.MAXDB].tables
85
86
for db in dbs:
87
query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER')
88
blind = not isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION)
89
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.tablename' % kb.aliasName], blind=blind)
90
91
if retVal:
92
for table in list(retVal[0].values())[0]:
93
if db not in kb.data.cachedTables:
94
kb.data.cachedTables[db] = [table]
95
else:
96
kb.data.cachedTables[db].append(table)
97
98
for db, tables in kb.data.cachedTables.items():
99
kb.data.cachedTables[db] = sorted(tables) if tables else tables
100
101
return kb.data.cachedTables
102
103
def getColumns(self, onlyColNames=False, colTuple=None, bruteForce=None, dumpMode=False):
104
self.forceDbmsEnum()
105
106
if conf.db is None or conf.db == CURRENT_DB:
107
if conf.db is None:
108
warnMsg = "missing database parameter. sqlmap is going "
109
warnMsg += "to use the current database to enumerate "
110
warnMsg += "table(s) columns"
111
logger.warning(warnMsg)
112
113
conf.db = self.getCurrentDb()
114
115
elif conf.db is not None:
116
if ',' in conf.db:
117
errMsg = "only one database name is allowed when enumerating "
118
errMsg += "the tables' columns"
119
raise SqlmapMissingMandatoryOptionException(errMsg)
120
121
conf.db = safeSQLIdentificatorNaming(conf.db)
122
123
if conf.col:
124
colList = conf.col.split(',')
125
else:
126
colList = []
127
128
if conf.exclude:
129
colList = [_ for _ in colList if re.search(conf.exclude, _, re.I) is None]
130
131
for col in colList:
132
colList[colList.index(col)] = safeSQLIdentificatorNaming(col)
133
134
if conf.tbl:
135
tblList = conf.tbl.split(',')
136
else:
137
self.getTables()
138
139
if len(kb.data.cachedTables) > 0:
140
tblList = list(kb.data.cachedTables.values())
141
142
if tblList and isListLike(tblList[0]):
143
tblList = tblList[0]
144
else:
145
errMsg = "unable to retrieve the tables "
146
errMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
147
raise SqlmapNoneDataException(errMsg)
148
149
for tbl in tblList:
150
tblList[tblList.index(tbl)] = safeSQLIdentificatorNaming(tbl, True)
151
152
if bruteForce:
153
resumeAvailable = False
154
155
for tbl in tblList:
156
for db, table, colName, colType in kb.brute.columns:
157
if db == conf.db and table == tbl:
158
resumeAvailable = True
159
break
160
161
if resumeAvailable and not conf.freshQueries or colList:
162
columns = {}
163
164
for column in colList:
165
columns[column] = None
166
167
for tbl in tblList:
168
for db, table, colName, colType in kb.brute.columns:
169
if db == conf.db and table == tbl:
170
columns[colName] = colType
171
172
if conf.db in kb.data.cachedColumns:
173
kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)][safeSQLIdentificatorNaming(tbl, True)] = columns
174
else:
175
kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] = {safeSQLIdentificatorNaming(tbl, True): columns}
176
177
return kb.data.cachedColumns
178
179
message = "do you want to use common column existence check? [y/N/q] "
180
choice = readInput(message, default='Y' if 'Y' in message else 'N').upper()
181
182
if choice == 'N':
183
return
184
elif choice == 'Q':
185
raise SqlmapUserQuitException
186
else:
187
return columnExists(paths.COMMON_COLUMNS)
188
189
rootQuery = queries[DBMS.MAXDB].columns
190
191
for tbl in tblList:
192
if conf.db is not None and len(kb.data.cachedColumns) > 0 and conf.db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[conf.db]:
193
infoMsg = "fetched tables' columns on "
194
infoMsg += "database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
195
logger.info(infoMsg)
196
197
return {conf.db: kb.data.cachedColumns[conf.db]}
198
199
if dumpMode and colList:
200
table = {}
201
table[safeSQLIdentificatorNaming(tbl, True)] = dict((_, None) for _ in colList)
202
kb.data.cachedColumns[safeSQLIdentificatorNaming(conf.db)] = table
203
continue
204
205
infoMsg = "fetching columns "
206
infoMsg += "for table '%s' " % unsafeSQLIdentificatorNaming(tbl)
207
infoMsg += "on database '%s'" % unsafeSQLIdentificatorNaming(conf.db)
208
logger.info(infoMsg)
209
210
blind = not isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION)
211
212
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), ("'%s'" % unsafeSQLIdentificatorNaming(conf.db)) if unsafeSQLIdentificatorNaming(conf.db) != "USER" else 'USER')
213
retVal = pivotDumpTable("(%s) AS %s" % (query, kb.aliasName), ['%s.columnname' % kb.aliasName, '%s.datatype' % kb.aliasName, '%s.len' % kb.aliasName], blind=blind)
214
215
if retVal:
216
table = {}
217
columns = {}
218
219
for columnname, datatype, length in _zip(retVal[0]["%s.columnname" % kb.aliasName], retVal[0]["%s.datatype" % kb.aliasName], retVal[0]["%s.len" % kb.aliasName]):
220
columns[safeSQLIdentificatorNaming(columnname)] = "%s(%s)" % (datatype, length)
221
222
table[tbl] = columns
223
kb.data.cachedColumns[conf.db] = table
224
225
return kb.data.cachedColumns
226
227
def getPrivileges(self, *args, **kwargs):
228
warnMsg = "on SAP MaxDB it is not possible to enumerate the user privileges"
229
logger.warning(warnMsg)
230
231
return {}
232
233
def search(self):
234
warnMsg = "on SAP MaxDB search option is not available"
235
logger.warning(warnMsg)
236
237
def getHostname(self):
238
warnMsg = "on SAP MaxDB it is not possible to enumerate the hostname"
239
logger.warning(warnMsg)
240
241
def getStatements(self):
242
warnMsg = "on SAP MaxDB it is not possible to enumerate the SQL statements"
243
logger.warning(warnMsg)
244
245
return []
246
247