Skip to main content

Insecure Use of Dangerous Function

This vulnerability category covers the following issues:

Fixing Command Injection

About Command Injection

What is command injection?

Command injection is a type of security vulnerability that allows an attacker to execute arbitrary commands on a target system. It occurs when an application accepts user input as part of a command or query that is executed by the system without proper validation or sanitization.

For example, consider a web application that allows users to search for products by entering a product name. If the application does not properly sanitize user input and passes the input directly to the operating system's command shell, an attacker can insert malicious code into the input that could be executed by the command shell.

This could result in the attacker gaining unauthorized access to the system or performing other malicious actions.

Check out this video for a high-level explanation:

What is the impact of command injection?

A successful command injection attack can have a wide-ranging impact, depending on the system and the attacker's goals. Here are a few potential impacts:

  • Unauthorized access: An attacker may be able to gain unauthorized access to a system or application, giving them access to sensitive data or functionality.
  • Data theft: An attacker may be able to steal data from the system, including personally identifiable information, financial data, or other sensitive data.
  • Malware installation: An attacker may be able to install malware on the system, allowing them to further compromise the system or use it as a launching point for other attacks.
  • Denial of service: An attacker may be able to launch a denial-of-service attack by executing commands that overwhelm the system's resources, or deleting important system files.
  • System compromise: In some cases, a successful command injection attack can lead to complete compromise of the system, allowing the attacker to take full control.

How to prevent command injection?

Some measures that can help prevent command injection attacks are:

  • Input validation and sanitization: Ensure that user input is validated and sanitized before it is used in any system command. Use regular expressions or input filters to remove or encode any special characters that could be used to execute arbitrary commands.
  • Use parameterized queries: When executing commands that include user input, use parameterized queries instead of string concatenation.
  • Limit permissions: Limit the permissions of the user account that runs the application to only those that are necessary to perform its functions.
  • Perform regular security audits: Regularly audit your system and application for security vulnerabilities, including command injection vulnerabilities. Use automated tools and manual testing to identify potential issues and fix them before they can be exploited.
  • Educate your development team: Educate your development team about the risks of command injection attacks and the measures that can be taken to prevent them.

References

Taxonomies

Explanation & Prevention

Training

The highlighted APIs below are used to execute system commands. If unfiltered input is passed to these APIs, it can lead to arbitrary command execution.

References:

