我有一个关于Oracle和检查权限的问题。
一些背景信息
我写了一些php脚本,可以在我们的环境中‘测试’各种东西。其中一项任务是检查用户是否对过程具有execute权限,以及该过程是否有效/已编译。
下面是查询
select ao.object_name, utp.grantee, ao.status, utp.privilege
from all_objects ao, user_tab_privs utp
where utp.owner = ao.owner and
ao.object_name = utp.table_name and
upper( ao.object_name ) = :object_name and
ao.object_type = 'PACKAGE' and
utp.privilege = 'EXECUTE' and
ao.status = 'VALID'这很有效,并为我们节省了过程特权上的时间;我现在意识到,我还可以仔细检查all_tab_privs以检查执行访问权限。
问题所在
现在我的问题是,我如何对表做类似的事情?我们遇到了一个问题,某个用户在表上选择了privs,但没有更新/插入privs。如何逐个检查这些权限。我已经查看了all_tab_privs,但还没有找到它告诉我我想要什么。它有一些我可以执行的过程,但是当我检查一个已知表是否存在时,它就不存在了。
select * from all_tab_privs
where table_name = 'KNOWN_TABLE' and
grantee = 'CURRENT_USER'
and privilege in ( 'SELECT', 'UPDATE', 'INSERT' );但是,我知道我已经可以选择/插入/更新,而不是为一个表返回3行,它不返回任何内容。
有什么想法吗?谢谢。
免责声明
我知道我可以尝试插入/更新数据,然后删除它,但我不想这样做。我不想留下任何痕迹,因为这些脚本将定期运行,应该是可重复的,并且不应该改变任何数据片段的状态,即使它只是表上的一个序列。
此外,如果您能提供一个可能的查询‘列表’,我可以用来确定权限,这将是很好的。例如,要确定我是否拥有select访问权限,请运行查询1、2和3。如果其中任何一个返回数据,则选择privs,依此类推,用于插入/更新。
发布于 2013-05-28 23:47:14
我最终使用基于不同查询和它们返回的结果的多步骤方法解决了这个问题。我使用一些PHP代码来执行所有的查询,所以不需要100%地使用大型查询来解决所有问题。
此外,我们的数据库在物理上是分开的,它们通过数据库链接链接在一起,因此我必须做一些额外的工作,以确保此权限检查跨数据库链接有效。
目前,我只检查SELECT、DELETE、UPDATE和INSERT权限;这就是我现在真正需要的。
该过程
以下是坚果列表中的一般过程。
2a。使用数据库查询检查该表是否可见。
2b。如果该表可见,请检查是否有任何权限查询返回此用户有权访问该表。
查询
以下是上述每个步骤的查询。
1个数据库链接
select db_link from all_db_links2a表格可见性
select * from all_tables%DB_LINK% where table_name = :table_name and owner = :owner在适用的情况下,上面的%DB_LINK%将替换为@db_link。如果我们正在检查当前的连接,那么我会将其完全删除。请记住,查询是由PHP脚本执行的,因此我可以对字符串进行一些字符串操作,以便删除当前数据库的%DB_LINK%或将其替换为我们在步骤1中获得的数据库链接之一。
2b。用户、角色、表
这里总共有4个查询。
/*****/
/* 1 */
/*****/
select *
from user_tab_privs%DB_LINK%
where
owner = :owner
and
table_name = :table_name
and
privilege = :privilege
/*****/
/* 2 */
/*****/
select * from user_sys_privs%DB_LINK% where privilege = :privilege
/*****/
/* 3 */
/*****/
select * from
(
select distinct granted_role from
(
select null linker, granted_role
from user_role_privs%DB_LINK%
union all
select role linker, granted_role
from role_role_privs%DB_LINK%
)
start with linker is null
connect by prior granted_role = linker
) user_roles join role_tab_privs%DB_LINK% rtab on user_roles.granted_role = rtab.role
where
owner = :owner
and
table_name = :table_name
and
rtab.privilege = :privilege
/*****/
/* 4 */
/*****/
select * from
(
select distinct granted_role from
(
select null linker, granted_role
from user_role_privs%DB_LINK%
union all
select role linker, granted_role
from role_role_privs%DB_LINK%
)
start with linker is null
connect by prior granted_role = linker
) user_roles join role_sys_privs%DB_LINK% rtab on user_roles.granted_role = rtab.role
where rtab.privilege = :privilege解释
数据库链接
在phpunit测试中,我传入了两个参数:表名和模式名(所有者)。但是,由于数据库链接,我们必须在查询中使用@db_link显式检查其他数据库。否则,我可能会报告一个表是不可访问的,而实际上它可以通过数据库链接访问。
表可见性
如果用户看不到表,那么检查权限就没有意义了。检查权限还可以防止用户被授予'SELECT ANY TABLE‘权限,但该表本身并不实际存在,从而避免导致不必要的失败。
4个查询的范围
正如其他海报所示,用户可以通过多种方式访问表格。具体地说,他们可以被赋予角色,这些角色可以被赋予角色,然后这些角色可以被分配访问权限。或者可以通过系统特权向用户提供显式访问或一般访问。
查询1
四个查询中的第一个检查用户是否被赋予了对表的显式SELECT、DELETE等权限。它很容易理解,理想情况下这就是所有需要的东西
查询2
第二个检查是查看用户是否被授予了任何系统权限,比如DELETE any TABLE、SELECT ANY TABLE、INSERT ANY TABLE等。这些权限不是显式授予表的,但是用户可以在具有可见性的任何表上执行任何被引用的操作。
查询3
第三个查询将查看用户直接或间接拥有的任何角色是否被赋予了对表的显式SELECT、DELETE等权限。这与查询1类似,不同之处在于它基于分配给用户的角色,而不是用户。
查询4
第四个检查以查看用户直接或间接拥有的任何角色是否被赋予了任何系统权限,如删除任何表、选择任何表、插入任何表等。
就这样!我将它们链接在一起,并使用它们返回的结果来确定用户是否拥有所需的权限。
值得一提的是细节
如果一个用户在db_link_1上有任何特权,并不意味着他们对他们在db_link_2上访问的表有相同的特权,大多数人都应该知道这一点,但我想确保我明确地说明了这一点。例如,跨db_link_1的表1上的select privs并不意味着跨db_link_2的表2上的select privs。
我一次一个地检查每个db_link。所以首先我从我直接连接的数据库开始,这不需要数据库链接。然后,如果我找不到表,或者表上没有privs,我就会转到下一个数据库链接。
在查询2和4中,我使用“SELECT ANY TABLE”、“DELETE ANY TABLE”等来代替:privilege变量。
在查询1和3中,我使用了'SELECT','DELETE','UPDATE','INSERT‘来代替:特权变量。
发布于 2013-05-29 00:39:01
对我来说,这看起来相当乐观,因为角色问题可能会变得非常复杂,特别是如果角色有密码保护的话,而且如果没有真正尝试DML,我永远不会百分之百地信任这种方法。
尝试查询可能会更简单,例如:
select count(*)
from schema_name.table_name
where 1=0;
insert into schema_name.table_name
select *
from schema_name.table_name
where 1=0;
delete from schema_name.table_name
where 1=0;
update schema_name.table_name
set column_name = column_name
where 1=0;我相信,如果没有授予特权(没有现成的数据库可以检查),这样的查询将失败,并且它们永远不会修改任何数据。
顺便说一句,ANY特权通常被认为是一个安全问题,所以如果任何用户被授予了这些特权,那么您可能希望使系统失败。
发布于 2013-04-23 00:15:48
如果您拥有通过角色授予的权限,则需要进行更复杂的检查。comments中的链接提供了一些查询,用于查看更广泛的情况,但如果您想要查看当前用户可以看到的内容-正如您的一个查询所建议的那样-那么您可以查询session_roles视图,以查看除了直接授予的对象权限之外,当前通过角色可用于您的会话的对象权限:
select atp.table_schema, atp.table_name, atp.privilege, atp.grantee,
'Direct' as grant_type
from all_tab_privs atp
where atp.grantee = user
union all
select atp.table_schema, atp.table_name, atp.privilege, atp.grantee,
'Via role' as grant_type
from session_roles sr
join all_tab_privs atp on atp.grantee = sr.role;如果您想查看特定的对象或权限,显然可以添加筛选器,而grant_type伪列只是用于提供信息-并不是很有用,因为您可以将grantee与user进行比较,以获得相同的信息。
您可能还想查看session_privs,以检查您的用户是否拥有您期望的任何系统权限。
但是,如果您希望单个查询同时检查另一个用户或多个用户的权限,则需要更多类似于链接查询的内容,以及运行这些查询所需的权限。
https://stackoverflow.com/questions/16110197
复制相似问题