CodeQL 文档

从库输入构建的不安全的 shell 命令

ID: js/shell-command-constructed-from-input
Kind: path-problem
Security severity: 6.3
Severity: error
Precision: high
Tags:
   - correctness
   - security
   - external/cwe/cwe-078
   - external/cwe/cwe-088
Query suites:
   - javascript-code-scanning.qls
   - javascript-security-extended.qls
   - javascript-security-and-quality.qls

单击查看 CodeQL 代码库中的查询

使用导出函数的输入动态构建 shell 命令可能会无意中改变 shell 命令的含义。使用导出函数的客户端可能会使用包含 shell 以特殊方式解释的字符的输入,例如引号和空格。这会导致 shell 命令行为异常,甚至允许恶意用户在系统上执行任意命令。

建议

如果可能,请使用安全的 API(例如 child_process.execFile)以数组形式将动态参数提供给 shell,以避免 shell 解释。

如果以单个字符串形式提供参数,请避免简单地在空格处拆分字符串。参数可能包含带引号的空格,导致它们被拆分为多个参数。使用类似 shell-quote 的库来解析字符串,而不是将其解析为参数数组。

或者,如果命令必须由 shell 解释(例如,因为它包含 I/O 重定向),则可以在将输入嵌入命令之前使用 shell-quote 转义输入中的任何特殊字符。

示例

以下示例显示了动态构建的 shell 命令,该命令从远程 URL 下载文件。

var cp = require("child_process");

module.exports = function download(path, callback) {
  cp.exec("wget " + path, callback);
}

但是,如果输入包含空格或 shell 以特殊方式解释的其他特殊字符,则 shell 命令将无法按预期工作。

更糟糕的是,客户端可能会传入用户控制的数据,而不知道输入被解释为 shell 命令。这可能会允许恶意用户提供输入 http://example.org; cat /etc/passwd,以执行命令 cat /etc/passwd

为了避免这种潜在的灾难性行为,请将导出函数的输入作为不会被 shell 解释的参数提供。

var cp = require("child_process");

module.exports = function download(path, callback) {
  cp.execFile("wget", [path], callback);
}

再举一个例子,考虑以下代码,它与前面的示例类似,但将 wget 的输出管道到 wc -l,以计算下载文件的行数。

var cp = require("child_process");

module.exports = function download(path, callback) {
  cp.exec("wget " + path + " | wc -l", callback);
};

在这种情况下,使用 child_process.execFile 不是一种选择,因为需要 shell 来解释管道运算符。相反,您可以在将输入嵌入命令之前使用 shell-quote 转义输入。

var cp = require("child_process");

module.exports = function download(path, callback) {
  cp.exec("wget " + shellQuote.quote([path]) + " | wc -l", callback);
};

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私