Skip to main content

Insecure Use of Dangerous Function

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

Untrusted input passed to dynamic evaluation function

If you have untrusted data coming from HTTP requests it's important to validate, filter, and sanitize the data before any further processing. That includes passing the data or a property of it to the Python functions eval, or exec(), which allows attackers to execute arbitrary Python code.

Rule-specific references:

Fixing Strategies

The fixing advice for this vulnerability depends largely on how the dynamic evaluation functions are used. There is no secure replacement for using exec() or eval() with untrusted input.

Fixing strategies are:

  1. Replace the dangerous functions with alternatives that achieve the desired functionality.
  2. Validate input before passing it to the dangerous function. Ensure that only expected values are processed. This is very difficult to achieve, as there may be ways to bypass the input filtering.
  3. Implement an allow list. Instead of just passing user input to the function, the use cases are well-defined and can be triggered via an option that is provided by the user.

Untrusted input passed to Paramiko exec_command

This rule detects untrusted input being passed as a parameter for exec_command(), which can lead to OS command injection.

Fixing Strategies

The fixing advice for this vulnerability depends largely on how the exec_command() function is called. There is no secure replacement for this function.

Fixing strategies are:

  1. Replace the dangerous functions with alternatives that achieve the desired functionality.
  2. Validate input before passing it to the dangerous function. Ensure that only expected values are processed. This is very difficult to achieve, as there may be ways to bypass the input filtering.
  3. Implement an allow list. Instead of just passing user input to the function, the use cases are well-defined, e.g. existing scripts on the SSH server that can be triggered via an option that is provided by the user.

Untrusted input passed to OS command execution function

This rule detects user input that is passed to Python functions that spawn operating system commands, which allows attackers to execute arbitrary commands.

Vulnerabilities in the use of the following libraries are supported by GuardRails:

Rule-specific references:

Option A: Use subprocess securely

If it's not possible to use an internal Python API instead of running an OS command, then it is recommended to use the in-built subprocess library securely.

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

  2. Replace the usage of the Python libraries commands, platform, popen2, os or even subprocess with the secure usage shown below.

    import flask
    import subprocess
    # ...
    @app.route("secure-command-execution-arg")
    def a():
    arg = flask.request.args.get("arg")
    # Secure example for passing and argument to a command
    subprocess.run(["ping", "-c1", arg])
    # ...
    @app.route("secure-command-execution-cmd")
    def b():
    cmd = flask.request.args.get("cmd")
    arg = flask.request.args.get("arg")
    allowed = {'p': "ping", 'l': "ls"}

    # Secure example for passing an allow-list for a command
    subprocess.call([allowed[cmd], arg])
  3. Test it

  4. Ship it 🚢 and relax 🌴