Document security implications of qualified names.
Commit 5770172cb0c9df9e6ce27c507b449557e5b45124 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
|
||||
search_path = "$user"</literal>. Everyone retains the ability to
|
||||
create objects in the public schema, but only qualified names will
|
||||
choose those objects. 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
|
||||
choose those objects. While qualified table references are fine, calls
|
||||
to functions in the public schema <link linkend="typeconv-func">will be
|
||||
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
|
||||
almost-superuser ability, use the first pattern instead.
|
||||
</para>
|
||||
@ -2393,8 +2396,10 @@ REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
||||
Remove the public schema from <varname>search_path</varname> in
|
||||
<link linkend="config-setting-configuration-file"><filename>postgresql.conf</filename></link>.
|
||||
The ensuing user experience matches the previous pattern. In addition
|
||||
to that pattern's implications for <literal>CREATEROLE</literal>, this
|
||||
trusts database owners the same way. If you assign
|
||||
to that pattern's implications for functions
|
||||
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>
|
||||
privilege, <literal>CREATEDB</literal> privilege or individual database
|
||||
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
|
||||
<replaceable class="parameter">link_symbol</replaceable> is the
|
||||
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
|
||||
to be the same as the name of the SQL function being defined.
|
||||
language source code. If the link symbol is omitted, it is assumed to
|
||||
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>
|
||||
@ -575,10 +578,9 @@ CREATE [ OR REPLACE ] FUNCTION
|
||||
<productname>PostgreSQL</productname> allows function
|
||||
<firstterm>overloading</firstterm>; that is, the same name can be
|
||||
used for several different functions so long as they have distinct
|
||||
input argument types. However, 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).
|
||||
input argument types. Whether or not you use it, this capability entails
|
||||
security precautions when calling functions in databases where some users
|
||||
mistrust other users; see <xref linkend="typeconv-func"/>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1518,6 +1518,12 @@ sqrt(2)
|
||||
Other functions can be added by the user.
|
||||
</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>
|
||||
The arguments can optionally have names attached.
|
||||
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
|
||||
declaration. In named notation, the arguments are matched to the
|
||||
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>
|
||||
|
@ -246,7 +246,19 @@ search path position.
|
||||
<para>
|
||||
Check for an operator accepting exactly the input argument types.
|
||||
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>
|
||||
|
||||
<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
|
||||
preferred.
|
||||
</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 performance="optional">
|
||||
<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
|
||||
found.
|
||||
</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>
|
||||
</substeps>
|
||||
</step>
|
||||
@ -610,9 +651,12 @@ found.
|
||||
<para>
|
||||
Check for a function accepting exactly the input argument types.
|
||||
If one exists (there can be only one exact match in the set of
|
||||
functions considered), use it.
|
||||
(Cases involving <type>unknown</type> will never find a match at
|
||||
this step.)
|
||||
functions considered), use it. Lack of an exact match creates a security
|
||||
hazard when calling, via qualified
|
||||
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>
|
||||
</step>
|
||||
|
||||
@ -750,6 +794,57 @@ SELECT round(4.0, 4);
|
||||
</para>
|
||||
</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>
|
||||
<title>Substring Function Type Resolution</title>
|
||||
|
||||
|
@ -764,8 +764,11 @@ SELECT mleast(ARRAY[10, -1, 5, 4.4]); -- doesn't work
|
||||
<para>
|
||||
Sometimes it is useful to be able to pass an already-constructed array
|
||||
to a variadic function; this is particularly handy when one variadic
|
||||
function wants to pass on its array parameter to another one. You can
|
||||
do that by specifying <literal>VARIADIC</literal> in the call:
|
||||
function wants to pass on its array parameter to another one. Also,
|
||||
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>
|
||||
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
|
||||
default values as well. (Although the use of named argument notation
|
||||
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>
|
||||
@ -1399,11 +1405,14 @@ $$ LANGUAGE SQL;
|
||||
<para>
|
||||
More than one function can be defined with the same SQL name, so long
|
||||
as the arguments they take are different. In other words,
|
||||
function names can be <firstterm>overloaded</firstterm>. When a
|
||||
query is executed, the server 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.
|
||||
function names can be <firstterm>overloaded</firstterm>. Whether or not
|
||||
you use it, this capability entails security precautions when calling
|
||||
functions in databases where some users mistrust other users; see
|
||||
<xref linkend="typeconv-func"/>. When a query is executed, the server
|
||||
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>
|
||||
|
@ -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
|
||||
* since it affects the lookup rules in func_get_detail().
|
||||
*
|
||||
* Currently, we always print VARIADIC if the function has a merged
|
||||
* variadic-array argument. Note that this is always the case for
|
||||
* functions taking a VARIADIC argument type other than VARIADIC ANY.
|
||||
*
|
||||
* In principle, if VARIADIC wasn't originally specified and the array
|
||||
* 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.
|
||||
* We always print VARIADIC if the function has a merged variadic-array
|
||||
* argument. Note that this is always the case for functions taking a
|
||||
* VARIADIC argument type other than VARIADIC ANY. If we omitted VARIADIC
|
||||
* and printed the array elements as separate arguments, the call could
|
||||
* match a newer non-VARIADIC function.
|
||||
*/
|
||||
if (use_variadic_p)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user