Semmle 1.21
Skip to end of metadata
Go to start of metadata

Name: Uncontrolled process operation

Description: Using externally controlled strings in a process operation can allow an attacker to execute malicious commands.

ID: cpp/uncontrolled-process-operation

Kind: problem

Severity: warning

Precision: medium

Query: UncontrolledProcessOperation.ql
/**
 * @name Uncontrolled process operation
 * @description Using externally controlled strings in a process
 *              operation can allow an attacker to execute malicious
 *              commands.
 * @kind problem
 * @problem.severity warning
 * @precision medium
 * @id cpp/uncontrolled-process-operation
 * @tags security
 *       external/cwe/cwe-114
 */

import cpp
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.TaintTracking

from string processOperation, int processOperationArg,
     FunctionCall call, Expr arg, Element source
where isProcessOperationArgument(processOperation, processOperationArg)
  and call.getTarget().getName() = processOperation
  and call.getArgument(processOperationArg) = arg
  and tainted(source, arg)
select arg,
  "The value of this argument may come from $@ and is being passed to " + processOperation,
  source, source.toString()

The code passes user input directly to system, dlopen, LoadLibrary or some other process or library routine. As a result, the user can cause execution of arbitrary code.

Recommendation

If possible, use hard-coded string literals for the command to run or library to load. Instead of passing the user input directly to the process or library function, examine the user input and then choose among hard-coded string literals.

If the applicable libraries or commands cannot be determined at compile time, then add code to verify that the user-input string is safe before using it.

Example

int main(int argc, char** argv) {
  char *lib = argv[2];
  
  // BAD: the user can cause arbitrary code to be loaded
  void* handle = dlopen(lib, RTLD_LAZY);
  
  // GOOD: only hard-coded libraries can be loaded
  void* handle2;

  if (!strcmp(lib, "inmem")) {
    handle2 = dlopen("/usr/share/dbwrap/inmem", RTLD_LAZY);
  } else if (!strcmp(lib, "mysql")) {
    handle2 = dlopen("/usr/share/dbwrap/mysql", RTLD_LAZY);
  } else {
    die("Invalid library specified\n");
  }
}

References
  • Common Weakness Enumeration: CWE-114.