Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Oracle VPD / RLS, how are malicious user predicates prevented from leaking info?

I've been reading the docs for Oracle VPD (Virtual Private Database, a.k.a. fine-grained security, the basis of label-based security), and there's something I'm having a hard time grasping. How does VPD prevent a user from leaking information using a malicious function in the WHERE clause?

Say you have a VPD policy that generates a static predicate like cust_no = SYS_CONTEXT('order_entry', 'cust_num'); (like in the Oracle VPD tutorial).

That results in queries being rewritten, so:

SELECT * FROM orders;

becomes:

SELECT * FROM orders 
  WHERE cust_no = SYS_CONTEXT('order_entry', 'cust_num');

Fine so far as it goes. But what if the user writes:

SELECT * FROM orders WHERE my_malicious_function(secret_column);

? Where my_malicious_function inserts each value it sees into another table owned by the malicious user's control, so they can then see the secret data by selecting that table.

The VPD rewriter will produce, according to the docs, something like:

SELECT * FROM orders 
  WHERE cust_no = SYS_CONTEXT('order_entry', 'cust_num')
    AND my_malicious_function(secret_column);

but Oracle is free to re-order sub-clauses in WHERE. What stops it from just running my_malicious_function first, if it thinks that'll be the cheaper or more selective predicate? (Unlikely when the security condition is a SYS_CONTEXT lookup, but very likely if the condition is a subquery against another table, or is a UDF its self).

I've read the documentation and I'm not seeing where it specifies any ordering guarantee on execution of VPD predicates vs user-supplied predicates. Is there such a guarantee, or any other mechanism to protect against malicious predicate functions?

(I'm also curious about whether a malicious predicate function in a VPD policy could cause a privileged user to run user-supplied code they did not intend by generating a predicate that refers to the malicious function, but that's somewhat separate.)

like image 693
Craig Ringer Avatar asked Oct 21 '22 21:10

Craig Ringer


1 Answers

The "malicious function" is run after the VPD policy is applied, so it cannot see the hidden data.

So, in your example, the following query:

SELECT * FROM orders WHERE my_malicious_function(secret_column);

Gets rewritten to:

SELECT * FROM (
  SELECT * FROM orders orders
  WHERE cust_no = SYS_CONTEXT('order_entry', 'cust_num')
)
WHERE my_malicious_function(secret_column);

Therefore, the function is only executed for rows that satisfy the VPD predicate.

Refer: http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_rls.htm#i1005326

When a table alias is required (for example, parent object is a type table) in the predicate, the name of the table or view itself must be used as the name of the alias. The server constructs the transient view as something like

select c1, c2, ... from tab tab where <predicate>

like image 108
Jeffrey Kemp Avatar answered Oct 24 '22 00:10

Jeffrey Kemp