You are on page 1of 5

Hardening the Oracle 11g Database - Initial Steps

The following is a basic set of hardening guidelines for an Oracle 11g database along with some scripts you may find
useful. This list is by no means complete. It does not cover file permissions, authentication controls and user profiles,
encryption, grants or auditing but it is a good place to start.
Or perhaps takes Slavic's advice from his comment on this post and start with Oracle's Checklist for Database
Security. It gives a broader, though perhaps less detailed view, and covers some of the topics I have left out (for
now). Also check out Slavik's Musings on Database Security Blog.
1.

Put the database server behind a firewall. See prior post Wall It Off! for a discussion of the importance
of a firewall, even for trusted users on your Intranet.

2.

Apply latest security patches for OS and harden the operating system.

3.

Install only the components needed. When installing the Oracle software, Spatial, OLAP, Data Mining,
and Real Application Testing are all installed by default. Change the default behavior if you do not need
these components. The MDSYS schema used by Spatial has been the target of security vulnerabilities
in the past.

4.

11g defaults to installing Advanced Security; this is a default that should be accepted assuming you
have the license.

5.

Change the default name of the Listener (LISTENER) as well as the default port (1521).

6.

Do not install the sample schemas which are installed by default.

7.

When running the Database Configuration Assistant, select the Custom option so that you have the
ability to de-select any unneeded components.

8.

Do take the default security settings, new for 11g, that enable auditing and a more hardened default
profile. This setting also revokes CREATE EXTERNAL JOB from PUBLIC, sets
07_DICTIONARY_ACCESSIBILITY and REMOTE_OS_ROLES to FALSE as well as setting values for
PASSWORD_GRACE_TIME, PASSWORD_LOCK_TIME and PASSWORD_LIFE_TIME to 7, 1, and 180
respectively rather than their previous default of UNLIMITED. This is a great move by Oracle.

9.

More good news. With 11g, a new initialization parameter called


SEC_RETURN_SERVER_RELEASE_BANNER is available that controls the display of Oracle version
information when clients connect to the database. It even defaults to FALSE (do not display), another
good move by Oracle.

10. Even more good news. With 11g, a new initialization parameter called
SEC_CASE_SENSITIVE_LOGON is available to allow case sensitive passwords. It even defaults to the
TRUE setting, meaning case sensitivity is supported. This can greatly increase password complexity
and make it harder to use brute force attacks to guess passwords. Make use of this new feature when
setting passwords.
11. Exit the installer. Prior versions of Oracle left encrypted passwords in the install logs which could be
easily decrypted by hackers. 11g appears to do a better job of this, instead displaying XXXXXXX or

*********** . However, I still consider it a best practice to change passwords at the command line rather
than through a tool. Make sure to use the "password <username>" syntax rather than the "alter user
<username> identified by <password>" syntax since the former encrypts the password over the network
and the later does not (at least in prior versions).
12. Change the default passwords for all the locked accounts. These passwords can be made very , very
strong since you will never use them.
13. Also change the passwords of SYS and SYSTEM. Again this is just a precaution in case the installer left
a remnant of the password you entered during the installation.
14. If you configured Enterprise Manager (OEM) then also change the SYSMAN and DBSNMP account
passwords using the appropriate procedure for those accounts in order not to break your OEM
installation.
15. Next you'll want to scan for default or weak passwords. I used to maintain my own script for this but now
I rely on Alexander Kornbrust's, founder of Red Database Security GmbH . This is the best tool I've
found and Alexander makes it freely available at: Oracle Password Checker (Cracker) .
16. With 11g, Oracle also supplies a DBA_USERS_WITH_DEFPWD view. Selecting * from this view will
return USERNAMEs with default passwords. This is nice to have but I still recommend Alexander's
script instead since it also checks for weak passwords.
17. You may be asking why all this checking for default and weak passwords when 11g does a good job of
this? First, you may be upgrading from a previous, less secure version and have some old defaults.
Second, DBAs are not infallible and sometimes create weak passwords. Scan regularly!
18. Next we'll check for demo accounts. If you've followed the above instructions you should have none but
it you are upgrading an existing database or forgot to change the default behavior of the installer, now is
the time to check. I use Randy Giefer's Demo Account Check SQL Script which you can download here.
Simply run the script and drop any demo accounts it finds.
19. Next we need to harden the database listener. Oracle created an EXTPROC entry in your listener.ora
configuration file whether you needed one or not. If you do not need to make external procedure calls
from the database then the EXTPROC listener is not needed and should be removed. External
procedure calls can give an attacker access to your operating system from within the database.
Removing this capability eliminates this attack vector.The entry will look something like this: (ADDRESS
= (PROTOCOL = IPC)(KEY = EXTPROC<your-non-default-listener-port>)) . Simply backup your current
listener.ora, remove the above line, and bounce the listener.
20. Next you'll want to set administration restrictions on your listener. This will prevent the use of the SET
command and require any listener configuration changes to be done by a user with write permissions on
the listener.ora file. Simply save a backup of the listener.ora file, add the following line:
ADMIN_RESTRICTIONS_LISTENER_<your-non-default-listener-name>=ON and then bounce the
listener.
21. Listener logging is turned on be default; however, it is generally a best practice to explicitly set values,
even if it is a default. To explicitly set this parameter, save a backup of the listener.ora file, add the

