...
Consequently, command injection doesn't work unless a command interpreter is explicitly invoked. However, particularly on Windows, there can be vulnerabilities where arguments have spaces, double quotes, etc., in or start with a - or / to indicate a switch.
...
This compliant solution sanitizes the email address folder by permitting only a handful of correct characters to appear.
Code Block | ||
---|---|---|
| ||
String address = System.getProperty("email"); if (address == null) { // handle error }... if (!Pattern.matches("[0-9A-Za-z@.]+", addressdir)) { // Handle error } Runtime runtime = Runtime.getRuntime(); Process proc = runtime.exec("mail " + address); // ... |
Although this is a compliant solution, the sanitization method is weak because : it will reject valid
...
Code Block |
---|
"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b") |
...
directories. Also since the command interpreter invoked is system dependent,
...
it is difficult to say that this solution will not allow command injection
...
on every
...
possible platform in which a Java program might run.
Compliant Solution (
...
Restricted user choice)
A further improvement to the previous This compliant solution is to parametrize the call to the prevents command injection by only passing trusted strings to Runtime.exec()
method. There are six forms of the exec()
method, most of which are convenience methods for the following method:
Code Block |
---|
public Process exec(String[] cmdarray,
String[] envp,
File dir)
throws IOException
|
Using any form of the exec()
method where the first argument is an array containing the command to call and its arguments is generally safer because the command itself does not contain untrusted data.
Code Block | ||
---|---|---|
| ||
String address = System.getProperty("email");
if (address == null) {
// handle error
}
if (!Pattern.matches("[0-9A-Za-z@.]+", address)) {
// Handle error
}
String[] command = {"mail", address};
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(command, null, null);
|
In some cases, this can still result in an argument injection attack.
Compliant Solution (Not passing untrusted data to the exec()
method)
This compliant solution prevents command injection by requiring the user to select one of a predefined group of addresses. This prevents untrusted data from being added to the command.
While the user has control over which string gets used, the user cannot send strings directly to Runtime.exec()
.
Code Block | ||
---|---|---|
| ||
String addressdir = null; int filenamenumber = Integer.parseInt(System.getproperty("addressdir")); // only allow integer choices switch(filenamenumber) { case 1: addressdir = "root@localhostdata1" break; // Option 1 case 2: addressdir = "postmaster@localhostdata2" break; // Option 2 default: // invalid break; } if (addressdir == null) { // handle error } Runtime runtime = Runtime.getRuntime(); Process proc = runtime.exec("mail " + address); |
This compliant solution hard codes the directories that may be listed.
This solution can quickly become email addresses which becomes unmanageable if you have many email addressesavailable directories. A more extensible solution is to read all the email addresses from a properties file into a java.util.Properties
object.
Compliant Solution (Avoid Runtime.exec()
)
When the task performed by executing a system command can be accomplished by some other means, it is almost always advisable to do so. This compliant solution uses the File.list()
method to provide directory listing, thereby preventing command injection.
Code Block | ||
---|---|---|
| ||
import java.io.File;
class DirList {
public static void main(String[] args) throws Exception {
File dir = new File(System.getProperty("dir"));
if (!dir.isDirectory()) {
System.out.println("Not a directory");
} else {
for (String file : dir.list()) {
System.out.println(file);
}
}
}
}
|
Risk Assessment
OS command injection can cause arbitrary programs to be executed.
...