OS コマンドインジェクション
基礎
- 悪意のあるリクエストにより、ウェブアプリケーションが意図しない OS コマンドを実行してしまうことで、システムに不正にアクセスされてしまう脆弱性
- この脆弱性が悪用されてしまうとサーバ内のファイルが閲覧、改ざん、削除されたり、システムが不正に操作されたりしてしまう可能性がある
影響
- サーバ内のファイルが不正に操作される
- 個人情報や機密情報などが漏えいする可能性や、改ざん、消去されることで、ウェブページや設定ファイルが改ざんされたり、システムが停止したりするといった被害が発生する可能性がある
- 不正にシステムを操作される
- 意図しない OS のシャットダウンが行われたり、ユーザの追加や変更が行われたりする可能性がある
- 不正なプログラムがダウンロード、実行される
- ウイルスやワーム、ボットに感染してしまったり、システムへ次回も不正に侵入が行えたりするようバックドアが設置されてしまう可能性がある
- 他システムへの攻撃の踏み台にされる
- 他システムへの攻撃を行いサービス不能にしてしまったり、システム攻略のための調査に利用されたり、迷惑メールの送信を行うなど加害者となってしまう可能性がある
原理
- ウェブアプリケーションがユーザからの攻撃リクエストをそのままの形(実行可能な形) でシェルに渡してしまうことで、シェルから OS にコマンド実行の命令が行われる
検査方法
画面の入力パラメータに「&/windows/system32/ping –n 21 127.0.0.1」を入れて、リクエスト送信
- 処理に約20秒の遅延が発生した場合、脆弱性あり
ブラウザのURL入力欄に表示されるGETリクエストの例
http://example.com/test.php?oldname=example.txt&newname=test.txt
- newname = を編集して newname=& /windows/system32/ping –n 21 127.0.0.1 と編集して送信
- 脆弱性があれば、処理に遅延が発生
- newname = を編集して newname=& /windows/system32/ping –n 21 127.0.0.1 と編集して送信
対策
- Web アプリケーションでの対策
- シェルを起動できる言語機能の利用を避ける
- PHP ふでファイル名を変更する場合場、 exec() の代わりに rename() を利用することで、シェルを使用せずにファイル名の変更が行える
- 入力データに使用可能な文字種や書式などのルールを明確にする
- ルールに沿ったでたーチェック
- ルールに沿わないのはエラーとして処理する
- エスケープはしない
- シェルを起動できる言語機能の利用を避ける
- 通信経路上での対策
- WAF を利用して遮断する
脆弱性コードの発見と修正方法
脆弱性がある箇所の発見方法
- シェル経由で OS コマンドを実行している箇所で、そのまま入力パラメータを文字列の連結により代入している場合に OS コマンド・インジェクションの脆弱性となる
脆弱性があるコード
<?php define('FILE_PATH', '/var/www/dt/tmpl/'); $pathAndOldname= FILE_PATH . basename($_GET["oldname"]); $newname=$_GET["newname"]; //脆弱なコード $result=exec("rename " . $pathAndOldname. " " . $newname, $output); echo $output; ?>
- ファイルの変更処理に exec() で OS の rename コマンドを使っている例
修正コード
<?php define('FILE_PATH', '/var/www/dt/tmpl/'); $pathAndOldname= FILE_PATH . basename($_GET["oldname"]); $pathAndNewname= FILE_PATH . basename($_GET["newname"]); $result=rename($pathAndOldname,$pathAndNewname); echo $result; ?>
シェル機能を呼び出せる関数(exec()等)は避け、同じ処理のできる別の関数を用いるようにする
どうしてもシェル機能を呼び出せる関数を使う必要がある場合には、エスケープ処理を行なう
<?php define('FILE_PATH', '/var/www/dt/tmpl/'); $pathAndOldname= FILE_PATH . basename($_GET["oldname"]); $newname=$_GET["newname"]; $result=exec("rename " . escapeshellarg($pathAndOldname). " " . escapeshellarg($newname, $output)); echo $output; ?>