You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sqlmap/src/sqlmap-master/plugins/dbms/oracle/enumeration.py

169 lines
7.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env python
"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
# 1. 导入必要的模块
from lib.core.common import getLimitRange # 获取限制范围
from lib.core.common import isAdminFromPrivileges # 判断是否为管理员
from lib.core.common import isInferenceAvailable # 判断是否可以使用推断注入
from lib.core.common import isNoneValue # 判断是否为 None 值
from lib.core.common import isNumPosStrValue # 判断是否为数字正字符串值
from lib.core.common import isTechniqueAvailable # 判断是否可以使用特定注入技术
from lib.core.compat import xrange # 兼容 Python 2 和 3 的 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 # SQL 查询语句
from lib.core.enums import CHARSET_TYPE # 字符集类型枚举
from lib.core.enums import DBMS # 数据库管理系统枚举
from lib.core.enums import EXPECTED # 预期返回类型枚举
from lib.core.enums import PAYLOAD # 注入类型枚举
from lib.core.exception import SqlmapNoneDataException # 没有数据异常
from lib.core.settings import CURRENT_USER # 当前用户
from lib.request import inject # 注入相关函数
from plugins.generic.enumeration import Enumeration as GenericEnumeration # 通用枚举类
# 2. 定义一个类 Enumeration继承自 GenericEnumeration
class Enumeration(GenericEnumeration):
# 3. 获取数据库用户角色
def getRoles(self, query2=False):
# 4. 输出获取数据库用户角色信息
infoMsg = "fetching database users roles"
# 5. 从查询集中获取角色查询语句
rootQuery = queries[DBMS.ORACLE].roles
# 6. 如果用户名为当前用户,则获取当前用户名
if conf.user == CURRENT_USER:
infoMsg += " for current user"
conf.user = self.getCurrentUser()
logger.info(infoMsg)
# 7. 存储管理员用户的集合
areAdmins = set()
# 8. 检查是否存在可用的注入技术或直接连接
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
# 9. 选择使用哪个查询语句
if query2:
query = rootQuery.inband.query2
condition = rootQuery.inband.condition2
else:
query = rootQuery.inband.query
condition = rootQuery.inband.condition
# 10. 如果指定了用户名,则添加到查询条件中
if conf.user:
users = conf.user.split(',')
query += " WHERE "
query += " OR ".join("%s = '%s'" % (condition, user) for user in sorted(users))
# 11. 执行查询语句,获取用户角色信息
values = inject.getValue(query, blind=False, time=False)
# 12. 如果没有获取到数据,尝试使用备用表 `USER_ROLE_PRIVS`
if not values and not query2:
infoMsg = "trying with table 'USER_ROLE_PRIVS'"
logger.info(infoMsg)
return self.getRoles(query2=True)
# 13. 处理获取到的用户角色信息
if not isNoneValue(values):
for value in values:
user = None
roles = set()
for count in xrange(0, len(value or [])):
# 14. 第一列为用户名
if count == 0:
user = value[count]
# 15. 其他列为角色
else:
role = value[count]
roles.add(role)
# 16. 将用户角色信息添加到缓存中
if user in kb.data.cachedUsersRoles:
kb.data.cachedUsersRoles[user] = list(roles.union(kb.data.cachedUsersRoles[user]))
else:
kb.data.cachedUsersRoles[user] = list(roles)
# 17. 如果没有获取到用户角色信息,尝试使用推断注入
if not kb.data.cachedUsersRoles and isInferenceAvailable() and not conf.direct:
# 18. 获取用户名列表
if conf.user:
users = conf.user.split(',')
else:
if not len(kb.data.cachedUsers):
users = self.getUsers()
else:
users = kb.data.cachedUsers
retrievedUsers = set()
# 19. 遍历用户列表,获取每个用户的角色信息
for user in users:
unescapedUser = None
if user in retrievedUsers:
continue
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
# 20. 获取每个用户的角色数量
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
# 21. 如果没有获取到角色数量,尝试使用备用表 `USER_SYS_PRIVS`
if not isNumPosStrValue(count):
if count != 0 and not query2:
infoMsg = "trying with table 'USER_SYS_PRIVS'"
logger.info(infoMsg)
return self.getPrivileges(query2=True)
warnMsg = "unable to retrieve the number of "
warnMsg += "roles for user '%s'" % user
logger.warning(warnMsg)
continue
infoMsg = "fetching roles for user '%s'" % user
logger.info(infoMsg)
roles = set()
indexRange = getLimitRange(count, plusOne=True)
# 22. 遍历角色索引,获取每个角色信息
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)
roles.add(role)
# 23. 将获取到的角色信息添加到缓存中
if roles:
kb.data.cachedUsersRoles[user] = list(roles)
else:
warnMsg = "unable to retrieve the roles "
warnMsg += "for user '%s'" % user
logger.warning(warnMsg)
retrievedUsers.add(user)
# 24. 如果没有获取到用户角色信息,抛出异常
if not kb.data.cachedUsersRoles:
errMsg = "unable to retrieve the roles "
errMsg += "for the database users"
raise SqlmapNoneDataException(errMsg)
# 25. 从角色信息中判断管理员用户
for user, privileges in kb.data.cachedUsersRoles.items():
if isAdminFromPrivileges(privileges):
areAdmins.add(user)
# 26. 返回用户角色信息和管理员用户
return kb.data.cachedUsersRoles, areAdmins