pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
由于PostgreSQL规则系统会重写查询,因此可能访问原始查询中并未使用的其他表或视图。使用更新规则时,这甚至可能包括对表的写访问。
重写规则没有单独的所有者。关系(表或视图)的所有者会自动成为为其定义的重写规则的所有者。PostgreSQL规则系统改变了默认访问控制系统的行为。由于规则而使用的关系都会根据规则所有者的权限进行检查,而不是调用规则的用户。这意味着用户只需要对其查询中明确命名的表/视图具有所需的权限。
例如,某个用户有一份电话号码列表,其中一部分是私人的,另一部分对办公室秘书有用。该用户可以这样构造:
CREATE TABLE phone_data (person text, phone text, private boolean);
CREATE VIEW phone_number AS
SELECT person, CASE WHEN NOT private THEN phone END AS phone
FROM phone_data;
GRANT SELECT ON phone_number TO assistant;
除了该用户本人(以及数据库超级用户)之外,没有人可以访问phone_data表。但由于GRANT的存在,秘书可以对phone_number视图执行SELECT。规则系统会把对phone_number的SELECT重写成对phone_data的SELECT。由于该用户是phone_number的所有者,因此也是规则的所有者,对phone_data的读访问会按照该用户的权限进行检查,于是查询被允许。同时,对phone_number本身的访问检查仍会执行,但这是针对调用用户进行的,因此除了用户本人和秘书之外,没有其他人能使用它。
权限是逐条规则检查的。因此,目前秘书是唯一能看到公开电话号码的人。但秘书还可以再建立一个视图,并把该视图授予公众访问。这样,任何人都可以通过秘书的视图看到phone_number中的数据。秘书做不到的是创建一个直接访问phone_data的视图。(其实秘书可以创建,但它不会起作用,因为每次访问都会在权限检查时被拒绝。)而且,一旦用户发现秘书开放了其phone_number视图,用户就可以撤销秘书的访问权限。那样一来,对秘书视图的任何访问都会立即失败。
这种逐条规则的检查看起来似乎像是一个安全漏洞,但实际上并不是。因为即使不这样工作,秘书也可以建立一个与phone_number具有相同列的表,每天把数据复制进去。那样一来,这些就是秘书自己的数据,秘书同样可以把访问权限授予任何人。GRANT的含义本来就是“我信任你”。如果某个你信任的人做了上面的事,那么该重新考虑这份信任,并使用REVOKE了。
需要注意的是,虽然视图可以用上面展示的技术来隐藏某些列的内容,但它们不能被用来可靠地隐藏不可见行中的数据。例如,下面这个视图是不安全的:
CREATE VIEW phone_number AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
This view might seem secure, since the rule system will rewrite any SELECT from phone_number into a SELECT from phone_data and add the qualification that only entries where phone does not begin with 412 are wanted. But if the user can create his or her own functions, it is not difficult to convince the planner to execute the user-defined function prior to the NOT LIKE expression. For example:
CREATE FUNCTION tricky(text, text) RETURNS bool AS $$
BEGIN
RAISE NOTICE '% => %', $1, $2;
RETURN true;
END
$$ LANGUAGE plpgsql COST 0.0000000000000000000001;
SELECT * FROM phone_number WHERE tricky(person, phone);
Every person and phone number in the phone_data table will be printed as a NOTICE, because the planner will choose to execute the inexpensive tricky function before the more expensive NOT LIKE. Even if the user is prevented from defining new functions, built-in functions can be used in similar attacks. (For example, most casting functions include their input values in the error messages they produce.)
类似的考虑也适用于更新规则。在上一节的示例中,示例数据库中那些表的所有者可以把shoelace视图上的SELECT、INSERT、UPDATE和DELETE权限授予其他用户,但对shoelace_log只授予SELECT权限。写日志记录的规则动作仍会成功执行,因此其他用户可以看到日志记录。但他们不能伪造记录,也不能操纵或删除已有记录。在这个例子里,不存在通过说服规划器改变操作顺序来破坏规则的可能性,因为唯一引用shoelace_log的规则是一条无条件的INSERT。在更复杂的场景中,情况未必如此。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。