# OS Command Injection \[Command Execution]

## 1. Introduction:

**OS command injection** (also known as shell injection) is a **web security vulnerability** that allows an attacker to execute arbitrary operating system (OS) commands **on the server that is running an application**, and typically **fully compromise the application** and all its data.&#x20;

{% hint style="warning" %}
**Command injection attacks are possible largely** due to **insufficient input validation**.
{% endhint %}

## 2. Typical vulnerable code:

```python
import os
import sys

file = sys.argv[1]

text = os.system("cat " +  file)
```

![Here's command injection in action.](/files/-MaDCUjy-NbqxvfRNExx)

## 3. Mitigations:

{% hint style="warning" %}
You should also spend some time on the following pages since defending against injections is quite similar regardless of what vulnerable vector you are dealing with.
{% endhint %}

{% content-ref url="/pages/-MYR42HfRBIQ5rbzByHJ" %}
[SQL Injections \[SQLi\]](/secure-coding/server-side/sql-injections.md)
{% endcontent-ref %}

{% content-ref url="/pages/-MZ41QZaaLWsR1wjAySR" %}
[XML External Entity Injection \[XXE\]](/secure-coding/server-side/xxe.md)
{% endcontent-ref %}

### 3.1. Avoid calling OS commands directly:

The primary defense **in the case of OS command injection** is **using built-in functions instead**, as they **cannot be manipulated to perform any malicious task**. Here is an example:

Instead of having `os.system("mkdir " + dir_name)`, we have to use its alternative, which is `os.mkdir(dir_name)`

### 3.2. Escaping the OS commands arguments:

By **escaping the user-supplied input** we can make sure **that we capsulate it into a "safer" format** for the `os.system` command to execute. As **escaping** the user-supplied input should **be used on top of an already existing defense mechanism**, it is recommended to **avoid** using OS commands directly.

An **example of escaping OS commands is showcased in the PHP function** [escapeshellarg](https://www.php.net/manual/en/function.escapeshellarg.php). Here, the function **adds single quotes around a string** and **quotes/escapes any existing single quotes** allowing you to **pass a string directly to a shell function** and having it be **treated as a single safe argument.**

```php
<?php

    system('ls '.escapeshellarg($dir));

?>

```

### 3.3. Parametrization with input validation:

Should calling **os commands on user-supplied input** be ***unavoidable*** (although it almost always is), a developer can make use of the following **two defensive layers**. As discussed in the SQLi section, one can defend their endpoint with:

1. **Parameterization:** If available, use structured mechanisms that automatically enforce the separation between data and command. These mechanisms can help provide the relevant quoting and encoding.
2. **Input validation:** The values for commands and the relevant arguments should be both validated. There are different degrees of validation for the actual command and its arguments:

* When it comes to the **commands** used, these must be validated against a list of allowed commands.
* In regards to the **arguments** used for these commands, they should be validated using the following options:
  * **Positive or allow list input validation**: Where are the arguments allowed explicitly defined.
  * **Allow list Regular Expression**: Where a list of safe, allowed characters and the maximum length of the string are defined. Ensure that metacharacters, like these:&#x20;

    ```
    & |  ; $ > < ` \ !
    ```

    &#x20;and white spaces are not part of the Regular Expression. For example, the following regular expression **only allows lowercase letters** and numbers and does **not contain metacharacters**. The length is also being limited to 3-10 characters: `^[a-z0-9]{3,10}$`

{% hint style="warning" %}
Ideally, a developer should use an existing API/ libraries for their language. For example (Python): Rather than use `os.system()` to issue a **`mail`** command, use the available Python `mail` library.

If no such available API exists, the developer **should scrub all input for malicious characters**. Typically, it is **much easier to define** the **legal** characters than the **illegal** characters.
{% endhint %}

### 3.4. Additional Defenses: <a href="#additional-defenses" id="additional-defenses"></a>

On top of primary defenses, parameterizations, and input validation, it is also recommended adopting all of these extra defenses:

* Applications **should run using the lowest privileges** that are required to accomplish the necessary tasks.
* If possible, **create isolated accounts** with **limited privileges** that are only used for **a single task**.

## 4. Takeaways:

**Avoiding directly calling OS commands** is an obvious first step towards defending against command injection. As it should be a standard by now, when dealing with **user supplied input**, a developer should always make sure to **escape as well as validate it.**

{% hint style="info" %}
You can find more resources on this topic here:

* [OS Command Injection Defense\[OWASP\]](https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html)
* [Command Injection\[OWASP\]](https://owasp.org/www-community/attacks/Command_Injection)
  {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://vladtoie.gitbook.io/secure-coding/server-side/os-command-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
