@@ -1907,67 +1907,67 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
1907
1907
<title>Usage Patterns</title>
1908
1908
1909
1909
<para>
1910
- Schemas can be used to organize your data in many ways. There are a few
1911
- usage patterns easily supported by the default configuration, only one of
1912
- which suffices when database users mistrust other database users:
1910
+ Schemas can be used to organize your data in many ways.
1911
+ A <firstterm>secure schema usage pattern</firstterm> prevents untrusted
1912
+ users from changing the behavior of other users' queries. When a database
1913
+ does not use a secure schema usage pattern, users wishing to securely
1914
+ query that database would take protective action at the beginning of each
1915
+ session. Specifically, they would begin each session by
1916
+ setting <varname>search_path</varname> to the empty string or otherwise
1917
+ removing non-superuser-writable schemas
1918
+ from <varname>search_path</varname>. There are a few usage patterns
1919
+ easily supported by the default configuration:
1913
1920
<itemizedlist>
1914
1921
<listitem>
1915
1922
<!-- "DROP SCHEMA public" is inferior to this REVOKE, because pg_dump
1916
- doesn't preserve that DROP. -->
1923
+ doesn't preserve that DROP.
1924
+
1925
+ A database owner can attack the database's users via "CREATE SCHEMA
1926
+ trojan; ALTER DATABASE $mydb SET search_path = trojan, public;". A
1927
+ CREATEROLE user can issue "GRANT $dbowner TO $me" and then use the
1928
+ database owner attack. -->
1917
1929
<para>
1918
1930
Constrain ordinary users to user-private schemas. To implement this,
1919
1931
issue <literal>REVOKE CREATE ON SCHEMA public FROM PUBLIC</literal>,
1920
- and create a schema for each user with the same name as that user. If
1921
- affected users had logged in before this, consider auditing the public
1932
+ and create a schema for each user with the same name as that user.
1933
+ Recall that the default search path starts
1934
+ with <literal>$user</literal>, which resolves to the user name.
1935
+ Therefore, if each user has a separate schema, they access their own
1936
+ schemas by default. After adopting this pattern in a database where
1937
+ untrusted users had already logged in, consider auditing the public
1922
1938
schema for objects named like objects in
1923
- schema <literal>pg_catalog</literal>. Recall that the default search
1924
- path starts with <literal>$user</literal>, which resolves to the user
1925
- name. Therefore, if each user has a separate schema, they access their
1926
- own schemas by default .
1939
+ schema <literal>pg_catalog</literal>. This pattern is a secure schema
1940
+ usage pattern unless an untrusted user is the database owner or holds
1941
+ the <literal>CREATEROLE</literal> privilege, in which case no secure
1942
+ schema usage pattern exists .
1927
1943
</para>
1928
- </listitem>
1929
-
1930
- <listitem>
1931
1944
<para>
1932
- Remove the public schema from each user's default search path
1933
- using <literal>ALTER ROLE <replaceable>user</replaceable> SET
1934
- search_path = "$user"</literal>. Everyone retains the ability to
1935
- create objects in the public schema, but only qualified names will
1936
- choose those objects. While qualified table references are fine, calls
1937
- to functions in the public schema <link linkend="typeconv-func">will be
1938
- unsafe or unreliable</link>. Also, a user holding
1939
- the <literal>CREATEROLE</literal> privilege can undo this setting and
1940
- issue arbitrary queries under the identity of users relying on the
1941
- setting. If you create functions or extensions in the public schema or
1942
- grant <literal>CREATEROLE</literal> to users not warranting this
1943
- almost-superuser ability, use the first pattern instead.
1944
1945
</para>
1945
1946
</listitem>
1946
1947
1947
1948
<listitem>
1948
1949
<para>
1949
- Remove the public schema from <varname>search_path</varname> in
1950
- <link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>.
1951
- The ensuing user experience matches the previous pattern. In addition
1952
- to that pattern's implications for functions
1953
- and <literal>CREATEROLE</literal>, this trusts database owners
1954
- like <literal>CREATEROLE</literal>. If you create functions or
1955
- extensions in the public schema or assign
1956
- the <literal>CREATEROLE</literal>
1957
- privilege, <literal>CREATEDB</literal> privilege or individual database
1958
- ownership to users not warranting almost-superuser access, use the
1959
- first pattern instead .
1950
+ Remove the public schema from the default search path, by modifying
1951
+ <link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>
1952
+ or by issuing <literal>ALTER ROLE ALL SET search_path =
1953
+ "$user"</literal>. Everyone retains the ability to create objects in
1954
+ the public schema, but only qualified names will choose those objects.
1955
+ While qualified table references are fine, calls to functions in the
1956
+ public schema <link linkend="typeconv-func">will be unsafe or
1957
+ unreliable</link>. If you create functions or extensions in the public
1958
+ schema, use the first pattern instead. Otherwise, like the first
1959
+ pattern, this is secure unless an untrusted user is the database owner
1960
+ or holds the <literal>CREATEROLE</literal> privilege .
1960
1961
</para>
1961
1962
</listitem>
1962
1963
1963
1964
<listitem>
1964
1965
<para>
1965
1966
Keep the default. All users access the public schema implicitly. This
1966
1967
simulates the situation where schemas are not available at all, giving
1967
- a smooth transition from the non-schema-aware world. However, any user
1968
- can issue arbitrary queries under the identity of any user not electing
1969
- to protect itself individually. This pattern is acceptable only when
1970
- the database has a single user or a few mutually-trusting users.
1968
+ a smooth transition from the non-schema-aware world. However, this is
1969
+ never a secure pattern. It is acceptable only when the database has a
1970
+ single user or a few mutually-trusting users.
1971
1971
</para>
1972
1972
</listitem>
1973
1973
</itemizedlist>
0 commit comments