Guide to solving security issues during Java Coding

Source: Internet
Author: User
Tags object serialization websphere application server
In this article, we discuss 13 different static exposure techniques. For each type of exposure, we explain the impact of not dealing with these security issues. We also recommend some rules for you to develop robust and secure Java applications that are not threatened by these static security exposures. When appropriate, we provide code samples (both exposed code and exposed code ).

Techniques for dealing with High severity exposures
Follow the following suggestions to avoid high-severity static security exposure:

Restrict access to variables
Make every class and method final unless there is enough reason not to do so
Do not rely on the package Scope
Make the class unreadable
Make the class unserializable
Make class irreversible serialization
Avoid hard-coded sensitive data
Search for malicious code
Restrict access to variables
If the variable is declared as public, the external code can operate on the variable. This may cause security exposure.

Impact
If the instance variable is public, you can directly access and operate on the instance variable on the class instance. Declaring instance variables as protected does not necessarily solve this problem: Although it is impossible to directly access such variables on the basis of the class instance, you can still access this variable from the derived class.

Listing 1 demonstrates the code with a public variable, which is exposed because the variable is public.

Listing 1. Code with public variables
Class test {
Public int ID;
Protected string name;

Test (){
Id = 1;
Name = "Hello World ";
}
// Code
}

Public class myclass extends test {
Public void methodillegalset (string name ){
This. Name = Name; // This shoshould not be allowed
}

Public static void main (string [] ARGs ){
Test OBJ = new test ();
OBJ. ID = 123; // This shoshould not be allowed
Myclass MC = new myclass ();
MC. methodillegalset ("illegal set value ");
}
}

 

Suggestions
Generally, the value method should be used instead of the Public variable. According to the specific treatment principles of specific issues, when determining which variables are particularly important and should be declared as private, please compare the convenience and cost of coding with the security needs. Listing 2 demonstrates the following code to ensure security:

Listing 2. Code without public variables
Class test {
Private int ID;
Private string name;

Test (){
Id = 1;
Name = "Hello World ";
}
Public void setid (int id ){
This. ID = ID;
}
Public void setname (string name ){
This. Name = Name;
}
Public int GETID (){
Return ID;
}
Public String getname (){
Return name;
}
}

 

Make all classes and Methods final
Classes and methods that cannot be extended should be declared as final. This prevents code extension classes outside the system and modifies the behavior of classes.

Impact
Declaring a class as non-public does not prevent attackers from extending the class, because the class can still be accessed from its own package.

Suggestions
Make every class and method final unless there is enough reason not to do so. We recommend that you discard scalability, although it is one of the main advantages of using object-oriented languages such as Java. Scalability becomes your enemy when trying to provide security. scalability only provides attackers with more troublesome methods.

Do not rely on the package Scope
Classes, methods, and variables without explicitly marking public, private, or protected are accessible in their own packages.

Impact
If the Java package is not closed, attackers can introduce a new class to the package and use the new class to access the content you want to protect. Some packages such as Java. Lang are closed by default, and some JVMs allow you to close your own packages. However, you 'd better assume that the package is not closed.

Suggestions
From the software engineering point of view, the package scope is significant because it can prevent accidental and unintentional access to the content you want to hide. But do not rely on it for security. Classes, methods, and variables should be explicitly labeled as public, private, or protected that suits your specific needs.

Make the class unreadable
Cloning allows you to easily copy class instances without the constructor.

Impact
Even if you have no intention of cloning a class, the external source can define the subclass of your class and implement java. Lang. cloneable. This allows attackers to create new instances of your class. Copying the memory image of an existing object generates a new instance. Although this is an acceptable method for generating a new object, it is unacceptable in most cases. Listing 3 illustrates the code exposed by cloning:

