12 Tips to write a secure java code
Anybody can write code, but writing secure code is what matters when it comes to the real life programming.
Security matters at lot to the users because you don’t want your data exposed to the world writing secure code must be learned by a budding developers.
The guidelines have taken from most of the senior developers who had a practical approach in the code.
These rules haven’t been sugar-coated for mass consumption. They get fairly technical and require broad knowledge of Java to understand. Though experienced Java developers will understand all the rules that follow, less experienced Java developers may have a bit of homework to do. Nevertheless, following these rules will make your Java code more secure.
Of course, security is an elusive goal. Following these rules certainly won’t provide any guarantee that your code is completely secure. It is easy to write insecure code that follows these rules. By following these goals, however, you will minimize or eliminate certain kinds of security attacks that you might not have thought of.
Think of these rules as a first step. If you are writing code that may be linked or run in conjunction with untrusted code, then you should definitely consider following these rules.
Every attempt has been made to keep the rules simple enough that you can treat them as a checklist to be followed in mechanical fashion. That way you can save your brainpower for other security issues.
Rule 1: Don’t depend on initialization
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 nonfinal clone method in one of your superclasses, then define this method: public final void clone() throws java.lang.CloneNotSupportedException { super.clone(); }
This prevents an attacker from redefining your clone method.
Rule 9: Make your classes nonserializeable
Serialization is dangerous because it allows adversaries to get their hands on the internal state of your objects. An adversary can serialize one of your objects into a byte array that can be read. This allows the adversary to inspect the full internal state of your object, including any fields you marked private, and including the internal state of any objects you reference.
To prevent this, you can make your object impossible to serialize. To achieve this goal, declare the writeObject method:
To prevent this, you can make your object impossible to serialize. To achieve this goal, declare the writeObject method:
private final void writeObject(ObjectOutputStream out) throws java.io.IOException { throw new java.io.IOException("Object cannot be serialized"); }
This method is declared final so that a subclass defined by the adversary cannot override it.
Rule 10: Make your classes nondeserializeable
This rule is even more important than the previous one. Even if your class isn’t serializeable, it may still be deserializeable. An adversary can create a sequence of bytes that happens to deserialize to an instance of your class. This is dangerous, since you do not have control over what state the deserialized object is in. You can think of deserialization as another kind of public constructor for your object; unfortunately it’s a kind of constructor that is difficult for you to control.
You can prevent this kind of attack by making it impossible to deserialize a byte stream into an instance of your class. You can do this by declaring the
readObject
method:private final void readObject(ObjectInputStream in) throws java.io.IOException { throw new java.io.IOException("Class cannot be deserialized"); }
As above, this method is declared final to prevent the adversary from overriding it.
Rule 11: Don’t compare classes by name
Sometimes you want to compare the classes of two objects to see whether they are the same; or you want to see whether an object has a particular class. When you do this, be aware that there can be multiple classes with the same name in a JVM. It is a mistake to compare classes by name since different classes can have the same name. A better method is to compare class objects for equality directly. For example, given two objects, A and B, if you want to see whether they are the same class, use this code:
if(a.getClass() == b.getClass()){ // objects have the same class }else{ // objects have different classes } You should also be on the lookout for cases of less direct by-name comparisons. Suppose, for example, you want to see whether an object has the class "Foo." Here is the wrong way to do it: if(obj.getClass().getName().equals("Foo")) // Wrong! // objects class is named Foo }else{ // object's class has some other name } Here's a better way to do it: if(obj.getClass() == this.getClassLoader().loadClass("Foo")){ // object's class is equal to the class that this class calls "Foo" }else{ // object's class is not equal to the class that // this class calls "Foo" }
Do note the legalistic comments in the last example. Whenever you use class names, you open yourself up to mix-and-match attacks, as described in Rule 7. You should also know that the Java language forces you to use class names all the time: in variable declarations, instanceof expressions, and exception-catching blocks. Only the designers of Java can prevent mix-and-match attacks, but you can avoid making the problem worse by avoiding by-name class comparisons.
Rule 12: Secrets stored in your code won’t protect you
You might be tempted to store secrets such as cryptographic keys in the code for your application or library. Secrets stored in this way are completely accessible to anybody who runs your code. There is nothing to stop a malicious programmer or virtual machine from looking inside your code and learning its secrets.
Code obfuscation is another way of storing a secret in your code; in the case of obfuscation the secret is simply the algorithm used by your code. There’s not much harm in using an obfuscator, but you shouldn’t believe it will provide strong protection. There is no real evidence that it is possible to obfuscate Java source code or bytecode so that a dedicated adversary with good tools cannot reverse the obfuscation.
Conclusion
Writing secure Java code is very difficult. There is no magic bullet that will solve your security problems; all you can do is think hard (perhaps with help from formal analysis tools) and use prudent engineering practices to minimize risks. Sometimes a pair of objective outside eyes can help. The rules set forth here are intended to describe prudent engineering practices for writing secure Java code. They won’t solve your security problems, but they will reduce the number of ways things can go wrong.
If you got a doubt about this article please take your time to comment us.
No comments:
Post a Comment