mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	Document security implications of qualified names.
Commit 5770172cb0 documented secure schema
usage, and that advice suffices for using unqualified names securely.
Document, in typeconv-func primarily, the additional issues that arise
with qualified names.  Back-patch to 9.3 (all supported versions).
Reviewed by Jonathan S. Katz.
Discussion: https://postgr.es/m/20180721012446.GA1840594@rfd.leadboat.com
			
			
This commit is contained in:
		| @@ -1937,9 +1937,12 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC; | |||||||
|        using <literal>ALTER ROLE <replaceable>user</replaceable> SET |        using <literal>ALTER ROLE <replaceable>user</replaceable> SET | ||||||
|        search_path = "$user"</literal>.  Everyone retains the ability to |        search_path = "$user"</literal>.  Everyone retains the ability to | ||||||
|        create objects in the public schema, but only qualified names will |        create objects in the public schema, but only qualified names will | ||||||
|        choose those objects.  A user holding the <literal>CREATEROLE</literal> |        choose those objects.  While qualified table references are fine, calls | ||||||
|        privilege can undo this setting and issue arbitrary queries under the |        to functions in the public schema <link linkend="typeconv-func">will be | ||||||
|        identity of users relying on the setting.  If you |        unsafe or unreliable</link>.  Also, a user holding | ||||||
|  |        the <literal>CREATEROLE</literal> 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 <literal>CREATEROLE</literal> to users not warranting this |        grant <literal>CREATEROLE</literal> to users not warranting this | ||||||
|        almost-superuser ability, use the first pattern instead. |        almost-superuser ability, use the first pattern instead. | ||||||
|       </para> |       </para> | ||||||
| @@ -1950,8 +1953,10 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC; | |||||||
|        Remove the public schema from <varname>search_path</varname> in |        Remove the public schema from <varname>search_path</varname> in | ||||||
|        <link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>. |        <link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>. | ||||||
|        The ensuing user experience matches the previous pattern.  In addition |        The ensuing user experience matches the previous pattern.  In addition | ||||||
|        to that pattern's implications for <literal>CREATEROLE</literal>, this |        to that pattern's implications for functions | ||||||
|        trusts database owners the same way.  If you assign |        and <literal>CREATEROLE</literal>, this trusts database owners | ||||||
|  |        like <literal>CREATEROLE</literal>.  If you create functions or | ||||||
|  |        extensions in the public schema or assign | ||||||
|        the <literal>CREATEROLE</literal> |        the <literal>CREATEROLE</literal> | ||||||
|        privilege, <literal>CREATEDB</literal> privilege or individual database |        privilege, <literal>CREATEDB</literal> privilege or individual database | ||||||
|        ownership to users not warranting almost-superuser access, use the |        ownership to users not warranting almost-superuser access, use the | ||||||
|   | |||||||
| @@ -480,8 +480,11 @@ CREATE [ OR REPLACE ] FUNCTION | |||||||
|        file containing the dynamically loadable object, and |        file containing the dynamically loadable object, and | ||||||
|        <replaceable class="parameter">link_symbol</replaceable> is the |        <replaceable class="parameter">link_symbol</replaceable> is the | ||||||
|        function's link symbol, that is, the name of the function in the C |        function's link symbol, that is, the name of the function in the C | ||||||
|        language source code.  If the link symbol is omitted, it is assumed |        language source code.  If the link symbol is omitted, it is assumed to | ||||||
|        to be the same as the name of the SQL function being defined. |        be the same as the name of the SQL function being defined.  The C names | ||||||
|  |        of all functions must be different, so you must give overloaded C | ||||||
|  |        functions different C names (for example, use the argument types as | ||||||
|  |        part of the C names). | ||||||
|       </para> |       </para> | ||||||
|  |  | ||||||
|       <para> |       <para> | ||||||
| @@ -545,10 +548,9 @@ CREATE [ OR REPLACE ] FUNCTION | |||||||
|     <productname>PostgreSQL</productname> allows function |     <productname>PostgreSQL</productname> allows function | ||||||
|     <firstterm>overloading</firstterm>; that is, the same name can be |     <firstterm>overloading</firstterm>; that is, the same name can be | ||||||
|     used for several different functions so long as they have distinct |     used for several different functions so long as they have distinct | ||||||
|     input argument types.  However, the C names of all functions must be |     input argument types.  Whether or not you use it, this capability entails | ||||||
|     different, so you must give overloaded C functions different C |     security precautions when calling functions in databases where some users | ||||||
|     names (for example, use the argument types as part of the C |     mistrust other users; see <xref linkend="typeconv-func">. | ||||||
|     names). |  | ||||||
|    </para> |    </para> | ||||||
|  |  | ||||||
|    <para> |    <para> | ||||||
|   | |||||||
| @@ -1528,6 +1528,12 @@ sqrt(2) | |||||||
|     Other functions can be added by the user. |     Other functions can be added by the user. | ||||||
|    </para> |    </para> | ||||||
|  |  | ||||||
|  |    <para> | ||||||
|  |     When issuing queries in a database where some users mistrust other users, | ||||||
|  |     observe security precautions from <xref linkend="typeconv-func"> when | ||||||
|  |     writing function calls. | ||||||
|  |    </para> | ||||||
|  |  | ||||||
|    <para> |    <para> | ||||||
|     The arguments can optionally have names attached. |     The arguments can optionally have names attached. | ||||||
|     See <xref linkend="sql-syntax-calling-funcs"> for details. |     See <xref linkend="sql-syntax-calling-funcs"> for details. | ||||||
| @@ -2409,6 +2415,8 @@ SELECT CASE WHEN min(employees) > 0 | |||||||
|     its argument values in the same order as they are defined in the function |     its argument values in the same order as they are defined in the function | ||||||
|     declaration.  In named notation, the arguments are matched to the |     declaration.  In named notation, the arguments are matched to the | ||||||
|     function parameters by name and can be written in any order. |     function parameters by name and can be written in any order. | ||||||
|  |     For each notation, also consider the effect of function argument types, | ||||||
|  |     documented in <xref linkend="typeconv-func">. | ||||||
|    </para> |    </para> | ||||||
|  |  | ||||||
|    <para> |    <para> | ||||||
|   | |||||||
| @@ -246,7 +246,19 @@ search path position. | |||||||
| <para> | <para> | ||||||
| Check for an operator accepting exactly the input argument types. | Check for an operator accepting exactly the input argument types. | ||||||
| If one exists (there can be only one exact match in the set of | If one exists (there can be only one exact match in the set of | ||||||
| operators considered), use it. | operators considered), use it.  Lack of an exact match creates a security | ||||||
|  | hazard when calling, via qualified name | ||||||
|  |   <footnote id="op-qualified-security"> | ||||||
|  |    <!-- If you edit this, consider editing func-qualified-security. --> | ||||||
|  |    <para> | ||||||
|  |     The hazard does not arise with a non-schema-qualified name, because a | ||||||
|  |     search path containing schemas that permit untrusted users to create | ||||||
|  |     objects is not a <link linkend="ddl-schemas-patterns">secure schema usage | ||||||
|  |     pattern</link>. | ||||||
|  |    </para> | ||||||
|  |   </footnote> | ||||||
|  | (not typical), any operator found in a schema that permits untrusted users to | ||||||
|  | create objects.  In such situations, cast arguments to force an exact match. | ||||||
| </para> | </para> | ||||||
|  |  | ||||||
| <substeps> | <substeps> | ||||||
| @@ -589,6 +601,26 @@ function.  In that case the function appearing earlier in the search path is | |||||||
| used, or if the two functions are in the same schema, the non-variadic one is | used, or if the two functions are in the same schema, the non-variadic one is | ||||||
| preferred. | preferred. | ||||||
| </para> | </para> | ||||||
|  | <para> | ||||||
|  | This creates a security hazard when calling, via qualified name | ||||||
|  |   <footnote id="func-qualified-security"> | ||||||
|  |    <!-- If you edit this, consider editing op-qualified-security. --> | ||||||
|  |    <para> | ||||||
|  |     The hazard does not arise with a non-schema-qualified name, because a | ||||||
|  |     search path containing schemas that permit untrusted users to create | ||||||
|  |     objects is not a <link linkend="ddl-schemas-patterns">secure schema usage | ||||||
|  |     pattern</link>. | ||||||
|  |    </para> | ||||||
|  |   </footnote>, | ||||||
|  | a variadic function found in a schema that permits untrusted users to create | ||||||
|  | objects.  A malicious user can take control and execute arbitrary SQL | ||||||
|  | functions as though you executed them.  Substitute a call bearing | ||||||
|  | the <literal>VARIADIC</literal> keyword, which bypasses this hazard.  Calls | ||||||
|  | populating <literal>VARIADIC "any"</literal> parameters often have no | ||||||
|  | equivalent formulation containing the <literal>VARIADIC</literal> keyword.  To | ||||||
|  | issue those calls safely, the function's schema must permit only trusted users | ||||||
|  | to create objects. | ||||||
|  | </para> | ||||||
| </step> | </step> | ||||||
| <step performance="optional"> | <step performance="optional"> | ||||||
| <para> | <para> | ||||||
| @@ -602,6 +634,15 @@ will not be able to determine which to prefer, and so an <quote>ambiguous | |||||||
| function call</> error will result if no better match to the call can be | function call</> error will result if no better match to the call can be | ||||||
| found. | found. | ||||||
| </para> | </para> | ||||||
|  | <para> | ||||||
|  | This creates an availability hazard when calling, via qualified | ||||||
|  | name<footnoteref linkend="func-qualified-security">, any function found in a | ||||||
|  | schema that permits untrusted users to create objects.  A malicious user can | ||||||
|  | create a function with the name of an existing function, replicating that | ||||||
|  | function's parameters and appending novel parameters having default values. | ||||||
|  | This precludes new calls to the original function.  To forestall this hazard, | ||||||
|  | place functions in schemas that permit only trusted users to create objects. | ||||||
|  | </para> | ||||||
| </step> | </step> | ||||||
| </substeps> | </substeps> | ||||||
| </step> | </step> | ||||||
| @@ -610,9 +651,12 @@ found. | |||||||
| <para> | <para> | ||||||
| Check for a function accepting exactly the input argument types. | Check for a function accepting exactly the input argument types. | ||||||
| If one exists (there can be only one exact match in the set of | If one exists (there can be only one exact match in the set of | ||||||
| functions considered), use it. | functions considered), use it.  Lack of an exact match creates a security | ||||||
| (Cases involving <type>unknown</type> will never find a match at | hazard when calling, via qualified | ||||||
| this step.) | name<footnoteref linkend="func-qualified-security">, a function found in a | ||||||
|  | schema that permits untrusted users to create objects.  In such situations, | ||||||
|  | cast arguments to force an exact match.  (Cases involving <type>unknown</type> | ||||||
|  | will never find a match at this step.) | ||||||
| </para> | </para> | ||||||
| </step> | </step> | ||||||
|  |  | ||||||
| @@ -750,6 +794,57 @@ SELECT round(4.0, 4); | |||||||
| </para> | </para> | ||||||
| </example> | </example> | ||||||
|  |  | ||||||
|  | <example> | ||||||
|  | <title>Variadic Function Resolution</title> | ||||||
|  |  | ||||||
|  | <para> | ||||||
|  | <screen> | ||||||
|  | CREATE FUNCTION public.variadic_example(VARIADIC numeric[]) RETURNS int | ||||||
|  |   LANGUAGE sql AS 'SELECT 1'; | ||||||
|  | CREATE FUNCTION | ||||||
|  | </screen> | ||||||
|  |  | ||||||
|  | This function accepts, but does not require, the VARIADIC keyword.  It | ||||||
|  | tolerates both integer and numeric arguments: | ||||||
|  |  | ||||||
|  | <screen> | ||||||
|  | SELECT public.variadic_example(0), | ||||||
|  |        public.variadic_example(0.0), | ||||||
|  |        public.variadic_example(VARIADIC array[0.0]); | ||||||
|  |  variadic_example | variadic_example | variadic_example | ||||||
|  | ------------------+------------------+------------------ | ||||||
|  |                 1 |                1 |                1 | ||||||
|  | (1 row) | ||||||
|  | </screen> | ||||||
|  |  | ||||||
|  | However, the first and second calls will prefer more-specific functions, if | ||||||
|  | available: | ||||||
|  |  | ||||||
|  | <screen> | ||||||
|  | CREATE FUNCTION public.variadic_example(numeric) RETURNS int | ||||||
|  |   LANGUAGE sql AS 'SELECT 2'; | ||||||
|  | CREATE FUNCTION | ||||||
|  |  | ||||||
|  | CREATE FUNCTION public.variadic_example(int) RETURNS int | ||||||
|  |   LANGUAGE sql AS 'SELECT 3'; | ||||||
|  | CREATE FUNCTION | ||||||
|  |  | ||||||
|  | SELECT public.variadic_example(0), | ||||||
|  |        public.variadic_example(0.0), | ||||||
|  |        public.variadic_example(VARIADIC array[0.0]); | ||||||
|  |  variadic_example | variadic_example | variadic_example | ||||||
|  | ------------------+------------------+------------------ | ||||||
|  |                 3 |                2 |                1 | ||||||
|  | (1 row) | ||||||
|  | </screen> | ||||||
|  |  | ||||||
|  | Given the default configuration and only the first function existing, the | ||||||
|  | first and second calls are insecure.  Any user could intercept them by | ||||||
|  | creating the second or third function.  By matching the argument type exactly | ||||||
|  | and using the <literal>VARIADIC</literal> keyword, the third call is secure. | ||||||
|  | </para> | ||||||
|  | </example> | ||||||
|  |  | ||||||
| <example> | <example> | ||||||
| <title>Substring Function Type Resolution</title> | <title>Substring Function Type Resolution</title> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -683,8 +683,11 @@ SELECT mleast(ARRAY[10, -1, 5, 4.4]);    -- doesn't work | |||||||
|     <para> |     <para> | ||||||
|      Sometimes it is useful to be able to pass an already-constructed array |      Sometimes it is useful to be able to pass an already-constructed array | ||||||
|      to a variadic function; this is particularly handy when one variadic |      to a variadic function; this is particularly handy when one variadic | ||||||
|      function wants to pass on its array parameter to another one.  You can |      function wants to pass on its array parameter to another one.  Also, | ||||||
|      do that by specifying <literal>VARIADIC</> in the call: |      this is the only secure way to call a variadic function found in a schema | ||||||
|  |      that permits untrusted users to create objects; see | ||||||
|  |      <xref linkend="typeconv-func">.  You can do this by | ||||||
|  |      specifying <literal>VARIADIC</literal> in the call: | ||||||
|  |  | ||||||
| <screen> | <screen> | ||||||
| SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]); | SELECT mleast(VARIADIC ARRAY[10, -1, 5, 4.4]); | ||||||
| @@ -746,7 +749,10 @@ SELECT mleast(arr := ARRAY[10, -1, 5, 4.4]); | |||||||
|      parameters after a parameter with a default value have to have |      parameters after a parameter with a default value have to have | ||||||
|      default values as well.  (Although the use of named argument notation |      default values as well.  (Although the use of named argument notation | ||||||
|      could allow this restriction to be relaxed, it's still enforced so that |      could allow this restriction to be relaxed, it's still enforced so that | ||||||
|      positional argument notation works sensibly.) |      positional argument notation works sensibly.)  Whether or not you use it, | ||||||
|  |      this capability creates a need for precautions when calling functions in | ||||||
|  |      databases where some users mistrust other users; see | ||||||
|  |      <xref linkend="typeconv-func">. | ||||||
|     </para> |     </para> | ||||||
|  |  | ||||||
|     <para> |     <para> | ||||||
| @@ -1222,11 +1228,14 @@ $$ LANGUAGE SQL; | |||||||
|    <para> |    <para> | ||||||
|     More than one function can be defined with the same SQL name, so long |     More than one function can be defined with the same SQL name, so long | ||||||
|     as the arguments they take are different.  In other words, |     as the arguments they take are different.  In other words, | ||||||
|     function names can be <firstterm>overloaded</firstterm>.  When a |     function names can be <firstterm>overloaded</firstterm>.  Whether or not | ||||||
|     query is executed, the server will determine which function to |     you use it, this capability entails security precautions when calling | ||||||
|     call from the data types and the number of the provided arguments. |     functions in databases where some users mistrust other users; see | ||||||
|     Overloading can also be used to simulate functions with a variable |     <xref linkend="typeconv-func">.  When a query is executed, the server | ||||||
|     number of arguments, up to a finite maximum number. |     will determine which function to call from the data types and the number | ||||||
|  |     of the provided arguments.  Overloading can also be used to simulate | ||||||
|  |     functions with a variable number of arguments, up to a finite maximum | ||||||
|  |     number. | ||||||
|    </para> |    </para> | ||||||
|  |  | ||||||
|    <para> |    <para> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user