准则
指令注入
让我们先看看命令注入本身。我们主要将重点放在几个不同的示例上,这样更容易看到它在实际操作中的样子。因此,作为快速复习,当用户输入使用了操作系统命令的一部分时,就会出现命令注入漏洞,比如下面的函数:
let ip = request.params.ipAddress;
system("ping " + ip);
如果用户提供了 IP 地址(我们以 `8.8.8.8` 为例),执行的命令将是 `ping 8.8.8.8`,其功能与预期的完全相同。但是,如果用户提供的是 `8.8.8.8 && ls /etc/`,那么这条命令就不仅仅是ping 8.8.8.8 这个 IP 地址了,它还会在 `/etc/ 文件夹中运行 `ls`。
缓解
鉴于命令注入攻击的严重性,在处理系统命令时首先要问一些重要问题:
- 你真的需要调用该命令吗?最好的办法就是永远不要调用系统命令
- 是否有任何库/绑定可以让您在不使用系统命令的情况下实现相同的效果?
- 能否通过 "标准输入 "而不是命令本身将数据传入进程?
如果无法做到这些,参数化就很重要。
实例
下面是一些不同语言的示例,帮助您了解实际应用中的情况。
如果不使用参数化,就很容易发生命令注入。
string folder = "/tmp/ && ifconfig";
string cmd = "\"ls " + folder +"\"";
// INSECURE:同时执行 `ls` 和 `ifconfig` 命令
System.Diagnostics.Process.Start("bash", "-c " + cmd);
C# - 安全
通过以参数列表的形式提供命令,可以对命令进行参数化,防止命令注入。
string folder = "/tmp/ && ifconfig";
List<string> arguments = new List<string>() {"-c", "ls", folder};
// SECURE: Does not execute ifconfig command
System.Diagnostics.Process.Start("bash", arguments);
Java - 不安全
如果不使用参数化,就很容易发生命令注入。
String folder = "/tmp/ && ifconfig";
// INSECURE:同时执行 `ls` 和 `ifconfig` 命令
ProcessBuilder b = new ProcessBuilder("bash -c ls " + folder);
Process p = pb.start();
Java - 安全
通过以参数列表的形式提供命令,可以对命令进行参数化,防止命令注入。
String folder = "/tmp/ && ifconfig";
// 安全:不执行 ifconfig 命令
ProcessBuilder b = new ProcessBuilder("bash", "-c", "ls", folder);
Process p = pb.start();
Javascript - 不安全
如果不使用参数化,就很容易发生命令注入。
const { exec } = require("child_process");
const folder = "/tmp/ && ifconfig";
// INSECURE: Executes both the `ls` and `ifconfig` command
const ls = exec("bash -c ls " + folder, (error, stdout, stderr) => {
console.log(`stdout: ${stdout}`);
});
Javascript - 安全
const { spawn } = require("child_process");
const folder = "/tmp/ && ifconfig";
// SECURE: Does not execute ifconfig command
const ls = spawn("bash", ["-c", "ls", folder]);
ls.stdout.on("data", data => {
console.log(`stdout: ${data}`);
});
Python - 不安全
如果不使用参数化,就很容易出现命令注入问题。
import subprocess
folder = "/tmp/ && ifconfig"
# INSECURE:同时执行 `ls` 和 `ifconfig` 命令
subprocess.run("bash -c ls " + folder, shell=True)
Python - 安全
import subprocess
folder = "/tmp/ && ifconfig"
# 安全:不执行 ifconfig 命令
subprocess.run(["bash", "-c", "ls", folder])