連載
» 2004年11月12日 00時00分 公開

Webアプリケーションに潜むセキュリティホール(13):OSコマンドインジェクションを防ぐルールを作成する (3/3)

[中村隆之,三井物産セキュアディレクション]
前のページへ 1|2|3       

シェルを呼び出して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/+"
リスト2

 仕組みを簡単に説明しておこう。

  • 1行目:
    • 複数のOSコマンドをつなげる「;」が含まれている場合、2、3行目を飛ばし、4行目以降のルールをチェックする。
  • 2行目:
    • 1行目と同様である。
  • 3行目:
    • 記号「|」が含まれていない場合、4〜10行目のルールは意味がなくなるので、すべてスキップする。
  • 4行目:
    • /bin/xxx
      & /bin/xxx
      | /bin/xxx
      のようなパターンである場合は、
      OSコマンドインジェクションと判断する。
      以降、ディレクトリごとに同様のチェックを行う。

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/+"
リスト3

 リスト1とリスト3をつなげると、OSコマンドインジェクション用のルールになる。前回と同じように、リスト1、リスト3の内容を別ファイルに記述し、Includeディレクティブで読み込ませるようにするとよい。

 今回は、OSコマンドインジェクションの攻撃パターンを基に、それを防ぐためのmod_securityのルールを作成した。本文中でも説明しているように、コマンド引数を書き換えることにより、任意のOSコマンドが実行できるコマンドがほかにもある可能性がある。その場合は、その攻撃が成功しないように、別途ルールを追加する必要がある。

著者紹介

中村隆之(なかむらたかゆき)

三井物産セキュアディレクション勤務。 セキュリティコンサルタントとして主にWebアプリケーションのセキュリティ検査に従事しており、大手ポータルサイト、オンラインバンキングなどの数多くの 検査実績を持つ。また、セキュアネットワーク及び暗号関連の研究に携わり、大手製造、官公庁、金融機関へのセキュリティシステム導入など数多くの実績を持つ。

三井物産セキュアディレクション

主に、不正アクセス監視サービス、セキュリティ検査、セキュリティポリシー策定支援などのサービス提供している。また、セキュリティに関する教育サービスも実施中。



前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。