diff options
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/earthdistance.sgml | 27 | ||||
-rw-r--r-- | doc/src/sgml/extend.sgml | 203 | ||||
-rw-r--r-- | doc/src/sgml/hstore.sgml | 12 | ||||
-rw-r--r-- | doc/src/sgml/ltree.sgml | 9 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_extension.sgml | 37 |
5 files changed, 241 insertions, 47 deletions
diff --git a/doc/src/sgml/earthdistance.sgml b/doc/src/sgml/earthdistance.sgml index 4ac52cb191c..641e69c5e98 100644 --- a/doc/src/sgml/earthdistance.sgml +++ b/doc/src/sgml/earthdistance.sgml @@ -10,9 +10,8 @@ <para> The <filename>earthdistance</filename> module provides two different approaches to calculating great circle distances on the surface of the Earth. The one - described first depends on the <filename>cube</filename> module (which - <emphasis>must</emphasis> be installed before <filename>earthdistance</filename> can be - installed). The second one is based on the built-in <type>point</type> data type, + described first depends on the <filename>cube</filename> module. + The second one is based on the built-in <type>point</type> data type, using longitude and latitude for the coordinates. </para> @@ -24,11 +23,27 @@ </para> <para> - This module is considered <quote>trusted</quote>, that is, it can be - installed by non-superusers who have <literal>CREATE</literal> privilege - on the current database. + The <filename>cube</filename> module must be installed + before <filename>earthdistance</filename> can be installed + (although you can use the <literal>CASCADE</literal> option + of <command>CREATE EXTENSION</command> to install both in one command). </para> + <caution> + <para> + It is strongly recommended that <filename>earthdistance</filename> + and <filename>cube</filename> be installed in the same schema, and that + that schema be one for which CREATE privilege has not been and will not + be granted to any untrusted users. + Otherwise there are installation-time security hazards + if <filename>earthdistance</filename>'s schema contains objects defined + by a hostile user. + Furthermore, when using <filename>earthdistance</filename>'s functions + after installation, the entire search path should contain only trusted + schemas. + </para> + </caution> + <sect2> <title>Cube-Based Earth Distances</title> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index 890ff97b7ae..641c9ce3c9b 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -540,7 +540,7 @@ RETURNS anycompatible AS ... <para> The extension script may set privileges on objects that are part of the - extension via <command>GRANT</command> and <command>REVOKE</command> + extension, using <command>GRANT</command> and <command>REVOKE</command> statements. The final set of privileges for each object (if any are set) will be stored in the <link linkend="catalog-pg-init-privs"><structname>pg_init_privs</structname></link> @@ -597,32 +597,6 @@ RETURNS anycompatible AS ... dropping the whole extension. </para> - <sect2 id="extend-extensions-style"> - <title>Defining Extension Objects</title> - - <!-- XXX It's not enough to use qualified names, because one might write a - qualified name to an object that itself uses unqualified names. Many - information_schema functions have that defect, for example. However, - that's a defect in the referenced object, and relatively few queries - will be affected. Also, we direct applications to secure search_path - when connecting to an untrusted database; if applications do that, - they are immune to known attacks even if some extension refers to a - defective object. Therefore, guide extension authors as though core - PostgreSQL contained no such defect. --> - <para> - Widely-distributed extensions should assume little about the database - they occupy. In particular, unless you issued <literal>SET search_path = - pg_temp</literal>, assume each unqualified name could resolve to an - object that a malicious user has defined. Beware of constructs that - depend on <varname>search_path</varname> implicitly: <token>IN</token> - and <literal>CASE <replaceable>expression</replaceable> WHEN</literal> - always select an operator using the search path. In their place, use - <literal>OPERATOR(<replaceable>schema</replaceable>.=) ANY</literal> - and <literal>CASE WHEN <replaceable>expression</replaceable></literal>. - </para> - - </sect2> - <sect2> <title>Extension Files</title> @@ -740,7 +714,8 @@ RETURNS anycompatible AS ... <para> If this parameter is <literal>true</literal> (which is the default), only superusers can create the extension or update it to a new - version. If it is set to <literal>false</literal>, just the privileges + version (but see also <varname>trusted</varname>, below). + If it is set to <literal>false</literal>, just the privileges required to execute the commands in the installation or update script are required. This should normally be set to <literal>true</literal> if any of the @@ -768,6 +743,9 @@ RETURNS anycompatible AS ... Generally, this should not be set true for extensions that could allow access to otherwise-superuser-only abilities, such as file system access. + Also, marking an extension trusted requires significant extra effort + to write the extension's installation and update script(s) securely; + see <xref linkend="extend-extensions-security"/>. </para> </listitem> </varlistentry> @@ -921,7 +899,7 @@ RETURNS anycompatible AS ... schema; that is, <command>CREATE EXTENSION</command> does the equivalent of this: <programlisting> -SET LOCAL search_path TO @extschema@; +SET LOCAL search_path TO @extschema@, pg_temp; </programlisting> This allows the objects created by the script file to go into the target schema. The script file can change <varname>search_path</varname> if it wishes, @@ -941,9 +919,15 @@ SET LOCAL search_path TO @extschema@; <para> If any prerequisite extensions are listed in <varname>requires</varname> - in the control file, their target schemas are appended to the initial - setting of <varname>search_path</varname>. This allows their objects to be - visible to the new extension's script file. + in the control file, their target schemas are added to the initial + setting of <varname>search_path</varname>, following the new + extension's target schema. This allows their objects to be visible to + the new extension's script file. + </para> + + <para> + For security, <literal>pg_temp</literal> is automatically appended to + the end of <varname>search_path</varname> in all cases. </para> <para> @@ -1170,6 +1154,154 @@ SELECT * FROM pg_extension_update_paths('<replaceable>extension_name</replaceabl </para> </sect2> + <sect2 id="extend-extensions-security"> + <title>Security Considerations for Extensions</title> + + <para> + Widely-distributed extensions should assume little about the database + they occupy. Therefore, it's appropriate to write functions provided + by an extension in a secure style that cannot be compromised by + search-path-based attacks. + </para> + + <para> + An extension that has the <varname>superuser</varname> property set to + true must also consider security hazards for the actions taken within + its installation and update scripts. It is not terribly difficult for + a malicious user to create trojan-horse objects that will compromise + later execution of a carelessly-written extension script, allowing that + user to acquire superuser privileges. + </para> + + <para> + If an extension is marked <varname>trusted</varname>, then its + installation schema can be selected by the installing user, who might + intentionally use an insecure schema in hopes of gaining superuser + privileges. Therefore, a trusted extension is extremely exposed from a + security standpoint, and all its script commands must be carefully + examined to ensure that no compromise is possible. + </para> + + <para> + Advice about writing functions securely is provided in + <xref linkend="extend-extensions-security-funcs"/> below, and advice + about writing installation scripts securely is provided in + <xref linkend="extend-extensions-security-scripts"/>. + </para> + + <sect3 id="extend-extensions-security-funcs"> + <title>Security Considerations for Extension Functions</title> + + <para> + SQL-language and PL-language functions provided by extensions are at + risk of search-path-based attacks when they are executed, since + parsing of these functions occurs at execution time not creation time. + </para> + + <para> + The <link linkend="sql-createfunction-security"><command>CREATE + FUNCTION</command></link> reference page contains advice about + writing <literal>SECURITY DEFINER</literal> functions safely. It's + good practice to apply those techniques for any function provided by + an extension, since the function might be called by a high-privilege + user. + </para> + + <!-- XXX It's not enough to use qualified names, because one might write a + qualified name to an object that itself uses unqualified names. Many + information_schema functions have that defect, for example. However, + that's a defect in the referenced object, and relatively few queries + will be affected. Also, we direct applications to secure search_path + when connecting to an untrusted database; if applications do that, + they are immune to known attacks even if some extension refers to a + defective object. Therefore, guide extension authors as though core + PostgreSQL contained no such defect. --> + <para> + If you cannot set the <varname>search_path</varname> to contain only + secure schemas, assume that each unqualified name could resolve to an + object that a malicious user has defined. Beware of constructs that + depend on <varname>search_path</varname> implicitly; for + example, <token>IN</token> + and <literal>CASE <replaceable>expression</replaceable> WHEN</literal> + always select an operator using the search path. In their place, use + <literal>OPERATOR(<replaceable>schema</replaceable>.=) ANY</literal> + and <literal>CASE WHEN <replaceable>expression</replaceable></literal>. + </para> + + <para> + A general-purpose extension usually should not assume that it's been + installed into a secure schema, which means that even schema-qualified + references to its own objects are not entirely risk-free. For + example, if the extension has defined a + function <literal>myschema.myfunc(bigint)</literal> then a call such + as <literal>myschema.myfunc(42)</literal> could be captured by a + hostile function <literal>myschema.myfunc(integer)</literal>. Be + careful that the data types of function and operator parameters exactly + match the declared argument types, using explicit casts where necessary. + </para> + </sect3> + + <sect3 id="extend-extensions-security-scripts"> + <title>Security Considerations for Extension Scripts</title> + + <para> + An extension installation or update script should be written to guard + against search-path-based attacks occurring when the script executes. + If an object reference in the script can be made to resolve to some + other object than the script author intended, then a compromise might + occur immediately, or later when the mis-defined extension object is + used. + </para> + + <para> + DDL commands such as <command>CREATE FUNCTION</command> + and <command>CREATE OPERATOR CLASS</command> are generally secure, + but beware of any command having a general-purpose expression as a + component. For example, <command>CREATE VIEW</command> needs to be + vetted, as does a <literal>DEFAULT</literal> expression + in <command>CREATE FUNCTION</command>. + </para> + + <para> + Sometimes an extension script might need to execute general-purpose + SQL, for example to make catalog adjustments that aren't possible via + DDL. Be careful to execute such commands with a + secure <varname>search_path</varname>; do <emphasis>not</emphasis> + trust the path provided by <command>CREATE/ALTER EXTENSION</command> + to be secure. Best practice is to temporarily + set <varname>search_path</varname> to <literal>'pg_catalog, + pg_temp'</literal> and insert references to the extension's + installation schema explicitly where needed. (This practice might + also be helpful for creating views.) Examples can be found in + the <filename>contrib</filename> modules in + the <productname>PostgreSQL</productname> source code distribution. + </para> + + <para> + Cross-extension references are extremely difficult to make fully + secure, partially because of uncertainty about which schema the other + extension is in. The hazards are reduced if both extensions are + installed in the same schema, because then a hostile object cannot be + placed ahead of the referenced extension in the installation-time + <varname>search_path</varname>. However, no mechanism currently exists + to require that. For now, best practice is to not mark an extension + trusted if it depends on another one, unless that other one is always + installed in <literal>pg_catalog</literal>. + </para> + + <para> + Do <emphasis>not</emphasis> use <command>CREATE OR REPLACE + FUNCTION</command>, except in an update script that must change the + definition of a function that is known to be an extension member + already. (Likewise for other <literal>OR REPLACE</literal> options.) + Using <literal>OR REPLACE</literal> unnecessarily not only has a risk + of accidentally overwriting someone else's function, but it creates a + security hazard since the overwritten function would still be owned by + its original owner, who could modify it. + </para> + </sect3> + </sect2> + <sect2 id="extend-extensions-example"> <title>Extension Example</title> @@ -1189,18 +1321,18 @@ SELECT * FROM pg_extension_update_paths('<replaceable>extension_name</replaceabl CREATE TYPE pair AS ( k text, v text ); -CREATE OR REPLACE FUNCTION pair(text, text) +CREATE FUNCTION pair(text, text) RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1, $2)::@extschema@.pair;'; CREATE OPERATOR ~> (LEFTARG = text, RIGHTARG = text, FUNCTION = pair); -- "SET search_path" is easy to get right, but qualified names perform better. -CREATE OR REPLACE FUNCTION lower(pair) +CREATE FUNCTION lower(pair) RETURNS pair LANGUAGE SQL AS 'SELECT ROW(lower($1.k), lower($1.v))::@extschema@.pair;' SET search_path = pg_temp; -CREATE OR REPLACE FUNCTION pair_concat(pair, pair) +CREATE FUNCTION pair_concat(pair, pair) RETURNS pair LANGUAGE SQL AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k, $1.v OPERATOR(pg_catalog.||) $2.v)::@extschema@.pair;'; @@ -1215,6 +1347,7 @@ AS 'SELECT ROW($1.k OPERATOR(pg_catalog.||) $2.k, # pair extension comment = 'A key/value pair data type' default_version = '1.0' +# cannot be relocatable because of use of @extschema@ relocatable = false </programlisting> </para> diff --git a/doc/src/sgml/hstore.sgml b/doc/src/sgml/hstore.sgml index fd75e92790b..8a1caa35761 100644 --- a/doc/src/sgml/hstore.sgml +++ b/doc/src/sgml/hstore.sgml @@ -918,10 +918,14 @@ ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || ''; Python dictionaries. </para> - <para> - Of these additional extensions, <literal>hstore_plperl</literal> is - considered trusted; the rest are not. - </para> + <caution> + <para> + It is strongly recommended that the transform extensions be installed in + the same schema as <filename>hstore</filename>. Otherwise there are + installation-time security hazards if a transform extension's schema + contains objects defined by a hostile user. + </para> + </caution> </sect2> <sect2> diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml index dea453fc759..36aa2b5fad8 100644 --- a/doc/src/sgml/ltree.sgml +++ b/doc/src/sgml/ltree.sgml @@ -835,6 +835,15 @@ ltreetest=> SELECT ins_label(path,2,'Space') FROM test WHERE path <@ 'Top. creating a function, <type>ltree</type> values are mapped to Python lists. (The reverse is currently not supported, however.) </para> + + <caution> + <para> + It is strongly recommended that the transform extensions be installed in + the same schema as <filename>ltree</filename>. Otherwise there are + installation-time security hazards if a transform extension's schema + contains objects defined by a hostile user. + </para> + </caution> </sect2> <sect2> diff --git a/doc/src/sgml/ref/create_extension.sgml b/doc/src/sgml/ref/create_extension.sgml index 756dd193f85..efd7fc64656 100644 --- a/doc/src/sgml/ref/create_extension.sgml +++ b/doc/src/sgml/ref/create_extension.sgml @@ -177,6 +177,33 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name system views. </para> + <caution> + <para> + Installing an extension as superuser requires trusting that the + extension's author wrote the extension installation script in a secure + fashion. It is not terribly difficult for a malicious user to create + trojan-horse objects that will compromise later execution of a + carelessly-written extension script, allowing that user to acquire + superuser privileges. However, trojan-horse objects are only hazardous + if they are in the <varname>search_path</varname> during script + execution, meaning that they are in the extension's installation target + schema or in the schema of some extension it depends on. Therefore, a + good rule of thumb when dealing with extensions whose scripts have not + been carefully vetted is to install them only into schemas for which + CREATE privilege has not been and will not be granted to any untrusted + users. Likewise for any extensions they depend on. + </para> + + <para> + The extensions supplied with <productname>PostgreSQL</productname> are + believed to be secure against installation-time attacks of this sort, + except for a few that depend on other extensions. As stated in the + documentation for those extensions, they should be installed into secure + schemas, or installed into the same schemas as the extensions they + depend on, or both. + </para> + </caution> + <para> For information about writing new extensions, see <xref linkend="extend-extensions"/>. @@ -188,10 +215,16 @@ CREATE EXTENSION [ IF NOT EXISTS ] <replaceable class="parameter">extension_name <para> Install the <link linkend="hstore">hstore</link> extension into the - current database: + current database, placing its objects in schema <literal>addons</literal>: +<programlisting> +CREATE EXTENSION hstore SCHEMA addons; +</programlisting> + Another way to accomplish the same thing: <programlisting> +SET search_path = addons; CREATE EXTENSION hstore; -</programlisting></para> +</programlisting> + </para> </refsect1> <refsect1> |