Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1ibXs2-00037j-B3 for pgsql-docs@arkaria.postgresql.org; Sun, 01 Dec 2019 22:39:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1ibXrz-0005Jc-Am for pgsql-docs@arkaria.postgresql.org; Sun, 01 Dec 2019 22:39:11 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1ibXry-0005JU-Nr for pgsql-docs@lists.postgresql.org; Sun, 01 Dec 2019 22:39:11 +0000 Received: from mail-qk1-x744.google.com ([2607:f8b0:4864:20::744]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1ibXrr-0003a6-B6 for pgsql-docs@postgresql.org; Sun, 01 Dec 2019 22:39:09 +0000 Received: by mail-qk1-x744.google.com with SMTP id g15so2731348qka.8 for ; Sun, 01 Dec 2019 14:39:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; h=date:from:to:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=nGRtkwVosMuQx6nWWTQ1c7Y0oKsKyPzwufAwqoQmD+8=; b=LX3lDNuOhGpGIQO2qF2EE7HeldC1r5Aq31MWKry4Csp+h90PV8R4BgQY6OnwleN7nn tT4cfHWGLqald+uIDOBRuorOTnbfwuNewWOa4wwtPLl9DzDdp7d5q4/879djltjYPVBQ McP8fGEarp7pRxHK8efAOizECqE24JH1vKs08= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=nGRtkwVosMuQx6nWWTQ1c7Y0oKsKyPzwufAwqoQmD+8=; b=f92TTpxzNqqe17vKHpRzlVdOx1gSoUqe5U96menKQnnnMM/xkdUVhKVmiig95IjMAg ReDC6mXPIkaBI/QgD3mAdn6Mtisux67Iz9tTa/Rue0OQwjG8EpKSfAXYD9hW/gdge+T5 LHv4Qy1t2Y8GZd55xxWFw9EzuB3eri/yLmY6pDBAo6HU9WZWdKrdM1GUjuy64u2nd4Tl 7io9IOAlHymPvmoXXV/erYIn+NDdhELxOosTlMQP74CBSKuf33os3ZWrHEYYW8AUlsyw nTin7GOyyBQ7Rl+dhgwabpakjJUulUpdiZQGyHzfjU6ILL4Y3Kd1CdcYieZzeqm+mlvT 8yrw== X-Gm-Message-State: APjAAAUOjVBd2e97/yX05TlAcwvhQjd6lZPByoSebHlk16JrzY3F0GZP ldsRYZ4kY0kSyNznGA4yjSPa1NSorss= X-Google-Smtp-Source: APXvYqzibfPtrXiPH+JqdQl93Kb1bgzkFyMovvO6OIEmcnPGPjIpISzengpX/sHozA08KJs369F44g== X-Received: by 2002:ae9:f442:: with SMTP id z2mr29761358qkl.130.1575239941937; Sun, 01 Dec 2019 14:39:01 -0800 (PST) Received: from gust.leadboat.com ([184.169.45.4]) by smtp.gmail.com with ESMTPSA id z7sm15834775qth.85.2019.12.01.14.38.57 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 01 Dec 2019 14:39:01 -0800 (PST) Date: Sun, 1 Dec 2019 17:38:49 -0500 From: Noah Misch To: pgsql-docs@postgresql.org Subject: Re: Schema Usage Patterns vs. dbowner or CREATEROLE Message-ID: <20191201223849.GA117647@gust.leadboat.com> References: <20191013013512.GC4131753@rfd.leadboat.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="qMm9M+Fa2AknHoGS" Content-Disposition: inline In-Reply-To: <20191013013512.GC4131753@rfd.leadboat.com> User-Agent: Mutt/1.5.24 (2015-08-30) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sat, Oct 12, 2019 at 06:35:12PM -0700, Noah Misch wrote: > When I updated > https://www.postgresql.org/docs/devel/ddl-schemas.html#DDL-SCHEMAS-PATTERNS > for CVE-2018-1058, I wrote that some schema usage patterns are secure against > CREATEROLE users and database owners. That was incorrect. Even with the > first pattern, 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. I plan to update this section to assert that all three usage > patterns are equally vulnerable to dbowner and CREATEROLE attack. (The > technique described under "If untrusted users have access to a database ..." > in libpq.sgml remains secure.) I'm attaching a patch for that. Two of the patterns became so similar that I merged them. --qMm9M+Fa2AknHoGS Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="dbowner-schema-security-doc-v1.patch" diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 0be0774..3546e39 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -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. --qMm9M+Fa2AknHoGS--