Listing 3. Clone code
Class myclass {

Private int ID;
Private string name;

Public myclass (){
Id = 1;
Name = "haryporter ";
}

Public myclass (int id, string name ){
This. ID = ID;
This. Name = Name;
}

Public void display (){
System. Out. println ("ID =" + ID +"
"+" Name = "+ name );
}
}
// Hackers code to clone the user class

Public class hacker extends myclass implements cloneable {

Public static void main (string [] ARGs ){
Hacker hack = new hacker ();
Try {
Myclass o = (myclass) Hack. Clone ();
O. Display ();
}
Catch (clonenotsupportedexception e ){
E. printstacktrace ();
}
}
}

 

Suggestions
To prevent the class from being cloned, add the method shown in Listing 4 to your class:

Listing 4. Make your code unclone
Public final object clone ()
Throws java. Lang. clonenotsupportedexception {

Throw new java. Lang. clonenotsupportedexception ();
}

 

If you want your class to be cloned and you have considered the consequences of this option, you can still protect your class. To do this, define a clone method as final in your class and make it dependent on a non-final clone method in one of your superclasses, as shown in listing 5:

Listing 5. Securely cloning your code
Public final object clone ()
Throws java. Lang. clonenotsupportedexception {

Super. Clone ();
}

 

The clone () method appears in the class to prevent attackers from redefining your clone method.

Make the class unserializable
Serialization allows you to save data in a class instance in an external file. You can break into the code to clone or copy the instance, and then serialize it.

Impact
Serialization is worrying because it allows external sources to get control of the internal state of your object. This external source can serialize one of your objects into a byte array that attackers can then read. This allows attackers to fully review the internal status of your objects, includes any fields marked as private. It also allows attackers to access the internal status of any referenced object.

Suggestions
To prevent objects in the class from being serialized, define the writeobject () method in Listing 6 in the class:

Listing 6. Preventing Object serialization
Private final void writeobject (objectoutputstream out)
Throws java. Io. notserializableexception {

Throw new java. Io. notserializableexception ("this object cannot
Be serialized ");
}

 

The writeobject () method is declared as final to prevent attackers from overwriting the method.

Make class irreversible serialization
By using deserialization, attackers can use external data or byte streams to instantiate classes.

Impact
The class can be deserialized regardless of whether it can be serialized. External sources can create a byte sequence that is deserialized into a class instance. This may pose a lot of risks because you cannot control the status of the deserialization object. Please turn the Inverse Sequence into another public constructor of your object? A constructor that you cannot control.

Suggestions
To prevent object deserialization, define the readobject () method in listing 7 in your class:

Listing 7. Preventing object deserialization
Private final void readobject (objectinputstream in)
Throws java. Io. notserializableexception {

Throw new java. Io. notserializableexception ("this object cannot
Be deserialized ");
}

 

This method is declared as final to prevent attackers from overwriting the method.

Avoid hard-coded sensitive data
You may try to store secrets such as encryption keys in your application or library code. For your developers, doing so will usually make things easier.

Impact
Anyone running your code can fully access the secrets stored in this method. There is nothing to prevent a programmer or virtual machine from spying on your code and learning its secrets.

Suggestions
You can store secrets in your code in a way that can only be decrypted by you. In this case, the secret lies only in the algorithm used by your code. There is no harm in doing so, but don't be proud to think that doing so provides strong protection. Can you hide your source code or bytecode? That is, how to encrypt the source code or bytecode In order to decrypt the encrypted format? However, attackers are very likely to deduce the encryption format and reverse engineer the hidden code to reveal its secrets.

One possible solution to this problem is to store sensitive data in an attribute file, which can be read from the file whenever necessary. If the data is extremely sensitive, your application should use encryption/Decryption technologies when accessing attribute files.

Search for malicious code
A developer who is engaged in a certain project may intentionally introduce vulnerable code and plan to use it in the future. Such code may start a background process during initialization, which can open a backdoor for the intruder. It can also change some sensitive data.

There are three types of malicious code:

Main method in the class
Methods that have not been defined and used
Dead Code in comments
Impact
The entry point program may be dangerous and malicious. Generally, Java developers write the main () method in their classes, which helps test the functions of a single class. When classes are transferred from testing to the production environment, classes with the main () method become a potential threat to the application, because the break-in uses them as the entry points.

Check whether there are unused methods in the code. These methods will pass all the security checks during the test, because they are not called in the code? However, they may contain hard-coded sensitive data inside them (although test data ). Attackers who introduce a small piece of code may subsequently call this method.

Avoid dead code in the final application (the code in the comment ). If the hacker removes the comment on such code, the code may affect the system functionality.

You can see examples of all three types of malicious code in listing 8:

Listing 8. potentially malicious Java code
Public void unusedmethod (){
// Code written to harm the system
}

Public void usedmethod (){
// Unusedmethod (); // code in comment put with bad intentions,
// Might affect the system if uncommented
// Int x = 100;
// X = x + 10; // code in comment, might affect
// Functionality of the system if uncommented
}

 

Suggestions
The main () method (except the main () method for starting the application), unused methods, and dead code should be removed from the application code. Prior to Software Delivery and use, major developers should conduct a comprehensive code review on sensitive applications. Use the "stub" or "Dummy" class instead of the main () method to test the functions of the application.

Skills for dealing with moderate severity exposures
Follow the following suggestions to avoid moderate-severity static security exposure:

Do not rely on Initialization
Do not compare classes by name
Do not use internal classes
Do not rely on Initialization
You can allocate objects without running the constructor. These objects are not safe to use because they are not initialized by the constructor.

Impact
The verification object ensures data integrity during initialization.

For example, imagine creating an account object for a customer. A new account can be opened only when the initial account balance is greater than 0. You can perform such verification in the constructor. Some users create an account object without executing the constructor. They may create a new account with some negative values, which may cause system inconsistency and be vulnerable to further intervention.

Suggestions
Before using an object, check the initialization process of the object. To do this, each class should have a private Boolean flag set in the constructor, as shown in the class in listing 9. In each non-static method, the Code should check the value of this flag before any further execution. If the value of this flag is true, the control should proceed. Otherwise, the control should throw an exception and stop the execution. The methods called from the constructor will not check the initialization variables, because no flag is set when the method is called. Because these methods do not check the flag, they should be declared as private to prevent users from directly accessing them.

Listing 9. Use the Boolean flag to check the initialization process
Public class myclass {

Private Boolean initialized = false;
// Other variables

Public myclass (){
// Variable Initialization
Method1 ();
Initialized = true;
}

Private void Method1 () {// No need to check for initialization variable
// Code
}

Public void method2 (){
Try {
If (initialized = true ){
// Proceed with the business logic
}

Else {
Throw new exception ("illegal state of the object ");
}
} Catch (exception e ){
E. printstacktrace ();
}
}
}

 

If the object is initialized by deserialization, the verification mechanism discussed above will not work because the constructor is not called during this process. In this case, the class should implement the objectinputvalidation interface:

Listing 10. Implementing objectinputvalidation

Interface java. Io. objectinputvalidation {
Public void validateobject () throws invalidobjectexception;
}

 

All verifications should be executed in the validateobject () method. The object must also be registered by calling the objectinputstream. registervalidation () method to verify the deserialization object. The first parameter of registervalidation () is the object that implements validateobject (). It is usually a reference to the object itself. Note: any object that implements validateobject () may act as an object validators, but an object typically verifies its own reference to other objects. The second parameter of registervalidation () is an integer priority that determines the callback order. A callback with a higher priority is smaller than a higher priority. The order of callbacks within the same priority is unknown.

When the object has been deserialized, objectinputstream calls validateobject () on each registered object in the order of priority from high to low ().

Do not compare classes by name
Sometimes, you may need to compare the classes of two objects to determine whether they are the same; or, you may want to see if an object is an instance of a specific class. Because JVM may include multiple classes with the same name (classes with the same name but in different packages), you should not compare classes by name.

Impact
If you compare a class by name, you may have no intention of granting the class that you do not want to grant to others, because the intruder can define a class with the same name as your class.

For example, suppose you want to determine whether an object is an instance of the class com. Bar. Foo. Listing 11 demonstrates the error method for completing this task:

Listing 11. Comparison errors
If (obj. getclass (). getname (). Equals ("foo") // wrong!
// Objects class is named foo
} Else {
// Object's class has some other name
}

 

Suggestions
When you have to compare classes by name, you must be extremely careful. Make sure that the current namespace of the classloader of the current class is used, as shown in listing 12:

Listing 12. Better comparison methods
If (obj. getclass () = This. getclassloader (). loadclass ("com. Bar. foo ")){
// Object's class is equal
// The class that this class cballs "com. Bar. foo"
} Else {
// Object's class is not equal to the class that
// This class call" com. Bar. foo"
}

 

However, a better way to compare classes is to directly compare class objects to see if they are equal. For example, if you want to determine whether two objects a and B belong to the same class, you should use the code in listing 13:

Listing 13. directly compare objects to see if they are equal
If (A. getclass () = B. getclass ()){
// Objects have the same class
} Else {
// Objects have different classes
}

 

Use as few direct names as possible for comparison.

Do not use internal classes
Java bytecode does not have the concept of an internal class, because the compiler converts an internal class into a common class. If the internal class is not declared as private, then, any code in the same package can access this normal class.

Impact
Because of this feature, malicious code in the package can access these internal classes. If the internal class can access fields of the external class, the situation will become worse. These fields may have been declared as private, so that the internal class is converted to an independent class, but when the internal class accesses the fields of the external class, the compiler will remove these fields from the private) is valid within the package scope. The internal class exposure is bad enough, but what's worse is that the compiler makes it futile for you to make certain fields private.

We recommend that you do not use an internal class if you do not use an internal class.

Tips for dealing with Low severity exposures
Follow the following suggestions to avoid low-severity static security exposure:

Avoid returning mutable objects
Check local method
Avoid returning mutable objects
The Java method returns a copy of the object reference. If the actual object is changeable, then using such a reference caller may change its content, which we usually don't want to see.

Impact
Consider this example: A method returns a reference to an internal array of sensitive objects, assuming that the caller of this method does not change these objects. Even if the array object itself cannot be changed, you can operate the content of the array outside the array object, which will be reflected in the object that returns the array. If this method returns changeable objects, things will get worse; external entities can change the public variables declared in that class, which will be reflected in the actual object.

Listing 14 demonstrates the vulnerability. The getexposedobj () method returns the reference copy of the exposed object, which is variable:

Listing 14. Returning a reference copy of a mutable object
Class exposed {
Private int ID;
Private string name;

Public exposed (){
}
Public exposed (int id, string name ){
This. ID = ID;
This. Name = Name;
}
Public int GETID (){
Return ID;
}
Public String getname (){
Return name;
}
Public void setid (int id ){
This. ID = ID;
}
Public void setname (string name ){
This. Name = Name;
}
Public void display (){
System. Out. println ("ID =" + ID + "name =" + name );
}
}

Public class exp12 {
Private exposed exposedobj = new exposed (1, "Harry Porter ");

Public exposed getexposedobj (){
Return exposedobj; // returns a reference to the object.

}
Public static void main (string [] ARGs ){
Exp12 exp12 = new exp12 ();
Exp12.getexposedobj (). Display ();
Exposed exposed = exp12.getexposedobj ();
Exposed. setid (10 );
Exposed. setname ("hacker ");
Exp12.getexposedobj (). Display ();
}
}

 

Suggestions
If the method returns a changeable object, but you do not want to call the program to change the object, modify the method so that it does not return the actual object but returns its copy or clone. To correct the code in listing 14, make it return a copy of the exposed object, as shown in listing 15:

Listing 15. Returning a copy of a mutable object
Public exposed getexposedobj (){
Return new exposed (exposedobj. GETID (), exposedobj. getname ());
}

 

Alternatively, your code can return the clone of the exposed object.

Check local method
The local method is a Java method, and its implementation is written in another programming language, such as C or C ++. Some developers implement local methods because the Java language is slower than many compiled languages even when using the real-time (just-in-time) compiler. Others need to use local code to implement Platform-specific functions outside JVM.

Impact
When using local code, be careful because it is impossible to verify the code and the local code may potentially allow the applet to bypass the General Security Manager) and Java to control device access.

Suggestions
If you have to use the local method, check these methods to confirm:

What do they return?
What do they get as parameters?
Does they bypass security checks?
Are they public or private?
Whether they contain method calls that bypass the packet boundary and bypass packet Protection
Conclusion
Writing secure Java code is very difficult, but this article describes some feasible practices to help you write secure Java code. These suggestions do not resolve all your security issues, but they will reduce the number of exposures. Best software security practices can help ensure the normal operation of the software. Security is critical and highly reliable. system designers always spend a lot of energy analyzing and tracking software behavior. Is security only treated as critical system features? And from the very beginning, we can build it into the application, so that we can avoid the same security method of repairing and completing.

References

Click the discussion at the top or bottom of the article to join the Forum.

Learn more about Java security APIs.

Developerworks security topics usually contain excellent resources related to computer security.

Larry koved, Anthony J. "The Evolution of Java security" (developerworks, 1998) written by nadalin, Don Neal, and Tim Lawson jointly discussed the early development of Java security models.

Sing Li told developers in his Java Security Series (composed of two parts) (developerworks, February 2001) that although the community may have to reconsider the security design in Java 2, there is still a consistent development that only helps developers to meet their needs:
Part 1
Part 2

"Statically scanning Java code for security vulnerabilities" (IEEE software, September 2000) co-authored by John viega, Tom mutdosch, Gary McGraw, and Ed Felten introduced a Java tool, you can use this tool to check security vulnerabilities in your Java code.

Securing Java: getting down to business with mobile code (John Wiley and Sons, 1998) written by G. McGraw and E. Felten in collaboration deeply covers Java security. (The document is in pdf format .)

Regularly examine the IBM research Java security page so that IBM can track this innovation when there are significant developments in the security field.

If your Java code runs on the S/390 system, you will need to check the S/390 Java security page for additional information.

About the author
Bijaya Nanda Sahu is a software engineer at IBM Global Services in India. He has worked in various Internet technologies and frameworks (J2EE, wsbcc, jade), WebSphere related technologies, UML and OOAD. At present, he is engaged in Internet Banking security issues, focusing on WebSphere Application Server and Portal Server. Can contact him via bijaya.sahu@in.ibm.com

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.