If an attacker can execute arbitrary code on your servers, your systems
are almost certainly going to be compromised. You need to take great
care when designing how your web server interacts with the underlying operating
system.

Risks

Prevalence

Common

Exploitability

Moderate

Impact

Devastating

Remote code execution is a major security lapse, and
the last step along the road to complete system takeover. After gaining access,
an attacker will attempt to escalate their privileges on the server,
install malicious scripts, or make your server part of a botnet to be
used at a later date.

Command injection vulnerabilities often occur in older, legacy code,
such as CGI scripts.

Protection

If your application calls out to the operating system, you need to be sure command
strings are securely constructed, or else you risk having malicious instructions injected
by an attacker. This section outlines a few approaches to protecting yourself.

Try to Avoid Command Line Calls Altogether

Modern programming languages have interfaces that permit you to read files,
send emails, and perform other operation system functions. Use
APIs wherever possible – only use shell commands where
absolutely necessary. This will reduce the number of attack vectors
in your application, and will also simplify your codebase.

Escape Inputs Correctly

Injection vulnerabilities occur when untrusted input is not
sanitized correctly. If you use shell commands, be sure to
scrub input values for potentially malicious characters:

;

&

|

`

Even better, restrict input by testing it against a regular expression
of known safe characters. (For example, alphanumeric characters.)

Restrict the Permitted Commands

Try to construct all or most of your shell commands using string literals,
rather than user input. Where user input is required, try to whitelist
permitted values, or enumerate them in a conditional statement.

Perform Thorough Code Reviews

Check system calls for vulnerabilities as a part of your
code review process. Vulnerabilities often creep in over time – make
sure your team knows what to look for.

Run with Restricted Permissions

It is a good practice to run your server processes with only the
permissions that they require to function – the principle of least privilege.
This can help limit the impact of command
injection vulnerabilities as a second line of defense.

Make sure each web server process can only access the directories that it needs,
and narrow down the directories in which they write or execute files.
Consider running the process in a chroot jail if you are running on Unix. This will
limit the ability of maliciously injected code to “climb out” of a
directory.

Code Samples

The code samples below illustrate how to safely make command-line calls in
various languages.

New processes are spawned in python using the modules
popen2,
os,
commands, and
subprocess.
subprocess is the preferred API (the others are deprecated and replaced by
it). The subprocess module has built-in protection against command execution:

from subprocess import call
# An invocation of the call(...) function will ensure only a single
# command is run.
call(["ls", "-l"])

This protection can be disabled – be on the lookout for anything that opens
a process in the following manner: