シェルインジェクションとは
シェルインジェクションはOSコマンドインジェクションとも呼ばれ、プログラムの脆弱性を利用して一連の悪意のある命令を作成し、標的プログラムに攻撃者のコマンドを実行させることを指します。シェルインジェクションはUnixシェルから名付けられていますが、プログラムがコマンドラインインターフェイスを呼び出すことを許可するシステムで実行されているほとんどのプログラムは、シェルインジェクション関連の脆弱性を誤って導入する可能性があります。シェルインジェクションの潜在的なリスクがあるインターフェイスには、Javajava.lang.Runtime.exec()
および.NETのインターフェイスが含まれますSystem.Diagnostics.Process.Start()
。
SQLインジェクションなどの脆弱性と比較して、シェルインジェクションについて言及されることはめったにありませんが、プログラム外のリソースに直接接続できるため、通常、より深刻な影響があります。
この記事は、友人が書いたデモプログラムでシェルインジェクションの脆弱性が発見されたために書かれたものなので、最初は例としてプログラムを書き直しました。次のJavaコードでは、フロントエンドがDockerイメージ名をバックエンドサーバーに渡し、バックエンドサーバーがdocker pull
コマンドを呼び出して対応するイメージファイルをプルします。
String imageName = (String) params.get("imageName");
String cmd = "docker pull " + imageName;
Process process = Runtime.getRuntime().exec(cmd);
// ...
フロントエンドから渡されるimageName
パラメータ値が通常のイメージ名(たとえばnginx
)の場合、docker pull nginx
コマンドが実行されてnginxイメージがプルされます。また、フロントエンドから渡されたimageName
パラメータ値nginx; echo hacked
、つまり悪意のある命令があるecho hacked
場合、バックエンドプログラムはdocker pull nginx
正常に実行されecho hacked
た後にコマンドを実行します。利便性を実証し、誤操作を回避するために、echo
ここでは直感的で無害なコマンドを使用しています。このコマンドをターミナルで直接実行した結果は次のとおりです。
# 示例中省略了执行结果与本文无关的一些输出信息
$ docker pull nginx; echo hacked
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
hacked # <- 此处为执行恶意命令的结果
次に、DVWAのPHPプログラムを使用したシェルインジェクションのさまざまな方法を紹介します。
シェル注入法
以下は、クライアントからのパラメーターipをpingコマンドのパラメーターとして受け取り、操作の結果を出力するPHPプログラムです。
$target = $_REQUEST['ip'];
$cmd = shell_exec('ping -c 4 ' . $target);
echo "<pre>{
$cmd}</pre>";
このセクションでは、上記の手順を通じていくつかのシェル注入方法を紹介します。例では、デモンストレーションとして直感的で無害な結果が得られるコマンドを使用します。
;
継続指導
連続コマンドを使用する場合command1; command2
、command1
コマンドが実行された後もcommand2
コマンドは実行され続けます。例では、パラメータがユーザーによって入力される127.0.0.1; echo hacked
と、プログラムは最初のping -c 4 127.0.0.1
コマンドで実行され、実行はecho hacked
コマンドを完了するために続行されます。ターミナルで実行されているこのコマンドの出力は次のとおりです。
$ ping -c 4 127.0.0.1; echo hacked
PING 127.0.0.1 (127.0.0.1): 56 data bytes
# ... ping的执行结果
4 packets transmitted, 4 packets received, 0.0% packet loss
hacked # <- echo hacked的执行结果
- パイプライン
|
command1 | command2
パイプを使用することによりcommand1
、command2
入力後の出力として実行を完了します。たとえば、パラメータを入力する127.0.0.1 | grep loss
と、プログラムはping -c 4 127.0.0.1
コマンドをgrep loss
入力コマンドとして出力します。このコマンドgrep loss
は、pingコマンドの出力で損失のある行を出力します。次に例を示します。
$ ping -c 4 127.0.0.1 | grep loss
4 packets transmitted, 4 packets received, 0.0% packet loss
&
バックグラウンド実行
&
コマンドの後に使用すると、コマンドがバックグラウンドで実行されます。ときに&
他のコマンドが続いている(command1 & command2
)、彼らはバックグラウンドで実行されるcommand1
と、フォアグラウンドでcommand2
。たとえば、コマンドping -c 4 127.0.0.1 & echo hacked
はバックグラウンドping -c 4 127.0.0.1
で実行され、echo hacked
コマンドを実行します。通常、このコマンドの結果は次のとおりです。
$ ping -c 4 127.0.0.1 & echo hacked
[1] 2333 # <- ping命令的进程号
hacked # <- echo hacked的执行结果
PING 127.0.0.1 (127.0.0.1): 56 data bytes
# ... ping的执行结果
注:ping
コマンドにはネットワークI / Oが含まれるため、出力はコマンドの実行後ではecho
なく、ping
コマンドのecho
後になります。
&&
対||
&&
そして、||
類似し、使用の両方command1 && command2
またはcommand1 || command2
。2つの違いは&& command2
、中間は実行が成功した後にcommand2
のみcommand1
実行され(終了コードは0)、|| command2
中間は実行が失敗したcommand2
後にのみcommand1
実行される(終了コードはゼロ以外の値)ことです。
`command`
対$(command)
どちらのタイプのアクションもcommand
コマンドを実行します。コマンドがcommand1 $(command2)
時刻(command1 `command2`
同じトークン)の場合command2
、command1
パラメーターとして出力されます。ユーザー入力パラメータなどは$(echo hacked)
、ping
前のプログラム実行で最初echo hacked
にコマンドを実行します。
いくつかのシェル噴射における上記方法に加えて、例えばリダイレクション(>
、、 、)なども、攻撃者によって使用されてもよいです。>>
<
<<
シェル注入防御策
- ユーザーが入力したコマンドを直接実行しないでください
プログラムでは、コマンドラインインターフェイスを介してコマンドを実行しないようにするか、ユーザーが入力したデータをシェルコマンドのパラメーターとして直接使用しないようにする必要があります。記事の冒頭にあるDockerコマンドと同様に、docker pull
コマンドを直接使用する代わりに、Dockerが提供するAPIインターフェースを使用して対応するイメージをプルできます。
- ユーザーが入力したパラメーターを確認します
上記の例のpingプログラムのように、必要なパラメーターがIPv4アドレスであると仮定すると、パラメーターの形式を正規化によってチェックして、有効なIPv4アドレス文字列であるかどうかを確認できます。
$target = $_REQUEST['ip'];
if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $target)) {
throw new Exception('Invalid ip');
}
$cmd = shell_exec('ping -c 4 ' . $target);
echo "<pre>{
$cmd}</pre>";
- 一般的なシンボルをフィルタリングする
上記フィルタ含み|
、&
、;
所望のパラメータは、特定のシンボルを含む場合、他の記号を、記号をエスケープすることができます。たとえば、echo hacked \&
コマンドはバックグラウンドで実行されず、出力結果はhacked &
です。
- ブラックリストとホワイトリストのメカニズムを使用する
コマンドで許可されるパラメーターを制限するために、白黒リストを作成します。
- 言語が提供するトランスコーディング方法を使用する
一部の言語は、phpのようなシェルパラメータをトランスコードするためのメソッドを提供しますが、escapeshellarg()
安全であると完全に信頼することはできません。
- 最小特権ユーザーを使用してプログラムを実行する
たとえば、Webアプリケーションでは、最低限必要な権限を持つユーザーがアプリケーションの実行に使用されます。この手段は実際の防御手段ではありません。攻撃された後の大きな影響を回避することを目的としており、シェルインジェクションの処理に使用されることに限定されません。
- …