Wednesday, August 13, 2014

Is Oracle Data Redaction broken?

In blackhat 2014 and earlier in 2013, David Litchfield has pointed out that "Oracle data redaction is broken and trivial to bypass". Here is an exaggerated scribe of his blackhat 2014 talk. Is that true that you can trivially bypass data redaction? Yes, of course, if you are using ad-hoc queries. You can trivially write a join query to fetch sensitive data if you have direct access to the database. Does that mean it is broken? No, not really; the problem is that Oracle data redaction does not claim to protect against ad-hoc queries. It is designed to be a helper function for applications to redact sensitive data before showing to application users. It can be considered as an application layer security feature. It is not a Database security feature that prevents leakage of sensitive data from the database when an attacker has direct access to the database.

Let me provide you an analogy using encryption which is not the defense for all threats. Transparent database encryption techniques provided by many database vendors, including, Oralce, Microsoft and IBM, is designed to protect data at rest. That is, if an attacker steals or gets access to a hard drive where the data is stored, they won't be able to access the actual data as it is encrypted and they don't have keys to decrypt it. However, if the attacker can compromise an application that access these encrypted data, they get access to the plaintext data. Does that mean the transparent encryption provided by all these vendors is broken? Certainly not. The same applies for Oracle data redaction.

Without the data redaction technique, an app developer would do the following to mask sensitive data, for example, credit card numbers:

1. Fetch credit card numbers from the database
2. Write application code to mask credit card numbers
3. Apply the application defined masking function before pushing the data user interface (e.g. web browser)

From the development and maintenance point of view, there are some pratical issues with the above approach:
- App developers need to write custom redaction code
- If multiple apps uses similar redaction or accesses multiple databases, it is difficult to maintain or update these redaction so that consistency is maintained in the long run. There is no way to centrally control it. It may require constant code changes.

Figure: Oracle data redaction example (Source: oracle.com)


Oracle data redaction helps overcome these practical issues. Further, notice that app already has privilege to access full credit card numbers. The objective of Oracle data redaction is not to block access to these credit card numbers. If the application is compromised, the attacker can use trivial bypass techniques to get his hands on the credit card numbers. Instead, the objective is to defend against app user compromises. If an app user is compromised, the can use his/her credential to login to the application and get access only to the redacted credit card number. In short, Oracle data redaction is designed to show the least information to app users.

If you want to prevent leakage of sensitive data from the database, you need use other preventive and detective techniques such as Oracle database vault and Oracle audit vault and firewall. This is a good example why organizations should have defense in depth to protect their valuables in databases!

2 comments:

Anonymous said...

If this is the intended use scenario, isn't it absolutely trivial to say... just not retrieve the data you don't need? This 'feature' is not worth five cents for what you sell it as, let alone what Oracle sales do.

Tom Martin said...

If one connects as a privileged (sysdba) user then redaction is not in force as described above or if the connected schema is excluded from the policy else ad-hoc queries don't get to see the redacted data.
To wit:
table test has ID - number and name. The redaction policy is full on name
Scott = the owner, but not in the redaction policy exclusion list. Scott can not see the NAME values.

DBNAME SCOTT> insert into test (id, name) values (6,'test insert as scott') ;

1 row created.

DBNAME SCOTT> commit ;

Commit complete.

DBNAME SCOTT>

mx7ts SCOTT> select * from test ;

ID NAME
---------- ------------------------------
1
2
3
6
4
5

6 rows selected.
/** priviliged user - excluded user CAN see adhoc redacted data **/
DBNAME SCOTT> connect sys/syspwd@dbname as sysdba
select * from scott.test

DBNAME SYS> select * from scott.test ;

ID NAME
---------- ------------------------------
1 Scott 1
2 Scott 2
3 Scott test 3
6 test insert as scott
4 test 4
5 test 5


DBNAME SYS>