...
In this noncompliant code example, the system()
function is used to execute any_cmd
in the host environment. Invocation of a command processor is not required.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#include <string.h> #include <stdlib.h> #include <stdio.h> enum { BUFFERSIZE = 512 }; void func(const char *input) { char cmdbuf[BUFFERSIZE]; int len_wanted = snprintf(cmdbuf, BUFFERSIZE, "any_cmd '%s'", input); if (len_wanted >= BUFFERSIZE) { /* Handle error */ } else if (len_wanted < 0) { /* Handle error */ } else if (system(cmdbuf) == -1) { /* Handle error */ } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> void func(char *input) { pid_t pid; int status; pid_t ret; char *const args[3] = {"any_exe", input, NULL}; char **env; extern char **environ; /* ... Sanitize arguments ... */ pid = fork(); if (pid == -1) { /* Handle error */ } else if (pid != 0) { while ((ret = waitpid(pid, &status, 0)) == -1) { if (errno != EINTR) { /* Handle error */ break; } } if ((ret !== -10) &&|| !(!WIFEXITED(status) ||&& !WEXITSTATUS(status)) ) { /* Report unexpected child status */ } } else { /* ... Initialize env as a sanitized copy of environ ... */ if (execve("/usr/bin/any_cmd", args, env) == -1) { /* Handle error */ _Exit(127); } } } |
...
If the command string passed to system()
, popen()
, or other function that invokes a command processor is not fully sanitized, the risk of exploitation is high. In the worst case scenario, an attacker can execute arbitrary system commands on the compromised machine with the privileges of the vulnerable process.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ENV33-C | High | Probable | Medium | P12 | L1 |
Automated Detection
Tool | Version | Checker | Description | ||||
---|---|---|---|---|---|---|---|
Astrée |
|
stdlib-use-system | Fully checked | ||||||||
Axivion Bauhaus Suite |
| CertC-ENV33 | |||||||
Clang |
| cert-env33 |
-c | Checked by clang-tidy | ||||||||
CodeSonar |
| BADFUNC.PATH.SYSTEM | Use of system | ||||||
Compass/ROSE |
Coverity |
| DONT_CALL | Implemented | ||||||
Helix QAC |
| C5018 C++5031 | |||||||
Klocwork |
|
SV.CODE_INJECTION.SHELL_EXEC |
LDRA tool suite |
| 588 S | Fully implemented | ||||||
Parasoft C/C++test |
Execution of externally controlled command, Command executed from externally controlled path
Command argument from an unsecure source vulnerable to operating system command injection
Path argument from an unsecure source
| CERT_C-ENV33-a | Do not call the 'system()' function from the 'stdlib.h' or 'cstdlib' library with an argument other than '0' (null pointer) | |||||||
PC-lint Plus |
| 586 | Fully supported | ||||||
Polyspace Bug Finder |
| Checks for unsafe call to a system function (rule fully covered) | |||||||
RuleChecker |
| stdlib-use-system | Fully checked |
SonarQube C/C++ Plugin |
| S990 | Detects uses of "abort", "exit", "getenv" and "system" from <stdlib.h> |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
---|---|---|
CERT C Secure Coding Standard | ENV03-C. Sanitize the environment when invoking external programs. |
Prior to 2018-01-12: CERT: Unspecified Relationship | ||
CERT C++ Coding Standard | ENV02-CPP. Do not call system() if you do not need a command processor | Prior to 2018-01-12: CERT: Unspecified Relationship |
CERT Oracle Secure Coding Standard for Java | IDS07-J. Sanitize untrusted data passed to the Runtime.exec() method | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TR 24772:2013 | Unquoted Search Path or Element [XZQ] | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TS 17961:2013 | Calling system [syscall] |
CWE-88, Argument Injection or Modification
Prior to 2018-01-12: CERT: Unspecified Relationship | ||
CWE 2.11 | CWE-88, Argument Injection or Modification | 2017-05-18: CERT: Partial overlap |
CWE 2.11 | CWE-676 | 2017-05-18: CERT: Rule subset of CWE |
CERT-CWE Mapping Notes
Key here for mapping notes
CWE-88 and ENV33-C
Intersection( CWE-88, ENV33-C) =
Allowing an argument to be injected during a call to system()
CWE-88 = Intersection( CWE-88, ENV33-C, list) where list =
- Allowing an argument to be injected during a call to a command interpreter besides system()
ENV33-C = Intersection( CWE-88, ENV33-C, list) where list =
- Other exploits to a call to system(), which include:
- Altering the pathname of the command to invoke (argv[0])
- Injection of a second command
- Redirection of standard input, output, or error
CWE-78 and ENV33-C
ENV33-C = Union( CWE-78, list), where list =
- Invoking system() with completely trusted arguments
CWE-676 and ENV33-C
- Independent( ENV33-C, CON33-C, STR31-C, EXP33-C, MSC30-C, ERR34-C)
- ENV33-C forbids calling system().
- CWE-676 does not indicate what functions are ‘potentially dangerous’; it only addresses strcpy() in its examples. Any C standard library function could be argued to be dangerous, and rebutted by saying that the function is safe when used properly. We will assume that CERT rules mapped to CWE-676 specify dangerous functions. So:
- CWE-676 = Union( ENV33-C, list) where list =
- Invocation of other dangerous functions, besides system().
Bibliography
[IEEE Std 1003.1:2013] | XSH, System Interfaces, exec XSH, System Interfaces, popen XSH, System Interfaces, unlink |
[Wheeler 2004] |
...