Are you secure? Securing the Oracle Network

Steven Karam's picture
articles: 

Last month we talked about basic Oracle security, and set out principles for a top notch secure system. These included passwords, the principle of least privilege, and roles.

This month we journey into the fascinating world of Oracle Network Security. The topics covered will not involve the Oracle Advanced Security option: it's too big to cover here, and it is an added expense that many companies do not want. Instead, we will go over basic network security that can be implemented by anyone who uses Oracle. It is built in and so is already part of your system.

Listener security

The first thing to do is to put a password on your listener. By default the listener comes with no password, and anyone can change listener settings through the lsnrctl tool. In Oracle 9i, any computer on your network can stop your listener in the blink of an eye if you do not password protect it.

First, a point on passwords. Yes, they are inconvenient, but they are much better than the alternatives. Which would you rather explain to your employer: that you have to spend hours working on password management, or that you have to spend days on fixing downtime or data corruption and that the company is losing money? And yes, an unprotected listener can easily be used to corrupt your entire database.

To password protect your listener, perform the following as your Oracle user:

$ lsnrctl
LSNRCTL> change_password
Old password: <press enter here>
New password: <enter new password>
Reenter new password: <reenter password>

If you have done all of this correctly, you will see the following:

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<hostname>)(PORT=<port>)))
Password changed for <listener name>
The command completed successfully

Just as a note, if the listener you are protecting does not have the default name of LISTENER, you must do set cur <listenername> before issuing the change_password command.

At this point, save the configuration of the listener to the file system. If you are on 10g, it will save with no problems:

LSNRCTL> save_config
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<hostname>)(PORT=<port>)))
Saved <listener name> configuration parameters.
Listener Parameter File <oracle home>/listener.ora
Old Parameter File <oracle home>/listener.bak
The command completed successfully

And you have a password protected listener.

However, this does not happen on 9i. If you perform a save_config, you will see the following:

LSNRCTL> save_config
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<hostname>)(PORT=<port>)))
TNS-01169: The listener has not recognized the password

Oops! The reason is this: in Oracle 10g, operating system authentication for the listener has been implemented. The listener checks to make sure you are part of the privileged dba group, and if so it will grant you access to change the password, save configuration, stop the listener, etc. In 9i, we must do the following at this point:

LSNRCTL> set password
Password: <the password you chose>
The command completed successfully

At this point, you can now perform a save_config.

So what is the result of this? In 9i, you will now require a password whenever you wish to stop the listener or any other "destructive" listener actions. In 10g, if you are not logged into the operating system with a privileged account, you will have to enter a password as well. A typical listener stop may look like this in Oracle 9i:

$ lsnrctl
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<hostname>)(PORT=<port>)))
TNS-01169: The listener has not recognized the password
LSNRCTL> set password
Password: <enter password here>
The command completed successfully
LSNRCTL> stop
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=<hostname>)(PORT=<port>)))
The command completed successfully

You are now protected against unauthorized shutdowns of your listener. This protects you from a whole range of possible security breaches. Remember that "set password" is how you enter your password for authentication; change_password is how it is changed.

Blocking by IP Address

Now comes the fun part: keeping people out of your database! While IP-based blocking is not as suitable as a full firewall, you are able to block clients based on their IP address or hostname.

The secret lies in the SQLNET.ORA file. This file can be found in your $ORACLE_HOME/network/admin directory along with your tnsnames.ora and listener.ora. Open it up and insert the following line:

tcp.validnode_checking = yes

This turns on the hostname/IP checking for your listeners. After this, you can supply lists of nodes to enable/disable, as such:

tcp.invited_nodes = (hostname1, hostname2)
tcp.excluded_nodes = (192.168.10.3)

Note that if you only specify invited nodes, all others will be excluded, so there is really no reason to do both. The same goes for excluded nodes: exclude a list of clients, invite all others.

Even though this will not protect you against advanced attacks (IP and hostname are easy to spoof) it still serves as a deterrent against hacking attempts.

