@@ -1725,18 +1725,18 @@ SELECT * FROM shoelace;
1725
1725
<programlisting>
1726
1726
CREATE TABLE phone_data (person text, phone text, private boolean);
1727
1727
CREATE VIEW phone_number AS
1728
- SELECT person, phone FROM phone_data WHERE NOT private;
1728
+ SELECT person, CASE WHEN NOT private THEN phone END AS phone
1729
+ FROM phone_data;
1729
1730
GRANT SELECT ON phone_number TO secretary;
1730
1731
</programlisting>
1731
-
1732
+
1732
1733
Nobody except him (and the database superusers) can access the
1733
1734
<literal>phone_data</> table. But because of the <command>GRANT</>,
1734
1735
the secretary can run a <command>SELECT</command> on the
1735
1736
<literal>phone_number</> view. The rule system will rewrite the
1736
1737
<command>SELECT</command> from <literal>phone_number</> into a
1737
- <command>SELECT</command> from <literal>phone_data</> and add the
1738
- qualification that only entries where <literal>private</> is false
1739
- are wanted. Since the user is the owner of
1738
+ <command>SELECT</command> from <literal>phone_data</>.
1739
+ Since the user is the owner of
1740
1740
<literal>phone_number</> and therefore the owner of the rule, the
1741
1741
read access to <literal>phone_data</> is now checked against his
1742
1742
privileges and the query is permitted. The check for accessing
@@ -1770,15 +1770,53 @@ GRANT SELECT ON phone_number TO secretary;
1770
1770
</para>
1771
1771
1772
1772
<para>
1773
- This mechanism also works for update rules. In the examples of
1773
+ Note that while views can be used to hide the contents of certain
1774
+ columns using the technique shown above, they cannot be used to reliably
1775
+ conceal the data in unseen rows. For example, the following view is
1776
+ insecure:
1777
+ <programlisting>
1778
+ CREATE VIEW phone_number AS
1779
+ SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
1780
+ </programlisting>
1781
+ This view might seem secure, since the rule system will rewrite any
1782
+ <command>SELECT</command> from <literal>phone_number</> into a
1783
+ <command>SELECT</command> from <literal>phone_data</> and add the
1784
+ qualification that only entries where <literal>phone</> does not begin
1785
+ with 412 are wanted. But if the user can create his or her own functions,
1786
+ it is not difficult to convince the planner to execute the user-defined
1787
+ function prior to the <function>NOT LIKE</function> expression.
1788
+ <programlisting>
1789
+ CREATE FUNCTION tricky(text, text) RETURNS bool AS $$
1790
+ BEGIN
1791
+ RAISE NOTICE '% => %', $1, $2;
1792
+ RETURN true;
1793
+ END
1794
+ $$ LANGUAGE plpgsql COST 0.0000000000000000000001;
1795
+ SELECT * FROM phone_number WHERE tricky(person, phone);
1796
+ </programlisting>
1797
+ Every person and phone number in the <literal>phone_data</> table will be
1798
+ printed as a <literal>NOTICE</literal>, because the planner will choose to
1799
+ execute the inexpensive <function>tricky</function> function before the
1800
+ more expensive <function>NOT LIKE</function>. Even if the user is
1801
+ prevented from defining new functions, built-in functions can be used in
1802
+ similar attacks. (For example, casting functions include their inputs in
1803
+ the error messages they produce.)
1804
+ </para>
1805
+
1806
+ <para>
1807
+ Similar considerations apply to update rules. In the examples of
1774
1808
the previous section, the owner of the tables in the example
1775
1809
database could grant the privileges <literal>SELECT</>,
1776
1810
<literal>INSERT</>, <literal>UPDATE</>, and <literal>DELETE</> on
1777
1811
the <literal>shoelace</> view to someone else, but only
1778
1812
<literal>SELECT</> on <literal>shoelace_log</>. The rule action to
1779
1813
write log entries will still be executed successfully, and that
1780
1814
other user could see the log entries. But he cannot create fake
1781
- entries, nor could he manipulate or remove existing ones.
1815
+ entries, nor could he manipulate or remove existing ones. In this
1816
+ case, there is no possibility of subverting the rules by convincing
1817
+ the planner to alter the order of operations, because the only rule
1818
+ which references <literal>shoelace_log</> is an unqualified
1819
+ <literal>INSERT</>. This might not be true in more complex scenarios.
1782
1820
</para>
1783
1821
</sect1>
1784
1822
0 commit comments