mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-28 20:57:20 +02: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:
parent
9a513f8f9e
commit
a117c7a7b6
@ -2380,9 +2380,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>
|
||||||
@ -2393,8 +2396,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
|
||||||
|
@ -545,8 +545,11 @@ CREATE [ OR REPLACE ] FUNCTION
|
|||||||
as for the <xref linkend="sql-load"/> command. The string
|
as for the <xref linkend="sql-load"/> command. The string
|
||||||
<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>
|
||||||
@ -575,10 +578,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>
|
||||||
|
@ -1518,6 +1518,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.
|
||||||
@ -2590,6 +2596,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</quote> error will result if no better match to the call can be
|
function call</quote> 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>
|
||||||
|
|
||||||
|
@ -764,8 +764,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</literal> 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]);
|
||||||
@ -827,7 +830,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>
|
||||||
@ -1399,11 +1405,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>
|
||||||
|
@ -10761,16 +10761,11 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
|
|||||||
* Determine whether VARIADIC should be printed. We must do this first
|
* Determine whether VARIADIC should be printed. We must do this first
|
||||||
* since it affects the lookup rules in func_get_detail().
|
* since it affects the lookup rules in func_get_detail().
|
||||||
*
|
*
|
||||||
* Currently, we always print VARIADIC if the function has a merged
|
* We always print VARIADIC if the function has a merged variadic-array
|
||||||
* variadic-array argument. Note that this is always the case for
|
* argument. Note that this is always the case for functions taking a
|
||||||
* functions taking a VARIADIC argument type other than VARIADIC ANY.
|
* VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
|
||||||
*
|
* and printed the array elements as separate arguments, the call could
|
||||||
* In principle, if VARIADIC wasn't originally specified and the array
|
* match a newer non-VARIADIC function.
|
||||||
* actual argument is deconstructable, we could print the array elements
|
|
||||||
* separately and not print VARIADIC, thus more nearly reproducing the
|
|
||||||
* original input. For the moment that seems like too much complication
|
|
||||||
* for the benefit, and anyway we do not know whether VARIADIC was
|
|
||||||
* originally specified if it's a non-ANY type.
|
|
||||||
*/
|
*/
|
||||||
if (use_variadic_p)
|
if (use_variadic_p)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user