シェルを呼び出してOSコマンドを実行する個所での攻撃パターン
ここまではPerlに依存した説明であったが、ここからは、ほぼすべての言語で共通の説明となる。例で示す関数は、Perlのsystem()関数を使うことにする。
コマンドラインでOSを操作したことがある方ならお分かりだろうが、コマンドラインの1行には複数のOSコマンドを渡すことができる。本連載の第2回で説明しているOSコマンドインジェクションは、このパターンである。
OSのシェルに文字列を渡す仕組みでは、OSコマンドだけでなく、シェル上の特殊文字もそのまま機能する。このパターンのOSコマンドインジェクションは、シェルの特殊文字をうまく機能させることによってOSコマンドを実行させる。
シェルの特殊文字については、第2回で説明しているので、ここでは、これらの特殊文字をどのようにして使うかについて説明しよう。
複数のOSコマンドを呼び出す方法としては、以下のようなパターンがある。これは、セキュリティというよりは、シェルの基本である。
command1 ; command2 command1 | command2 command1 || command2 command1 && command2 command1 & command2
これらの攻撃にマッチさせるには、以下の3つの記号に注目するとよい。
「;」、「|」、「&」
「||」と「&&」については、それぞれ1文字のパターンで代用できる。また、上記の記号以外として、サーバのルート上にあるディレクトリを指定する。攻撃者は、OSコマンドを絶対パスで指定してくるためである。
では、この攻撃パターンに対するルールを作成してみる。あまり洗練されていないが、リスト2のようなルールができた。
1: SecFilter ";" skipnext:2 2: SecFilter "&" skipnext:1 3: SecFilter "!|" skipnext:7 4: SecFilter "(;|&|\|)[[:space:]]*/bin/.+" 5: SecFilter "(;|&|\|)[[:space:]]*/home/.+" 6: SecFilter "(;|&|\|)[[:space:]]*/opt/.+" 7: SecFilter "(;|&|\|)[[:space:]]*/usr/+" 8: SecFilter "(;|&|\|)[[:space:]]*/etc/+" 9: SecFilter "(;|&|\|)[[:space:]]*/sbin/+" 10: SecFilter "(;|&|\|)[[:space:]]*/var/+"
仕組みを簡単に説明しておこう。
- 1行目:
- 複数のOSコマンドをつなげる「;」が含まれている場合、2、3行目を飛ばし、4行目以降のルールをチェックする。
- 2行目:
- 1行目と同様である。
- 3行目:
- 記号「|」が含まれていない場合、4〜10行目のルールは意味がなくなるので、すべてスキップする。
- 4行目:
- /bin/xxx
& /bin/xxx
| /bin/xxx
のようなパターンである場合は、
OSコマンドインジェクションと判断する。
以降、ディレクトリごとに同様のチェックを行う。
- /bin/xxx
OSコマンドの引数を操作して別のOSコマンドを実行させる攻撃パターン
本来はmod_securityが動作しているOSにインストールされているOSコマンドをすべて調べなければならないのだが、今回は1つの例としてfindコマンドについて説明する。findコマンドは、OS上のファイルやディレクトリを検索するためのコマンドであるが、-exec引数を渡すことによって、別のOSコマンドを実行させることができる。
単純な例として、URLパラメータとして渡したファイルを見つけるCGIを使用する。ソースは以下に示すようになっている。
#!/usr/bin/perl use CGI; $form = new CGI; $file = $form->param('file'); print "Content-Type: text/plain", "\r\n\r\n"; system("/usr/bin/find /etc -name \"*${file}*\"");
このCGIに対して、以下のように「;」(%3b)でOSコマンドをつなげようとすると、先ほどのルールにマッチしてしまい失敗する。
http://server/cgi-bin/test.cgi?file=a"%3b/bin/ls%20%23
上記のようなCGIでは、
http://server/cgi-bin/test3.cgi?file=a"%20-exec%20/bin/date%20\%5c%3b%23
というように、「-exec /bin/date \;#」のような-execオプションを使ってやると、OSコマンドが実行できる。この攻撃パターンを防御するには、先ほどのルールを以下のように変更する。
1: SecFilter ";" skipnext:3 2: SecFilter "&" skipnext:2 3: SecFilter "!|" skipnext:1 4: SecFilter "!-exec" skipnext:7 5: SecFilter "(;|&|\||-exec )[[:space:]]*/bin/.+" 6: SecFilter "(;|&|\||-exec )[[:space:]]*/home/.+" 7: SecFilter "(;|&|\||-exec )[[:space:]]*/opt/.+" 8: SecFilter "(;|&|\||-exec )[[:space:]]*/usr/+" 9: SecFilter "(;|&|\||-exec )[[:space:]]*/etc/+" 10: SecFilter "(;|&|\||-exec )[[:space:]]*/sbin/+" 11: SecFilter "(;|&|\||-exec )[[:space:]]*/var/+"
リスト1とリスト3をつなげると、OSコマンドインジェクション用のルールになる。前回と同じように、リスト1、リスト3の内容を別ファイルに記述し、Includeディレクティブで読み込ませるようにするとよい。
今回は、OSコマンドインジェクションの攻撃パターンを基に、それを防ぐためのmod_securityのルールを作成した。本文中でも説明しているように、コマンド引数を書き換えることにより、任意のOSコマンドが実行できるコマンドがほかにもある可能性がある。その場合は、その攻撃が成功しないように、別途ルールを追加する必要がある。
著者紹介
中村隆之(なかむらたかゆき)
三井物産セキュアディレクション勤務。 セキュリティコンサルタントとして主にWebアプリケーションのセキュリティ検査に従事しており、大手ポータルサイト、オンラインバンキングなどの数多くの 検査実績を持つ。また、セキュアネットワーク及び暗号関連の研究に携わり、大手製造、官公庁、金融機関へのセキュリティシステム導入など数多くの実績を持つ。
主に、不正アクセス監視サービス、セキュリティ検査、セキュリティポリシー策定支援などのサービス提供している。また、セキュリティに関する教育サービスも実施中。
- Webアプリケーションの脆弱性を総括する
- OSコマンドインジェクションを防ぐルールを作成する
- mod_securityのXSS対策ルールを作成する
- Webアプリケーションファイアウォールによる防御
- 安全なWebアプリケーション開発のススメ
- オンラインショッピングにおける脆弱性の注意点
- ロジック系の検査 〜 問い合わせ画面に含まれる脆弱性 〜
- Webアプリケーションの検査(3)〜 攻撃されないためのセッション管理の検査方法 〜
- Webアプリケーションの検査(2)〜 Webサイトのセッションまわりを調べる方法 〜
- Webアプリケーションの検査テクニック(1)
- エラーメッセージの危険性
- 気を付けたい貧弱なセッション管理
- 顧客データがすべて盗まれる?!〜OSやデータベースへの攻撃〜
- サーバのファイルが丸見え?!
Copyright © ITmedia, Inc. All Rights Reserved.