aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/earthdistance.sgml27
-rw-r--r--doc/src/sgml/extend.sgml203
-rw-r--r--doc/src/sgml/hstore.sgml12
-rw-r--r--doc/src/sgml/ltree.sgml9
-rw-r--r--doc/src/sgml/ref/create_extension.sgml37
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=&gt; SELECT ins_label(path,2,'Space') FROM test WHERE path &lt;@ '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>