コマンド・インジェクション
とりあえずコマンド・インジェクション単体を見てみよう。ここでは、コマンド・インジェクションが実際にどのようなものかを理解しやすいように、いくつかの例を取り上げます。簡単に復習しておくと、コマンド・インジェクション脆弱性は、ユーザー入力がオペレーティング・システム・コマンドの一部を使用する場合に発生します:
let ip = request.params.ipAddress;
system("ping " + ip);
8.8.8.8`を例としてIPアドレスを指定した場合、実行されるコマンドは`ping 8.8.8.8`となり、期待通りの動作をする。しかし、ユーザーが`8.8.8.8 && ls /etc/`を指定した場合、このコマンドは単にIP 8.8.8.8をpingするだけでなく、`/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";
// SECURE:ifconfig コマンドを実行しない
ProcessBuilder b = new ProcessBuilder("bash", "-c", "ls", folder);
Process p = pb.start();
ジャバスクリプト - 安全ではない
パラメータ化を使わないと、これはコマンド・インジェクションに対して脆弱である。
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}`);
});
ジャバスクリプト - 安全
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}`);
});
パイソン - 安全ではない
パラメタリゼーションを使わないと、これはコマンド・インジェクションに脆弱である。
import subprocess
folder = "/tmp/ && ifconfig"
# INSECURE:ls` と `ifconfig` コマンドの両方を実行する
subprocess.run("bash -c ls " + folder, shell=True)
Python - セキュア
コマンドをパラメータ・リストとして提供することで、コマンドはパラメータ化され、コマンド・インジェクションから保護される。
import subprocess
folder = "/tmp/ && ifconfig"
# SECURE:ifconfig コマンドを実行しない
subprocess.run(["bash", "-c", "ls", folder])