Developing Secure Java Code - Best Practices for a Team

1

Developing Secure Java Code - Best Practices for a Team

The following article shall introduce to us the basic practices to be followed to write secure Java code.

A development team designs an application to perform specific tasks based on functional requirements and test cases whereas an attacker will try to exploit any action that an application can be made to do, any action that is not specifically disallowed is allowed.

It's essential for development teams to grasp that client-side controls like user based inputs, fields and interface control, both inputs and validations, provide little or no security advantages. An attacker can use tools like client-side web proxies such as OWASP WebScarab, Burp proxy or network packet capturing tools such as WireShark to analyze application traffic and submit custom built requests, bypassing the interface completely. Finally, Java Applets, Flash, and other client side objects can be decompiled and examined for security loop-holes.

Moreover, Java applications are gullible to attacks because they accept untrusted user input and interact with complex subsystems. Injection attacks such as cross-site scripting [XSS], XPath, and LDAP injection are possible when the components are susceptible, easy to attack, and are used in the application. An effective mitigation strategy is to whitelist input and encode or escape output before it is processed.

Working together as a Team

As you write code, follow the development rules for improving code functionality, security, performance, and maintainability.

Verify as soon as each piece of code is completed or modified, use unit level reliability testing to verify that it's functional and secure.

Verify as soon as each piece of code is completed or modified, use unit level functional testing to verify that it's implemented correctly and functions properly.

Use regression testing to make sure that each piece of code continues to operate correctly as the functionality is added or code is modified.

Maintain separate branches for all commits related to security and merge it into the master branch after a review by multiple team members.

Have a document that documents the Java secure coding standards. It is also important to make sure that you always stick to these standards. Spend time in updating those standards.

Have a Java security testing checklist to validate that the security fix works.

PRATEEK GIANCHANDANI

1



2

Have a list of certain libraries and common functions for fixing the most common type of vulnerabilities.

All the above steps can be automated to promote a quick implementation and allow your team to see the potential benefits without disturbing the development efforts or adding extra work to your already hectic schedule.

A basic approach that should be kept in mind to write security-critical Java code is as following:

Limit the lifetime of sensitive data

Data such as login credentials in memory can be vulnerable to compromise. A fellow user who can execute code on the same system as an application may be able to access such data if the application,

That uses objects to return any sensitive data whose contents are not cleared or junkcollected right after use.

Noncompliant Code: The following code reads the username & password from the console and stores the password as a String object; the credentials remain exposed until the garbage collector recollects the value.

String user = a.readLine("Enter your ID:"); String pass = a.readLine("Enter your pass:");

Compliant Code: The following code uses the Console.readPassword() method to obtain the password from the console.

String user = a.readLine("Enter your ID:"); char[] pass = a.readPassword("Enter your pass:");

PRATEEK GIANCHANDANI

2



3

Use conservative file naming conventions

File and path names containing particular characters or character sequences can cause problems when used in the construction of a file or path name:

Leading dashes: Leading dashes could create problems when programs are called with the file names as a parameter because the first character or characters of the file name might be interpreted as a switch for the options.

Control characters: like newlines, carriage returns, and escape. Spaces: Spaces can cause problems with scripts and particularly when double quotes are

not used to surround the file name.

Noncompliant code: File a = new File("A\uD8AB"); OutputStream out = new FileOutputStream(c);

The above code on an Ubuntu machine returns will generate the following filename output: A?

Compliant code: File a = new File("name.ext"); OutputStream out = new FileOutputStream(a);

Using an expressive file name with only the subset of ASCII mentioned previously.

Prevent code injection

Code injection involves injecting malicious code into an application, which will be executed within the context of the application. There are several ways in which Java code could be injected into an application with the use of scripting API, or dynamic JSP includes.

Example: The following code allows a user to inject arbitrary Javascript into Java's script engine.

PRATEEK GIANCHANDANI

3



4

import javax.script.*;

public class Ex1 { public static void main(String[] args) { try { ScriptEngineManager man1 = new ScriptEngineManager(); ScriptEngine engine = man1.getEngineByName("JavaScript"); System.out.println(args[0]); engine.eval("print('"+ args[0] + "')"); } catch(Exception e) { e.printStackTrace(); } }

}

In the above scenario, the attacker tries to inject code that creates a file on the file system. hallo'); var fImport = new JavaImporter(java.io.File); with(fImport) { var f = new File('new'); f.createNewFile(); }

Compliant Solution (Whitelisting):

The best defense to cope up against the code injection vulnerabilities is to prevent the inclusion of executable user input in code. Any user input that is used in dynamic code must be first sanitized, for instance, to ensure that it contains only valid, whitelisted characters.

private static void evalScript(String firstName) throws ScriptException { // Allow only alphanumeric and underscore chars in firstName // (modify if firstName may also include special characters) if (!firstName.matches("[\\w]*")) { // String does not match whitelisted characters throw new IllegalArgumentException(); }

ScriptEngineManager man1 = new ScriptEngineManager(); ScriptEngine engine = man1.getEngineByName("javascript"); engine.eval("print('"+ firstName + "')"); }

PRATEEK GIANCHANDANI

4



5

Prevent XPath Injection

Extensible Markup Language (XML) can be used for data storage like a relational database. Data is frequently retrieved from such an XML document using XPaths. XPath injection can occur when data supplied to an XPath retrieval routine to retrieve data from an XML document is used without proper sanitization. This attack is similar to SQL injection or XML injection. An attacker can enter valid SQL or XML constructs in the data fields of the query in use.

XML Path Injection Example Consider the following XML schema:

john d542353kij789f5

doe 2d187h6x29d098kn1 dena jb18dh12a36dh4z7

The passwords are hashed for illustrative purposes.

Any untrusted code may attempt to try and extract the user details from this file with an XPath statement created dynamically from user input. //users/user[username/text()='&LOGIN&' and password/text()='&PASSWORD&' ]

If an attacker knows that John is a valid user name, he or she can specify an input such as john' or '1'='1

This yields the following query string. //users/user[username/text()='john' or '1'='1' and password/text()='xxxx']

PRATEEK GIANCHANDANI

5



................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download