following line: LOGGING_LISTENER_<your-non-default-listener-name>=ON and then bounce the


listener.
22. The CIS benchmark recommends setting INBOUND_CONNECTION_TIMEOUT. This parameter
specifies the time, in seconds, that a client must complete its connection attempt after the initial network
connection has been acknowledged. The recommendation is to set it to the lowest value possible where
none of your client connections are timing out. By default this parameter is not set. To set this
parameter, save a backup of the listener.ora file, add the following line:
INBOUND_CONNECTION_TIMEOUT_<your-non-default-listener-name> n where n is the number of
seconds in which the client must complete its connection, and then bounce the listener.
23. The CIS benchmark recommends setting SQLNET.INBOUND_CONNECTION_TIMEOUT. This
parameter is similar to INBOUND_CONNECTION_TIMEOUT but it also includes the time for the initial
network connection. Therefore Oracle and CIS recommend setting this value slightly higher than the
INBOUND_CONNECTION_TIMEOUT value. By default this parameter is not set. To set this parameter,
save a backup of the sqlnet.ora file, add the following line:
SQLNET.INBOUND_CONNECTION_TIMEOUT n where n is slightly higher than the value for
INBOUND_CONNECTION_TIMEOUT, and then bounce the listener.
24. SQLNET.EXPIRE_TIME is an interesting parameter with multiple purposes. The original purpose was
dead connection detection, that is, to detect abnormally terminated client-side connections and
terminate the corresponding process on the server side. So if a client kills its connection and this
parameter is not set, the server will indefinitely keep the server-side process active thus using valuable
server resources for no good purpose. Setting this parameter to 10 will result in a probe being initiated
every 10 minutes from the server to the client to see if the client connection has terminated and if so
closing the server-side process. The other use for this parameter has developed out of the contrary
goals of modern connection pooling (especially for J2EE apps) and firewall technology. Establishing a
database connection is a relatively expensive and slow process from an application perspective.
Connection pools resolve the problem by keeping open some set minimum number of connections,
even when idle, such that connections are normally available to the application. This usually means
you'll have at least some idle connections at all times. Enter firewalls, which are generally configured to
tear down idle connections (without notifying the client) after some set period of inactivity. When a
firewall does this tear down, the client has no idea and assumes it has a good database connection;
however, when the pool tries to reuse a torn down connection it get an error. Even if the application is
well written and handles the exception, it will still take considerable time to attempt to reuse the
connection, get the error, handle the error and retry the connection. If the firewall has torn down multiple
connections, which is typically the case, this whole process my be repeated several times for multiple
users causing sever performance problems. Setting SQLNET.EXPIRE_TIME causes the probe to be
sent from server to client even on idle but active connections. This probe represents activity to the
firewall and it therefore no longer considers the connection to be idle and therefore will not tear it down.
So if you use connection pools and have a firewall between your app and database tier, set
SQLNET.EXPIRE_TIME to no more than half the value of you firewall's idle connection timeout in
minutes.
25. Block access to your database listener by IP address. Even if your firewall is compromised, you'll have
another layer of security protecting the listener. To enable this feature, backup your sqlnet.ora file, then
add the following lines:
o

tcp.validnode_checking = yes

tcp.invited_nodes = (hostname1, hostname2, ... , hostnameN)

You can specify a list of hostnames or IP addresses. If you


use hostnames, they must be resolvable to an IP address or the
listener will not start.

Unfortunately, the node list does not support partial IP


addresses or subnet masks in the manner of an Apache
configuration. You must specify a full IP address or a
resolvable hostname.

You can use tcp.excluded_nodes instead of tcp.invited_nodes;


however, the two are mutually exclusive. If you specify both,
the excluded nodes will be ignored.

26. 11g comes with a more secure listener out of the box. You can only stop the listener as the local OS
account that started the listener. Therefore, it is now actually more secure to NOT set a listener
password since setting one enables remote administration. Scanners will likely ding you on this but it is
the appropriate practice for 11g.
27. By default, Oracle registers an XPT service. If you are not using DataGurad you should remove this
service by running the following as SYS:
o

alter system set "__dg_broker_service_names" = ''


scope=spfile;

Note the parameter starts with two underscores.

Then bounce the database

lsnrctl status should now no longer show the XPT service

o
2.

This one is a little off topic but useful to know. If you have an existing database with XML DB installed
but you do not need it, you can disable the functionality and reduce your attack vectors by running the
following as SYS: alter system reset dispatchers scope=spfile sid='*';

3.

Next you'll want to explicitly set the hidden parameter _trace_files_public to false. To do this:
o

create pfile from spfile;

Add *._trace_files_public=false to the pfile

shutdown immediate

startup pfile='<full-path-to-pfile>'

create spfile from pfile;

shutdown immediate

startup

Finally, download, read and run the basic CIS Hardening Script. Make sure to read the comments in
the script to make sure the settings as appropriate for your environment. The database will need to be
bounced for these changes to take effect. This script sets:
o

GLOBAL_NAMES=TRUE

OS_AUTHENT_PREFIX TO THE NULL STRING

SQL92_SECURITY=TRUE

AUDIT_SYS_OPERATIONS=TRUE