Secure Coding

How To Find Vulnerabilities in Java Platform Source Code

Sharing is caring!

This section describes ways to acquire user-supplied input, ways to interact with the user’s session, potentially dangerous APIs, and security-relevant configuration options on the Java platform.

Identifying User-Supplied Data

Java applications acquire user-submitted input via the javax.servlet.http.HttpServletRequest interface, which extends the javax.servlet.ServletRequest interface. These two interfaces contain numerous APIs that web applications can use to access user-supplied data.

getParameter getQueryString getHeader getRequestURI getRequestedSessionIdgetInputStream getReader getRemoteUser etc.

Session Interaction

Java Platform applications use the javax.servlet.http.HttpSession interface to store and retrieve information within the current session. Per-session storage is a map of string names to object values. The APIs listed in Table 19-2 are used to store and retrieve data within the session.

Potentially Dangerous APIs

This section describes some common Java APIs that can introduce security vulnerabilities if used in an unsafe manner.

File Access

The main class used to access files and directories in Java is java.io.File.

From a security perspective, the most interesting uses of this class are calls to its constructor, which may take a parent directory and filename, or simply a pathname.
Whichever form of the constructor is used, path traversal vulnerabilities may exist if user-controllable data is passed as the filename parameter without checking for dot-dot-slash sequences.

For example, the following code opens a file in the root of the C:\ drive on Windows:

String userinput = “..\\boot.ini”;
File f = new File(“C:\\temp”, userinput);

The classes most commonly used for reading and writing fi le contents in Java are:

-java.io.FileInputStream
-java.io.FileOutputStream
-java.io.FileReader
-java.io.FileWriter

These classes take a File object in their constructors or may open a file themselves via a filename string, which may again introduce path traversalvulnerabilities if user-controllable data is passed as this parameter.

For example:
String userinput = “..\\boot.ini”;
FileInputStream fis = new FileInputStream(“C:\\temp\\” + userinput);

Database Access

The following are the APIs most commonly used for executing an arbitrary string as a SQL query:

-java.sql.Connection.createStatement
-java.sql.Statement.execute
-java.sql.Statement.executeQuery

If user-controllable input is part of the string being executed as a query, it is probably vulnerable to SQL injection.

For example:
String username = “admin’ or 1=1–”;
String password = “foo”;
Statement s = connection.createStatement();
s.executeQuery(“SELECT * FROM users WHERE username = “’ + username + “’ AND password = “’ + password + “’”);

executes this unintended query:

SELECT * FROM users WHERE username = ‘admin’ or 1=1–’ AND password = ‘foo’;

The following APIs are a more robust and secure alternative to the ones previously described. They allow an application to create a precompiled SQL statement and set the value of its parameter placeholders in a secure and type-safe way:

java.sql.Connection.prepareStatement
java.sql.PreparedStatement.setString
java.sql.PreparedStatement.setInt
java.sql.PreparedStatement.setBoolean
java.sql.PreparedStatement.setObject
java.sql.PreparedStatement.execute
java.sql.PreparedStatement.executeQuery
and so on.

If used as intended, these are not vulnerable to SQL injection. For example:

String username = “admin’ or 1=1–”;
String password = “foo”;
Statement s = connection.prepareStatement(
“SELECT * FROM users WHERE username = ? AND password = ?”);
s.setString(1, username);
s.setString(2, password);
s.executeQuery();

results in a query that is equivalent to the following:

SELECT * FROM users WHERE username = ‘admin’’ or 1=1–’ AND
password = ‘foo’

OS Command Execution

The following APIs are the means of executing external operating system commands from within a Java application:

java.lang.runtime.Runtime.getRuntime
java.lang.runtime.Runtime.exec

If the user can fully control the string parameter passed to exec, the application is almost certainly vulnerable to arbitrary command execution. For example, the following causes the Windows calc program to run:

String userinput = “calc”;
Runtime.getRuntime.exec(userinput);

However, if the user controls only part of the string passed to exec, the application may not be vulnerable. In the following example, the user-controllable data is passed as command-line arguments to the notepad process, causing it to attempt to load a document called | calc:

String userinput = “| calc”;
Runtime.getRuntime.exec(“notepad “ + userinput);

The exec API itself does not interpret shell metacharacters such as & and |, so this attack fails.

Sometimes, controlling only part of the string passed to exec may still be suffi cient for arbitrary command execution, as in the following subtly different example :

String userinput = “\\..\\system32\\calc”;
Runtime.getRuntime().exec(“notepad” + userinput);

Often, in this type of situation, the application is vulnerable to something other than code execution. For example, if an application executes the program wget with a user-controllable parameter as the target URL, an attacker may be able to pass dangerous command-line arguments to the wget process. For example, the attacker might cause wget to download a document and save it to an arbitrary location in the fi lesystem.

URL Redirection

The following APIs can be used to issue an HTTP redirect in Java:

javax.servlet.http.HttpServletResponse.sendRedirect
javax.servlet.http.HttpServletResponse.setStatus
javax.servlet.http.HttpServletResponse.addHeader

The usual means of causing a redirect response is via the sendRedirect method, which takes a string containing a relative or absolute URL. If the value
of this string is user-controllable, the application is probably vulnerable to a phishing vector.

You should also be sure to review any uses of the setStatus and addHeader APIs. Given that a redirect simply involves a 3xx response containing an HTTP Location header, an application may implement redirects using these APIs.

Sockets

The java.net.Socket class takes various forms of target host and port details in its constructors. If the parameters passed are user-controllable in any way, the application may be exploitable to cause network connections to arbitrary hosts, either on the Internet or on the private DMZ or internal network on which the application is hosted.

Join The Discussion