Are you secure? Securing the Oracle Network
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.
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.
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.
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.