令人惊讶的行为角色权限
简介
这*不是*关于安全漏洞。这里的所有问题都是已知的,并且在大多数情况下至少间接地记录在案。
这份文档是关于那些不直观且很难正确记录的行为,因此可能会给用户一种错误的安全感。
意外
用户无法控制使用其权限执行的代码。
对普通对象(如表和视图)的普通访问(例如 INSERT、SELECT)可以执行任意代码,并且没有实际的方法可以阻止这种情况,甚至不知道将执行什么代码。由对象所有者编写的代码将使用访问该对象的用户的权限执行。
唯一安全的做法是只访问您*绝对*信任的用户拥有的对象,例如超级用户或您角色的成员。如果对象所有者不是显式地您角色的成员,而您访问该对象,那么他们实际上就像您角色的成员一样。
实际上,这意味着我们的权限系统是分层的,但没有记录为这种方式。对象所有者使用 GRANT 分配细粒度的权限,访问这些对象的必须完全信任对象所有者。
函数作者不知道他们的函数会做什么。
PL/pgSQL 函数或使用 SPI 的任何函数都依赖于search_path
来查找甚至是最基本的函数和运算符,例如>
。因此,调用者可以轻松地操纵搜索路径,以便函数或运算符解析为另一个模式中相同名称的函数/运算符,该模式由调用者创建,并包含任意代码。
这会产生两个潜在问题
1. 对于SECURITY DEFINER
函数,最明显的问题是作者必须绝对控制函数的行为,因为它使用作者的权限执行。
2. 一个更微妙的问题是,当对象所有者依赖函数返回正确的结果时,例如在约束定义中。调用者可以操纵函数的行为,使其返回错误的结果并错误地通过约束检查,从而违反约束。
这些问题可以通过在函数定义中指定SET search_path
子句来解决。为了安全起见,任何可能被另一个用户直接或间接调用的函数都应该声明一个SET search_path
子句,但重要性没有被充分记录。此外,该行为是默认不安全的(函数具有公共 EXECUTE 权限,没有SET search_path
),并且一般来说,这种做法不被鼓励或广泛使用。
没有办法删除权限。
删除权限最直观的方法,SET SESSION AUTHORIZATION
和SET ROLE
,都可以在同一个会话中撤消。
技巧和特殊情况。
在某些情况下,权限更高的用户需要访问权限较低的用户拥有的对象。例如,表维护(例如 REINDEX)和逻辑复制。PostgreSQL 并没有普遍解决用户无法控制使用其权限执行什么代码的问题,而是简单地为维护命令开辟了特殊情况。这意味着超级用户对非特权用户拥有的表执行 REINDEX 是安全的,但在同一个表上执行 INSERT 或 SELECT 则非常危险。