Here are some rules for entering invited/excluded nodes:

  • You cannot use wildcards in your specifications.
  • You must put all invited nodes in one line; likewise for excluded nodes.
  • You should always enter localhost as an invited node.

Once you have set up your rules and enabled valid node checking, you must restart your listeners to reap the benefits. Here is an example:

PayrollDB is a database server, accessed by Payroll
SalesDB is a database server, accessed by Sales
SApp1, SApp2, and SApp3 are application servers using the SalesDB
PApp1, PApp2, and PApp3 are application servers using the PayrollDB

The sqlnet.ora on PayrollDB would look like this:

tcp.validnode_checking = yes
tcp.invited_nodes = (localhost, PayrollDB, PApp1, PApp2, PApp3)

The sqlnet.ora on SalesDB would look like this:

tcp.validnode_checking = yes
tcp.invited_nodes = (localhost, SalesDB, SApp1, SApp2, SApp3)

Once this has been done, restart the listener. (You did follow the first part of this article and password protect it, didn’t you?)

$ lsnrctl
LSNRCTL> set password
Password: <the password you chose>
The command completed successfully
LSNRCTL> stop
The command completed successfully
LSNRCTL> start

Now PApp1, PApp2, and PApp3 can access PayrollDB but not SalesDB; the same goes for the Sales application servers' access to PayrollDB.

While this isn't terribly advanced, it will definitely act as a good block against basic attacks.

Final guidelines

Here are some other things that will help to protect your database servers on the network:

  • Put your listener on a port other than the well-known 1521.
  • Run your listener as a different user.
  • Remove the EXTPROC entry from your listener configuration.
  • Use TCPS protocol for communications.
  • Use CMAN as an Oracle firewall.
  • Close unnecessary ports on the operating system (rexec, rsh, ftp, etc).

These guidelines are not absolutely necessary, but they do provide you with an extra bit of protection. Once you have password protected your listener and optionally set up valid node checking, you are definitely in a well secured position.

These guidelines will be welcome additions to your security plan (if you don't have one, make one), and will definitely impress auditors.

Next month we conclude our three part series with The third step - securing the database.

Comments

What if I have forgot the password of the listener? How can I set it again?

Thanks

Chandan Singh

Hi Chandan!

If you lose the password, log into the operating system as a user that can edit the listener.ora file. Simply delete out the encrypted password line that will save to the bottom of your listener.ora after you save_config.

Hi Steven, thanks for your helpful information. We like the idea of passwrod-protected listener but just wonder the best way to start/stop it (with the password) in the automatic startup/stop script. For example, without the password, we can easily do the following:

'start')
  echo "$0 : starting up" >> $LOG1
  echo "starting listener"
  su $ORACLE -c "$ORACLE_HOME/bin/lsnrctl start" >> $LOG1 2>&1
  ......  ;;
'stop')
  echo "$0 : shutting down" >> $LOG2
  echo "stopping listener"
  su $ORACLE -c "$ORACLE_HOME/bin/lsnrctl stop" >> $LOG2 2>&1
  ......    ;;

Thanks in advance.

Judy

Hi All,

"In Oracle 10, the TNSListener is secure out of the box and there should not be a need to set a listener password as in older versions of the Oracle listener."

Metalink Note: 260986.1.

Thanks,
Sanjeet Rakwal

Judy,

You need to call a shell script from the system's startup script.

...
su $ORACLE -c "$SCRIPTDIR/startlistener.sh" >> $LOG1 2>&1
...

Here are some samples:

startlistener.sh

#!/bin/sh
/ohome/oracle/app/product/9.2.0/bin/lsnrctl << EOF
set password XXXXXXXXXXX <-- encripted text password
start
exit
EOF

stoplistener.sh

/ohome/oracle/app/product/9.2.0/bin/lsnrctl << EOF
set password XXXXXXXXXXX <-- encripted text password
stop
exit
EOF