OS Command Injection - Java

OS Command Injection - Java

Need

Prevention of OS command injection attacks

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for building Java web applications with Servlets

Description

Non compliant code

        import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CommandInjectionServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String ipAddress = request.getParameter("ip");
        String command = "ping " + ipAddress;
        Runtime.getRuntime().exec(command);
    }
}
        
        

The code above shows a simple Java servlet that handles HTTP GET requests. In the doGet method, it retrieves a parameter named "ip" from the HTTP request, and then uses it to build a command string which is then executed by the exec method of Runtime.getRuntime().

The vulnerability lies in the fact that the "ip" parameter is directly concatenated into the command string without any sanitization or validation. This means if an attacker sends a request with a malicious "ip" parameter, they could inject arbitrary commands to be executed on the server. For example, an attacker could send a request with the "ip" parameter set to " 127.0.0.1; rm -rf /", which would cause the server to execute a command that deletes all files on the server.

This is an example of an OS command injection vulnerability, where the application allows the execution of functions or methods which execute commands in the system with non-sanitized parameters. This could allow an attacker to escalate privileges, obtain or modify sensitive information stored on the server, or perform other malicious actions.

Steps

  • Input validation and sanitization: Validate and sanitize all user inputs, especially those used in command execution.
  • Use parameterized queries: Instead of concatenating user inputs directly into the command, use parameterized queries or prepared statements to ensure that user inputs are treated as data and not as executable code.
  • Whitelist allowed characters: Create a whitelist of allowed characters for user inputs and reject any input that contains characters outside of the whitelist.
  • Limit privileges: Run the command execution code with the least privileges necessary to perform the required task. Avoid running commands with root/administrator privileges.
  • Use a secure execution method: Instead of using the 'exec' method, consider using a safer alternative that provides better control and security, such as using a library or framework that handles command execution securely.
  • Implement strong access controls: Ensure that only authorized users have access to the vulnerable code and restrict access to sensitive system resources.
  • Regularly update and patch dependencies: Keep all dependencies and libraries up to date to mitigate any known vulnerabilities that could be exploited.
  • Implement logging and monitoring: Implement logging and monitoring mechanisms to detect and respond to any suspicious or malicious activities related to command execution.

Compliant code

        import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.regex.Pattern;

public class CommandInjectionServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String ipAddress = request.getParameter("ip");

        // Validate and sanitize the input
        if (isValidIP(ipAddress)) {
            String[] command = {"ping", ipAddress};
            Runtime.getRuntime().exec(command);
        }
    }

    // Validate IP address using regex
    private boolean isValidIP(String ip) {
        String IPADDRESS_PATTERN = "^([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\." +
                "([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\." +
                "([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\." +
                "([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])$";
        Pattern pattern = Pattern.compile(IPADDRESS_PATTERN);
        return pattern.matcher(ip).matches();
    }
}
        
        

The updated code includes a method isValidIP that validates the IP address using a regular expression. This method checks if the IP address is in the correct format and only contains valid characters. If the IP address is valid, the command is executed. If not, the command is not executed.

This approach prevents OS command injection by ensuring that only valid IP addresses are used in the command. The command is also executed using an array of strings, which prevents the command from being modified by an attacker.

This solution addresses the OS command injection vulnerability by implementing input validation and sanitization (step 1), using parameterized queries (step 2), and creating a whitelist of allowed characters (step 3).

However, it's important to note that this solution does not address all the steps mentioned in the vulnerability fix. For a complete solution, you should also consider running the command execution code with the least privileges necessary (step 4), using a secure execution method (step 5), implementing strong access controls (step 6), regularly updating and patching dependencies (step 7), and implementing logging and monitoring (step 8).

References