For those who are ultra-conscious about security within the
Oracle RDBMS, particularly when the topic involves the weaknesses of Oracle’s
password mechanism or algorithm, older versions of Oracle (especially 10g and
below) are always going to be viewed as a hacker’s target of opportunity.
Almost nothing you can do, so it seems, will ever give you 100% protection
against hackers. There are many areas you can shore up, but some constants
remain, and those include the fact that some people are always going to have
access to sensitive data and that the vast majority of client connections will
involve transmitting data across a network.
The word “hacker” needs to be qualified a bit for the
purposes of this article. The hacker of interest used in the following
demonstrations is you, the DBA. How can a DBA be a hacker, given that you have
the keys to everything within the database in the first place? Just because you
have access to all data doesn’t mean you can view all data. In particular, you
can view the hashed value of passwords, but not the passwords themselves.
Why would you want to see actual password values? To be a
bit more restrictive, why would you want to know what a particular plaintext
password is? You can war game lots of scenarios where this may be necessary,
but one that may be more common than not is due to the use of legacy
applications, relatively high personnel turnover, and poor password
management/documentation in the first place. Changing SYS and SYSTEM passwords
is typically not an issue, but what about the password for the OLD_APP schema?
Before testing the “identified by values” temporary changing
of the password routine, you may need the plaintext value. I don’t know, something
about .NET developers always wanting to store unencrypted passwords in a
configuration file and then the file gets trashed during a server crash and no
one knows how to 1) rebuild the application, or 2) reconnect the application
comes to mind.
An Internet search for “Oracle password crackers” turns up a
good bit of information and even points you towards homegrown hacker-like
applications. For our (benevolent) purposes, I selected Laszlo Toth’s
woraauthbf tool, which you can read about and download from here (http://www.soonerorlater.hu/index.khtml?article_id=513).
The program is very much as-is (“Elpased” instead of Elapsed), but it serves our
purposes quite well.
To provide a bit more information about what’s documented,
you can use woraauthbf against older versions of Oracle by creating a text file
with the username, hashed password, the SID and the server name. The only parts
which have to be real are the username and hashed password value. Why is that?
Upon further research into how Oracle constructs the hashed value, you’ll learn
that the username and password are concatenated. The SID and server name have
nothing whatsoever to do with constructing the hashed value. Other “cracker”
programs rely on network information such as the client and server IP addresses
and ports and a third party “sniffer” tool to snoop the data being transmitted
between the client and server.
Using the tool
Let’s move on to a quick example. Create a password file by
copying the output from the following (or spooling) to a simple txt file:
from sys.dba_users, sys.V_$DATABASE, sys.v_$instance;
Again, the name and host_name can be whatever you want, or
just use the real values. My example is:
Scott’s password is tigers
(which is eventually reported as TIGERS, another knock on Oracle for ignoring
case), taking the length up to six characters from five. After unzipping
the downloaded file, open a CMD prompt/DOS window and invoke the command from
that location. Using a password file named password_file.txt, the command line
woraauthbf.exe -p c:password_file.txt
The output from this session (using all of the defaults) is
C:[my path]>woraauthbf.exe -p c:password_file.txt Usernames will be permuted! The number of processors: 2 Number of pwds to check: 321272406 Number of pwds to check by thread: 160636203 Password file: c:password_file.txt, charset: alpha, maximum length: 6, type: hash Start: 0 End: 160636203 Start array thread with 489 number of passwords! Start: 160636203 End: 321272406 Writing session files... Writing session files... Password found: SCOTT:TIGERS:ORCL:MYPC Elpased time: 164s Checked passwords: 153976754 Password / Second: 938882
The program calculated that slightly more than 321 million
passwords needed to be checked (but 26 to the 6th power is a bit
more than 308 million), and with two processors, the workload was evenly
divided. The default character set was alpha (A-Z) and it took a whopping 164
seconds to determine that Scott’s password is TIGERS. Also of interest is the
passwords checked per second rate of 938,882. We hit on the password before
exhausting all possible values, which you would expect to hit around the
halfway point anyway.
Excluding physical limitations (the number of CPUs and
processor speed, which when running this expect to see the performance meter
peg around 99% for this program), two key factors come into play in the run
time. If, and that is a big IF, you know the length and the character set
(purely alphabetical versus alphanumeric versus alphanumeric plus special
characters), you can greatly reduce the number of passwords to be checked. This
is a case where it is better to start off with a “small” guess and let that run
as opposed to opening up the criteria to everything. The run time ramps up
extremely fast after a certain point.
As an example, I changed the character set to alphanum, and
the run time to get Scott’s unchanged password went up to over six minutes. With
another user’s password info added to the same password file, knowing ahead of
time that is also length 6 and alphanumeric, the run time took over 29 minutes.
(The second user name and password shown below have been edited for privacy
woraauthbf.exe -p c:password_file.txt -m 6 -c alphanum Usernames will be permuted! The number of processors: 2 Number of pwds to check: 2238976116 Number of pwds to check by thread: 1119488058 Password file: c:password_file.txt, charset: alphanum, maximum length: 6, type: hash Start: 0 End: 1119488058 Start: 1119488058 End: 2238976116 Start array thread with 490 number of passwords! Writing session files... Writing session files... Writing session files... Writing session files... Writing session files... Writing session files... Password found: SCOTT:TIGERS:ORCL:MYPC Writing session files... Writing session files... Writing session files... ... Writing session files... Writing session files... Password found: SOMENAMES:X1M72Y:ORCL:MYPC Elpased time: 2152s Checked passwords: 1917149967 Password / Second: 890868
The second entry in the password file came from an 8i
database, while Scott’s hashed value came from a 10g version. I didn’t use the
–o option to specify the oran10.dll either. The implications of this should be
very clear: protect access to anything showing usernames and their hashed
password values, particularly the SYS.USER$ fixed table (not relying on
DBA_USERS view as that can be spoofed).
The run time to get the second user’s plaintext password was
quite reasonable. You could easily spend hours and hours scouring files looking
for the password being embedded in a script. My test was run on an ancient IBM
ThinkCentre with 3GHz and 2GB RAM, certainly nothing fancy. In the second run,
the rate dropped slightly, but I’m happy being able to check about 900,000
passwords a second. If you need to determine a “hidden” (more like forgotten)
password, this tool, and several others just like it, especially given the free
cost, will do the trick. Spending several hours (or even a few days) on CPU
time may be a cheaper route than having to socialize changing a forgotten
password with users who are quite against any downtime because their
application no longer works.