Path: blob/master/plugins/dbms/oracle/enumeration.py
2992 views
#!/usr/bin/env python12"""3Copyright (c) 2006-2025 sqlmap developers (https://sqlmap.org)4See the file 'LICENSE' for copying permission5"""67from lib.core.common import getLimitRange8from lib.core.common import isAdminFromPrivileges9from lib.core.common import isInferenceAvailable10from lib.core.common import isNoneValue11from lib.core.common import isNumPosStrValue12from lib.core.common import isTechniqueAvailable13from lib.core.compat import xrange14from lib.core.data import conf15from lib.core.data import kb16from lib.core.data import logger17from lib.core.data import queries18from lib.core.enums import CHARSET_TYPE19from lib.core.enums import DBMS20from lib.core.enums import EXPECTED21from lib.core.enums import PAYLOAD22from lib.core.exception import SqlmapNoneDataException23from lib.core.settings import CURRENT_USER24from lib.request import inject25from plugins.generic.enumeration import Enumeration as GenericEnumeration2627class Enumeration(GenericEnumeration):28def getRoles(self, query2=False):29infoMsg = "fetching database users roles"3031rootQuery = queries[DBMS.ORACLE].roles3233if conf.user == CURRENT_USER:34infoMsg += " for current user"35conf.user = self.getCurrentUser()3637logger.info(infoMsg)3839# Set containing the list of DBMS administrators40areAdmins = set()4142if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:43if query2:44query = rootQuery.inband.query245condition = rootQuery.inband.condition246else:47query = rootQuery.inband.query48condition = rootQuery.inband.condition4950if conf.user:51users = conf.user.split(',')52query += " WHERE "53query += " OR ".join("%s = '%s'" % (condition, user) for user in sorted(users))5455values = inject.getValue(query, blind=False, time=False)5657if not values and not query2:58infoMsg = "trying with table 'USER_ROLE_PRIVS'"59logger.info(infoMsg)6061return self.getRoles(query2=True)6263if not isNoneValue(values):64for value in values:65user = None66roles = set()6768for count in xrange(0, len(value or [])):69# The first column is always the username70if count == 0:71user = value[count]7273# The other columns are the roles74else:75role = value[count]7677# In Oracle we get the list of roles as string78roles.add(role)7980if user in kb.data.cachedUsersRoles:81kb.data.cachedUsersRoles[user] = list(roles.union(kb.data.cachedUsersRoles[user]))82else:83kb.data.cachedUsersRoles[user] = list(roles)8485if not kb.data.cachedUsersRoles and isInferenceAvailable() and not conf.direct:86if conf.user:87users = conf.user.split(',')88else:89if not len(kb.data.cachedUsers):90users = self.getUsers()91else:92users = kb.data.cachedUsers9394retrievedUsers = set()9596for user in users:97unescapedUser = None9899if user in retrievedUsers:100continue101102infoMsg = "fetching number of roles "103infoMsg += "for user '%s'" % user104logger.info(infoMsg)105106if unescapedUser:107queryUser = unescapedUser108else:109queryUser = user110111if query2:112query = rootQuery.blind.count2 % queryUser113else:114query = rootQuery.blind.count % queryUser115count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)116117if not isNumPosStrValue(count):118if count != 0 and not query2:119infoMsg = "trying with table 'USER_SYS_PRIVS'"120logger.info(infoMsg)121122return self.getPrivileges(query2=True)123124warnMsg = "unable to retrieve the number of "125warnMsg += "roles for user '%s'" % user126logger.warning(warnMsg)127continue128129infoMsg = "fetching roles for user '%s'" % user130logger.info(infoMsg)131132roles = set()133134indexRange = getLimitRange(count, plusOne=True)135136for index in indexRange:137if query2:138query = rootQuery.blind.query2 % (queryUser, index)139else:140query = rootQuery.blind.query % (queryUser, index)141role = inject.getValue(query, union=False, error=False)142143# In Oracle we get the list of roles as string144roles.add(role)145146if roles:147kb.data.cachedUsersRoles[user] = list(roles)148else:149warnMsg = "unable to retrieve the roles "150warnMsg += "for user '%s'" % user151logger.warning(warnMsg)152153retrievedUsers.add(user)154155if not kb.data.cachedUsersRoles:156errMsg = "unable to retrieve the roles "157errMsg += "for the database users"158raise SqlmapNoneDataException(errMsg)159160for user, privileges in kb.data.cachedUsersRoles.items():161if isAdminFromPrivileges(privileges):162areAdmins.add(user)163164return kb.data.cachedUsersRoles, areAdmins165166167