How to write Secure Java Code

There are many young programmers who come up to me asking for guidelines on how to write secure Java code. Most of the time they are worried about SQL Injection and Cross Site Scripting (XSS) attacks. But these are not the only concerns related to Java Security. There are many more attacks possible on a Java Application. So this post is about some basic guidelines and/or rules that can be followed by the developer to safe guard against the most common attacks. Don’t take these as the defacto standard that will prevent all kind of attacks but they can serve as the stepping stone for secure applications.

Rule 1: Don’t depend on Initialization.

Many Java programmers thinks that calling the constructor is the only way to allocate objects in Java. But this is so NOT true. There are many ways to allocate objects w/o using the constructor, the most common being using Serialization – more on this later. The easiest way for guarding against this problem is to write your classes so that before any object does anything, it checks if it has been initialized. Heres how you can do this:

  1. First make all the variables private. If you want to allow outside access to these variable make getter and setters. This keeps outside code from accessing non-initialized variables.
  2. Add a new private boolean field, initialized, to the class.
  3. Have each constructor set initialized as the last action before returning.
  4. Have each non-constructor method check that initialized is true before doing anything.

If you class has static initializer than do the same at the class level. Here are the steps:

  1. Make all static variables private. To allow outside access use static getters and setters.
  2. Add new private static boolean field classInitialized to the class.
  3. Have the static initializer set the value of classInitialized as the last action before returning.
  4. Before doing anything have each static method and each constructor check if classInitialized is true.

Rule 2: Make everything private (unless there is a good reason not to do so)

Limit access to your classes, methods and variables. Every non private Class, Variable or Method is a potential entry point for the Attacker. By default make everything private. Make something non private if there is a good reason and document that reason. Basically we are limiting the attack area here.

Rule 3: Make everything final (unless there is a good reason not to do so)

If a class or method isn’t final, an attacker could try to extend it in a dangerous and unforeseen way. By default, everything should be final. Make something non final only if there is a good reason, and document that reason.

You might think you can prevent an attacker from extending your class or its methods by declaring the class nonpublic. But if a class isn’t public, it must be accessible from within the same package.

You might think that this is pretty insane as by doing so we are sacrificing one of the tenets of Object Oriented Programming but when it comes to Security extensibility is your Enemy. It provides more ways for the attacker to cause trouble.

UPDATE: There is a possibility that the attacker can use Reflection APIs to change and inspect the values of the private/final fields as well. Java provides a solution for this by adding the package.access security property. This prevents untrusted parties from using the Reflection API on the specified package hierarchy. Here is a code sample for setting the property:

<pre>    private static final String PACKAGE_ACCESS_KEY = "package.access";
    static {
        String packageAccess = java.security.Security.getProperty(
            PACKAGE_ACCESS_KEY
        );
        java.security.Security.setProperty(
            PACKAGE_ACCESS_KEY,
            (
                (packageAccess == null || packageAccess.trim().isEmpty()) ?
                "" :
                (packageAccess + ",")
            ) +
            "xx.example.product.implementation."
        );
    }</pre>

Rule 4: Don’t depend on Package Scope.

As i said earlier, don’t depend on package scope. As the attacker can simply make another class in the same package which can access your classes, methods and variables (A few packages, such as java.lang, are closed by default, and a few Java virtual machines (JVMs) let you close your own packages. But you’re better off assuming packages aren’t closed.)

As per Java 6 security guidelines - It is recommended that as a matter of course, packages are marked as sealed in the jar file manifest.

Package scope is good from the Software Engineering standpoint but is not recommended from the security point of view.

Rule 5: Don’t use Inner Classes.

It is a misconception that inner classes are only accessible to the outer class that defines them. There is no concept of inner class at the byte code level. So the compiler translates the inner class to a full flash outer class with a package private scope. As per Rule 4 we shouldn’t depend upon the package private scope.

But wait inner class also gets access to the variables of the outer class even if they are private so how does this happen. Well the compiler silently changes the access modifier from private to package private in the outer class. It’s bad enough that the inner class is exposed; but it’s even worse that the compiler is silently overruling your decision to make some fields private. Don’t use inner classes if you can help it.

Rule 6: Avoid signing your code.

Signed code runs with special privileges so has more power to cause trouble. Try to audit the areas that need special privileges for performing actions and Try to minimize the amount of privileged code.

Code that isn’t signed will run without any special privileges. And code with no special privileges is much less likely to do damage.

Rule 7: Put all the signed code in one archive.

By doing so we prevent mix-and-match attack, in which the attacker constructs a new applet or library that links some of your signed classes together with malicious classes, or links together signed classes that you never meant to be used together. By signing a group of classes together, you make such attacks more difficult.

Rule 8: Make classes non-cloneable.

If the class is cloneable the attacker can construct an instance of the class without using the constructor. If the class is not implementing the Cloneable interface the attacker can make a sub-class and make it implement the Cloneable interface and create a clone which will allow the attacker to create new instances of your class.

The new instances are made by copying the memory images of existing objects; though this is sometimes an acceptable way to make a new object, it often is not.

You can do this by defining the following method in each of your classes:

public final void clone() throws java.lang.CloneNotSupportedException {
         throw new java.lang.CloneNotSupportedException();
}

If you want your class to be cloneable, and you’ve considered the consequences of that choice, then you can still protect yourself. If you’re defining a clone method yourself, make it final. If you’re relying on a non final clone method in one of your superclasses, then define this method:

public final void clone() throws java.lang.CloneNotSupportedException {
          super.clone();
}

Rule 9: Make your classes nonserializable.

Serialization is dangerous as it allows the attacker to serialize your object in to byte array and read the internal state of your object be it private. Not only can the attacker see the internal fields but also of the objects it references. A class can be made nonserializable by declaring the following method in the class:

private final void writeObject(ObjectOutputStream out) throws java.io.IOException {
throw new java.io.IOException("Object cannot be serialized");
}

If this is not possible declare all the fields you want the attacker from examining as transient.

Rule 10: Make your classes nondesrializable.

Prevent Serialization doesn’t mean that the class cannot be deserialized. Attacker can make a byte array which can be deserialized as an instance of the class and will have the state that attacker wants. You can make it impossible for the attacker to do that by declaring the following method in your class:

private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Class cannot be deserialized");
}

Rule 11: Don’t store secrets in your code.

It is a usual case that programmers store cryptographic keys and sometimes even license keys for third-party libraries inside the code or respective libraries. Secrets stored this was are completely accessible to the Attacker and don’t provide any Security.

Code Obfuscation can be used to protect against it but nothing is hidden from a dedicated Attacker armed with the correct tools.

I will sign-off for now. Again these are just some guidelines to get people started in the right direction. Feel free to comment by using the comments section.

Advertisement

About this entry