Feeds:
Posts
Comments

Posts Tagged ‘data encryption’

Today we shall look into a nice feature on how to secure our JDBC connections. It’s generally a standard to make JDBC connections in java applications to connect to database. We mostly have web applications running in a web container. These web applications make JDBC connections to the databases to retrieve data for the applications. How many of us have really thought how secure these JDBC calls are. Well they aren’t actually. Like any other insecure network protocol call, so are these JDBC connections. However these JDBC connections can be very easily encrypted. Well this discussion is purely based on Oracle databases and wouldn’t work with other drivers. However, if any one finds out about other databases please let me know.

Before we go any further let us see some of the security threats we face when we use normal JDBC connections

  • Eavesdropping and Data Theft
  • Data Tampering
  • Falsifying User Identities
  • Password-Related Threats

Data flowing over the network is prone to network sniffers, be it insider or outside you company. Any one can pick up these data packets and tamper with them.

Imagine you send a query for transfer of balance for $100 from Account A to Account B. Someone could intercept this request and just play around with the zeroes (This is only hypothetical. I sure shall try this out).

Since a picture is worth a thousand words, let us look at a typical application environment.

Application Infrastructure

Application Infrastructure

I believe now it is clear as to how your JDBC connections can get insecure.

Now we shall look into how to get around these issues. To solve these security challenges we have two special features that can be used

  • Data Encryption
  • Data Integrity

In simple lay man terms, it means that your JDBC calls will be transparently encrypted using standard encryption algorithms, there by making your data transfer secure. Secondly your data will be hashed to form messages digests, there by preventing data tampering. So that’s it. Let us get into action.

In order to encrypt and hash the data, certain configuration has to be done both at the client end and the server end. We shall look into them one at a time.

Client Configuration

This is one the easiest steps. You will only have to tell your JDBC driver to encrypt and digest the message as and when you make JDBC calls. Lets looks at a sample code

package com.datel.secure;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import oracle.net.ano.*;

public class StartAction {

    // The machine on which the database resides
    public final static String hostName    = "127.0.0.1";
    // The TNS listener port
    public final static String port  = "1521";
    // The database name (SID)
    public final static String databaseSID = "home";
    // The database User login
    public final static String userName    = "scott";
    // The database user password
    public final static String password    = "tiger";	 

    Connection connection;  

    public static void main(String[] args) {
		// TODO Auto-generated method stub
		new StartAction().makeDbConnection();
	}

	 public void makeDbConnection(){
		    try{

		      DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

		      // Form the database connect string using the connection parameters
		      // as specified in ConnectionParams.java
		      String dbConnectString ="@"+StartAction.hostName+":"+
		          							StartAction.port+":"+
		          							StartAction.databaseSID;

		      Properties prop = new Properties();

		      // Set the user name and password property
		      prop.put("user", StartAction.userName);
		      prop.put("password", StartAction.password);

		      int level = AnoServices.REQUIRED;

		      // Set the Client encryption level
		      prop.put("oracle.net.encryption_client", Service.getLevelString(level));

		      // Set the Client encryption selected list
		      prop.put("oracle.net.encryption_types_client", "(RC4_40)");

		      // Set the Client integrity level
		      prop.put("oracle.net.crypto_checksum_client", Service.getLevelString(level));

		      // Set the client integrity selected list
		      prop.put("oracle.net.crypto_checksum_types_client", "( MD5 )");

		      connection = DriverManager.getConnection("jdbc:oracle:thin:"+dbConnectString,prop);

		      if ( connection != null )
		      {

		    	  Statement stmt = connection.createStatement();
		    	  ResultSet rs;
		    	  rs = stmt.executeQuery("SELECT * from EMP"); 

		    	  while (rs.next()) {
		              String lastName = rs.getString("sal");
		              System.out.println(lastName + "\n");
		           }

		      }

		    } catch(SQLException ex){
		    	//Trap SQL errors

		    	ex.printStackTrace();

		    } catch(Exception ex){
		    	ex.printStackTrace();
		    }

		  }

}

  • The first thing that you would have noticed different is the client encryption level. I have set it to REQUIRED by setting the property oracle.net.encryption_client. This value signifies, encryption is required and mandated at the client end without which the connection would fail. It supports four different legal values. They are REJECTED, ACCEPTED, REQUESTED and REQUIRED. Similar configuration is required at the server end which we shall see in the server configuration. That means we can have 16 different combinations between client and server. I prefer to leave both the Client and the Server as REQUIRED, because it enforces the encryption security check and cannot be bypassed.
  • The next property that is set is oracle.net.encryption_types_client.This tells the JDBC driver to follow RC4_40 encryption standard. There are other encryption standards like DES and Triple DES. Possible values are RC4_256; RC4_128; RC4_56; RC4_40; 3DES112; 3DES168
  • The next property set is oracle.net.crypto_checksum_client. This tells the JDBC driver to generate checksums for the data and its values can also be REJECTED; ACCEPTED; REQUESTED; REQUIRED.
  • The last property that is set is oracle.net.crypto_checksum_types_client. This tells the JDBC diver to follow the MD5 hashing algorithm to form checksums.

If you were to run this code you would obviously get an error message which states that encryption is not enabled on the server. So let us step into the server configuration.

Server Configuration

On your database server access the Oracle Net Manager. You could find this at Start->Programs->OracleHome->Configuration and Migration Tools->Oracle Net Manger on your database server. Actually this Oracle utility does nothing special but writes to your SQLNET.ORA .You could directly edit this file or else use this utility. So fire up the application and you would see a screen such as this

Oracle Net Manager

Now click on the Profile properties which will bring up another screen. Choose Oracle Advance Security from the drop down list.

Set the encryption type to Required and Selected methods to RC4_40. If you recall this is the same encryption setting that was enabled on the client. The noticeable difference is the encryption seed. Set some hard difficult string in this field. This is used by oracle to encrypt the data in its algorithms. Next chose the integrity tab which fires up this screen

Here we select the similar configurations as the client. Checksum level is Required and the Selected method is MD5

Now go to File->Save Network Configuration. If you want to see where these properties are save go to you Oracle Home folder. Under Network->Admin there will be a file called SQLNET.ORA which would look something like follows

# sqlnet.ora Network Configuration File: c:\OraHome_1\NETWORK\ADMIN\sqlnet.ora

# Generated by Oracle configuration tools.

SQLNET.AUTHENTICATION_SERVICES= (NTS)

SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER= (MD5)

SQLNET.ENCRYPTION_SERVER = required

NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)

SQLNET.CRYPTO_SEED = somerandomlonghardstring

SQLNET.ENCRYPTION_TYPES_SERVER= (RC4_40)

SQLNET.CRYPTO_CHECKSUM_SERVER = required

There are ways to check if your encryption is working or not. I shall give you a hint thought. You can just check your database trace files. It would log something as follows


[29- -2008 15:49:06:398] nau_adi: exit
[29- -2008 15:49:06:398] na_tns: authentication is not active
[29- -2008 15:49:06:398] na_tns: encryption is active, using RC4_40
[29- -2008 15:49:06:398] na_tns: crypto-checksumming is active, using MD5
[29- -2008 15:49:06:398] na_tns: exit
….

Now fire up your application and enjoy transparent network encryption.

Advertisements

Read Full Post »