sqlmap/plugins/dbms/oracle/enumeration.py

166 lines
5.9 KiB
Python
Raw Normal View History

2019-05-08 13:47:52 +03:00
#!/usr/bin/env python
"""
2020-12-31 13:46:27 +03:00
Copyright (c) 2006-2021 sqlmap developers (http://sqlmap.org/)
2017-10-11 15:50:46 +03:00
See the file 'LICENSE' for copying permission
"""
2012-02-16 18:42:28 +04:00
from lib.core.common import getLimitRange
2012-10-25 00:59:46 +04:00
from lib.core.common import isAdminFromPrivileges
from lib.core.common import isInferenceAvailable
from lib.core.common import isNoneValue
2010-12-18 00:45:20 +03:00
from lib.core.common import isNumPosStrValue
from lib.core.common import isTechniqueAvailable
2019-03-28 18:04:38 +03:00
from lib.core.compat import xrange
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.enums import CHARSET_TYPE
2016-12-21 12:33:35 +03:00
from lib.core.enums import DBMS
2010-12-10 16:04:36 +03:00
from lib.core.enums import EXPECTED
2011-01-15 13:14:05 +03:00
from lib.core.enums import PAYLOAD
from lib.core.exception import SqlmapNoneDataException
2019-08-30 15:43:56 +03:00
from lib.core.settings import CURRENT_USER
from lib.request import inject
from plugins.generic.enumeration import Enumeration as GenericEnumeration
class Enumeration(GenericEnumeration):
def getRoles(self, query2=False):
infoMsg = "fetching database users roles"
2016-12-21 12:33:35 +03:00
rootQuery = queries[DBMS.ORACLE].roles
2019-08-30 15:43:56 +03:00
if conf.user == CURRENT_USER:
infoMsg += " for current user"
conf.user = self.getCurrentUser()
logger.info(infoMsg)
# Set containing the list of DBMS administrators
areAdmins = set()
2012-12-05 13:45:17 +04:00
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
if query2:
2011-04-30 17:20:05 +04:00
query = rootQuery.inband.query2
condition = rootQuery.inband.condition2
else:
2011-04-30 17:20:05 +04:00
query = rootQuery.inband.query
condition = rootQuery.inband.condition
if conf.user:
2017-04-18 16:56:24 +03:00
users = conf.user.split(',')
query += " WHERE "
query += " OR ".join("%s = '%s'" % (condition, user) for user in sorted(users))
values = inject.getValue(query, blind=False, time=False)
if not values and not query2:
2019-08-30 15:43:56 +03:00
infoMsg = "trying with table 'USER_ROLE_PRIVS'"
logger.info(infoMsg)
return self.getRoles(query2=True)
if not isNoneValue(values):
for value in values:
2011-04-30 17:20:05 +04:00
user = None
roles = set()
2017-07-05 12:31:42 +03:00
for count in xrange(0, len(value or [])):
# The first column is always the username
if count == 0:
user = value[count]
# The other columns are the roles
else:
role = value[count]
# In Oracle we get the list of roles as string
roles.add(role)
if user in kb.data.cachedUsersRoles:
kb.data.cachedUsersRoles[user] = list(roles.union(kb.data.cachedUsersRoles[user]))
else:
kb.data.cachedUsersRoles[user] = list(roles)
if not kb.data.cachedUsersRoles and isInferenceAvailable() and not conf.direct:
if conf.user:
2017-04-18 16:56:24 +03:00
users = conf.user.split(',')
else:
if not len(kb.data.cachedUsers):
users = self.getUsers()
else:
users = kb.data.cachedUsers
retrievedUsers = set()
for user in users:
unescapedUser = None
if user in retrievedUsers:
continue
2011-04-30 17:20:05 +04:00
infoMsg = "fetching number of roles "
infoMsg += "for user '%s'" % user
logger.info(infoMsg)
if unescapedUser:
queryUser = unescapedUser
else:
queryUser = user
if query2:
query = rootQuery.blind.count2 % queryUser
else:
query = rootQuery.blind.count % queryUser
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
2010-12-18 00:45:20 +03:00
if not isNumPosStrValue(count):
if count != 0 and not query2:
2019-08-30 15:43:56 +03:00
infoMsg = "trying with table 'USER_SYS_PRIVS'"
logger.info(infoMsg)
return self.getPrivileges(query2=True)
2011-04-30 17:20:05 +04:00
warnMsg = "unable to retrieve the number of "
warnMsg += "roles for user '%s'" % user
logger.warn(warnMsg)
continue
infoMsg = "fetching roles for user '%s'" % user
logger.info(infoMsg)
roles = set()
2012-02-16 18:42:28 +04:00
indexRange = getLimitRange(count, plusOne=True)
for index in indexRange:
if query2:
query = rootQuery.blind.query2 % (queryUser, index)
else:
query = rootQuery.blind.query % (queryUser, index)
role = inject.getValue(query, union=False, error=False)
# In Oracle we get the list of roles as string
roles.add(role)
if roles:
kb.data.cachedUsersRoles[user] = list(roles)
else:
2011-04-30 17:20:05 +04:00
warnMsg = "unable to retrieve the roles "
warnMsg += "for user '%s'" % user
logger.warn(warnMsg)
retrievedUsers.add(user)
if not kb.data.cachedUsersRoles:
2011-04-30 17:20:05 +04:00
errMsg = "unable to retrieve the roles "
errMsg += "for the database users"
raise SqlmapNoneDataException(errMsg)
for user, privileges in kb.data.cachedUsersRoles.items():
if isAdminFromPrivileges(privileges):
areAdmins.add(user)
return kb.data.cachedUsersRoles, areAdmins