Option A: Use dangerous functions securely

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the dangerous function. For example:

    // Java
    import java.lang.Runtime;
    Runtime r = Runtime.getRuntime();
    r.exec("/bin/sh -c some_tool" + input);

    or:

    //Scala
    def executeCommand(value:String) = Action {
    val result = value.!
    Ok("Result:\n"+result)
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, replace the dangerous function with the following:

    // Java
    // Ensure that only safe characters are supplied
    // Otherwise don't perform the operation
    if (!Pattern.matches("[0-9A-Za-z@.]+", input)) {
    // Handle error
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Fixing Code Injection

About Code Injection

What is code injection?

Code injection is a security vulnerability that occurs when an application generates code dynamically and does not properly validate or sanitize user input before using it to generate the code.

The main difference between command injection and code injection is that command injection focuses on executing arbitrary system commands, while code injection focuses on injecting and executing arbitrary code within a program or system.

Code Injection is limited by the functionality of the injected language itself.

Check out this video for a high-level explanation:

What is the impact of code injection?

A successful code injection attack can have a wide-ranging impact, depending on the system and the attacker's goals. Here are a few potential impacts:

  • Unauthorized access: An attacker may be able to gain unauthorized access to a system or application, giving them access to sensitive data or functionality.
  • Data theft: An attacker may be able to steal data from the system, including personally identifiable information, financial data, or other sensitive data.
  • Malware installation: An attacker may be able to install malware on the system, allowing them to further compromise the system or use it as a launching point for other attacks.
  • Denial of service: An attacker may be able to launch a denial-of-service attack by executing code that overwhelms the system's resources.
  • System compromise: In some cases, a successful code injection attack can lead to the complete compromise of the system.

How to prevent code injection?

Some measures that can help prevent code injection attacks are:

  • Input validation and sanitization: Ensure that user input is validated and sanitized before it is used to generate code.
  • Perform regular security audits: Regularly audit your system and application for security vulnerabilities, including code injection vulnerabilities. Use automated tools and manual testing to identify potential issues and fix them before they can be exploited.
  • Educate your development team: Educate your development team about the risks of code injection attacks and the measures that can be taken to prevent them.

References

Taxonomies

Explanation & Prevention

Training

Whenever dynamic code is evaluated, attackers have an opportunity to influence the code, which can lead to malicious code execution resulting in data leakage or operating system compromise.

This section covers code injection related to the following APIs:

  • Script Engine
  • Spring Expression
  • Expression Language
  • Seam Logging Call
  • OGNL
  • JSP Spring Expression

Option A: Using Script Engine safely

References:

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    public void runCustomTrigger(String script) {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    engine.eval(script);
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, leverage the following pattern:

    public void runCustomTrigger(String script) {
    SandboxContextFactory contextFactory = new SandboxContextFactory();
    Context context = contextFactory.makeContext();
    contextFactory.enterContext(context);
    try {
    ScriptableObject prototype = context.initStandardObjects();
    prototype.setParentScope(null);
    Scriptable scope = context.newObject(prototype);
    scope.setPrototype(prototype);
    context.evaluateString(scope,script, null, -1, null);
    } finally {
    context.exit();
    }
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option B: Using Spring Expression safely

Solution-specific references:

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    public void parseExpressionInterface(Person personObj,String property) {
    ExpressionParser parser = new SpelExpressionParser();
    //Unsafe if the input is controlled by the user.
    Expression exp = parser.parseExpression(property+" == 'Albert'");
    StandardEvaluationContext testContext = new StandardEvaluationContext(personObj);
    boolean result = exp.getValue(testContext, Boolean.class);
    [...]
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, ensure that the user input is sanitized accordingly

    // Java
    // Ensure that only safe characters are supplied
    // Otherwise don't perform the operation
    if (!Pattern.matches("[0-9A-Za-z@.]+", property)) {
    // Handle error
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option C: Using Expression Language safely

Solution-specific references:

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    public void evaluateExpression(String expression) {
    FacesContext context = FacesContext.getCurrentInstance();
    ExpressionFactory expressionFactory = context.getApplication().getExpressionFactory();
    ELContext elContext = context.getELContext();
    ValueExpression vex = expressionFactory.createValueExpression(elContext, expression, String.class);
    return (String) vex.getValue(elContext);
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, ensure that the user input is sanitized accordingly

    // Java
    // Ensure that only safe characters are supplied
    // Otherwise don't perform the operation
    if (!Pattern.matches("[0-9A-Za-z@.]+", expression)) {
    // Handle error
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option D: Using Seam Logging Call safely

Solution-specific references:

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    public void logUser(User user) {
    log.info("Current logged in user : " + user.getUsername());
    //...
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, use the following pattern instead:

    public void logUser(User user) {
    log.info("Current logged in user : #0", user.getUsername());
    //...
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option E: Using OGNL safely

Solution-specific references:

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    public void getUserProperty(String property) {
    [...]
    //The first argument is the dynamic expression.
    return ognlUtil.getValue("user."+property, ctx, root, String.class);
    }
  3. If the functionality is not required, then remove it

  4. Otherwise, ensure that the user input is sanitized accordingly

    // Java
    // Ensure that only safe characters are supplied
    // Otherwise don't perform the operation
    if (!Pattern.matches("[0-9A-Za-z@.]+", expression)) {
    // Handle error
    }
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴

Option F: Using JSP Spring Expression safely

A Spring expression is built with a dynamic value. The source of the values should be verified to avoid unfiltered values being evaluated.

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Locate the following code pattern:

    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <spring:eval expression="${param.lang}" var="lang" />
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
    <spring:eval expression="'${param.lang}'=='fr'" var="languageIsFrench" />
  3. If the functionality is not required, then remove it

  4. Otherwise, leverage the following pattern:

    <c:set var="lang" value="${param.lang}"/>
    <c:set var="languageIsFrench" value="${param.lang == 'fr'}"/>
  5. Test it and ensure the functionality works as expected

  6. Ship it 🚢 and relax 🌴