Document search_path security with untrusted dbowner or CREATEROLE.
authorNoah Misch
Sun, 8 Dec 2019 19:06:26 +0000 (11:06 -0800)
committerNoah Misch
Sun, 8 Dec 2019 19:06:26 +0000 (11:06 -0800)
Commit 5770172cb0c9df9e6ce27c507b449557e5b45124 wrote, incorrectly, that
certain schema usage patterns are secure against CREATEROLE users and
database owners.  When an untrusted user is the database owner or holds
CREATEROLE privilege, a query is secure only if its session started with
SELECT pg_catalog.set_config('search_path', '', false) or equivalent.
Back-patch to 9.4 (all supported versions).

Discussion: https://postgr.es/m/20191013013512[email protected]

doc/src/sgml/ddl.sgml

index 0be0774748955392c0fd9ea5b5d2d54d91297471..3546e390a8f115bf5429db939775c5307025bfdb 100644 (file)
@@ -3010,56 +3010,57 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
    Usage Patterns
 
    
-    Schemas can be used to organize your data in many ways.  There are a few
-    usage patterns easily supported by the default configuration, only one of
-    which suffices when database users mistrust other database users:
+    Schemas can be used to organize your data in many ways.
+    A secure schema usage pattern prevents untrusted
+    users from changing the behavior of other users' queries.  When a database
+    does not use a secure schema usage pattern, users wishing to securely
+    query that database would take protective action at the beginning of each
+    session.  Specifically, they would begin each session by
+    setting search_path to the empty string or otherwise
+    removing non-superuser-writable schemas
+    from search_path.  There are a few usage patterns
+    easily supported by the default configuration:
     
      
       
+           doesn't preserve that DROP.
+
+           A database owner can attack the database's users via "CREATE SCHEMA
+           trojan; ALTER DATABASE $mydb SET search_path = trojan, public;".  A
+           CREATEROLE user can issue "GRANT $dbowner TO $me" and then use the
+           database owner attack. -->
       
        Constrain ordinary users to user-private schemas.  To implement this,
        issue REVOKE CREATE ON SCHEMA public FROM PUBLIC,
-       and create a schema for each user with the same name as that user.  If
-       affected users had logged in before this, consider auditing the public
+       and create a schema for each user with the same name as that user.
+       Recall that the default search path starts
+       with $user, which resolves to the user name.
+       Therefore, if each user has a separate schema, they access their own
+       schemas by default.  After adopting this pattern in a database where
+       untrusted users had already logged in, consider auditing the public
        schema for objects named like objects in
-       schema pg_catalog.  Recall that the default search
-       path starts with $user, which resolves to the user
-       name.  Therefore, if each user has a separate schema, they access their
-       own schemas by default.
+       schema pg_catalog.  This pattern is a secure schema
+       usage pattern unless an untrusted user is the database owner or holds
+       the CREATEROLE privilege, in which case no secure
+       schema usage pattern exists.
       
-     
-
-     
       
-       Remove the public schema from each user's default search path
-       using ALTER ROLE user SET
-       search_path = "$user".  Everyone retains the ability to
-       create objects in the public schema, but only qualified names will
-       choose those objects.  While qualified table references are fine, calls
-       to functions in the public schema will be
-       unsafe or unreliable.  Also, a user holding
-       the CREATEROLE privilege can undo this setting and
-       issue arbitrary queries under the identity of users relying on the
-       setting.  If you create functions or extensions in the public schema or
-       grant CREATEROLE to users not warranting this
-       almost-superuser ability, use the first pattern instead.
       
      
 
      
       
-       Remove the public schema from search_path in
-       postgresql.conf.
-       The ensuing user experience matches the previous pattern.  In addition
-       to that pattern's implications for functions
-       and CREATEROLE, this trusts database owners
-       like CREATEROLE.  If you create functions or
-       extensions in the public schema or assign
-       the CREATEROLE
-       privilege, CREATEDB privilege or individual database
-       ownership to users not warranting almost-superuser access, use the
-       first pattern instead.
+       Remove the public schema from the default search path, by modifying
+       postgresql.conf
+       or by issuing ALTER ROLE ALL SET search_path =
+       "$user".  Everyone retains the ability to create objects in
+       the public schema, but only qualified names will choose those objects.
+       While qualified table references are fine, calls to functions in the
+       public schema will be unsafe or
+       unreliable.  If you create functions or extensions in the public
+       schema, use the first pattern instead.  Otherwise, like the first
+       pattern, this is secure unless an untrusted user is the database owner
+       or holds the CREATEROLE privilege.
       
      
 
@@ -3067,10 +3068,9 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
       
        Keep the default.  All users access the public schema implicitly.  This
        simulates the situation where schemas are not available at all, giving
-       a smooth transition from the non-schema-aware world.  However, any user
-       can issue arbitrary queries under the identity of any user not electing
-       to protect itself individually.  This pattern is acceptable only when
-       the database has a single user or a few mutually-trusting users.
+       a smooth transition from the non-schema-aware world.  However, this is
+       never a secure pattern.  It is acceptable only when the database has a
+       single user or a few mutually-trusting users.