連載
» 2002年11月23日 00時00分 UPDATE

不正侵入の手口と対策(3):侵入者の攻撃手法とその対策 (2/2)

[木村靖,三井物産セキュアディレクション株式会社]
前のページへ 1|2       

脆弱性を回避するための対策

 本稿で紹介した脆弱性を回避するためには、ソフトウェアを安全なバージョンにアップグレードすることが、最も根本的な対策となる。このことは何も本脆弱性に限ったことではなく、ソフトウェアのバグによって生じるほとんどの脆弱性にいえることである。

根本的な対策

 例:本稿で利用した脆弱性の場合
(OpenSSL SSLv2バッファオーバーフロー)

  • OpenSSLを安全なバージョンにアップグレードする

この問題の修正版のOpenSSL 0.9.6e以上にアップグレードする。ただし、0.9.6eでも別の脆弱性が指摘されているため、最新の0.9.6gを利用するとよい。

※注意
OpenSSLのライブラリを静的に取り込んでいるソフトウェアの場合、OpenSSLのアップグレード後、そのソフトウェア自身の再コンパイルも必要。

例:mod_sslで使用するOpenSSLのバージョンを確認

$ strings /usr/lib/apache/libssl.so | grep "OpenSSL 0"
OpenSSL 0.9.6b [engine] 9 Jul 2001

また、関連ファイルをRCSやCVSでバージョン管理しているソフトウェアの場合、ident(1)で調べるという手もある。

 しかしながら、ソフトウェアのアップグレードによる対策を行ううえで、どうしても避けて通れない問題がある。それが、脆弱性が指摘(公開)されてから対策が完了するまでのタイムラグだ。つまり、そのタイムラグによって生じた時間がたとえわずかであったとしても、対策が完了するまでの間は、攻撃者に侵入を許してしまう恐れがある。もちろん、指摘される以前からその脆弱性は含まれている訳だが、脆弱性が公開される/されないでは、攻撃の被害を受ける確立は雲泥の差となるだろう。

 根本的な対策が行われるまでの間、少しでも攻撃被害にあう時間を減らすためには、以下のいずれかの暫定策を実施するとよい。

  • 暫定策1. 脆弱性の存在するサービスを停止する
  • 暫定策2. 設定による回避
  • 暫定策3. 特定の脆弱性をついた攻撃を無効にする

暫定策1. 脆弱性の存在するサービスを停止する

 脆弱性の存在するサービスのみ停止(無効)し、根本的な対策が行われるまで、そのサービスを起動(利用可能)しないようにする。

 例:本稿で利用した脆弱性の場合
(OpenSSL SSLv2バッファオーバーフロー)

  • Apache:443/tcpポートのサービスを停止する
    Apacheの設定で、Listen 443を無効にするか、443/tcpへのアクセスを限定する。
  • Apache:SSLv2を無効にする
    SSLv2の通信時における問題であるため、一時的にSSLv2プロトコルによる通信を行わないようにする。ApacheのSSLRequireにおいて、環境変数SSL_PROTOCOLの内容をチェックし、SSLv2の場合は拒否するようにする。
メリット サービスを停止している間は確実に侵入を許さない
デメリット 根本的な対策がなされるまでサービスを停止することになるため、実運用に支障をきたしてしまう

暫定策2. 設定による回避

 脆弱性の中には、ソフトウェアの設定により攻撃を回避できるものもある。

 例:本稿で利用した脆弱性の場合
(OpenSSL SSLv2バッファオーバーフロー)

  • Apache:バージョン情報を隠す
    本脆弱性を攻撃するツール(ワーム)の中には、実際の攻撃を行う前に HTTPサーバのバージョンを調べ、該当するバージョンごとに適した攻撃を行うものがある。そこで、「第2回 攻撃者に有用な情報を与えない対策法」で紹介したApacheのバージョン情報を隠す設定(ServerTokens ProductOnly)を行うことで回避する。もちろん、ツールの中にはバー ジョン情報を調べないものも存在するため、完全な対策とはいえない。
メリット 現状の運用サービスを維持しつつ攻撃を回避できる
デメリット 場合によっては、脆弱性をつかれてしまうことがある

暫定策3. 特定の脆弱性をついた攻撃を無効にする

 対象サーバにて特定の脆弱性に対する攻撃を、最初から無効にしておけばよい。そうすれば、タイムラグによって生じる時間のみならず、脆弱性が指摘される以前からも、対象サーバの身を守ることができる。

 例:スタックバッファオーバーフローの脆弱性

  • スタックバッファオーバーフローを防ぐツールを利用する
    現在までに報告されている脆弱性の多くが、バッファオーバーフローの問題をつかれたものであるため、このバッファオーバーフロー攻撃を無効にするだけで、多くの攻撃を防ぐことが可能になる。
    スタックバッファオーバーフローを防ぐツールとしては、GCC拡張パッチLibsafeOpenwall LinuxカーネルパッチpropoliceStackGuardなどいくつか存在する。
メリット 特定の脆弱性による攻撃を未然に防ぐことが可能
デメリット サービスパフォーマンスの低下、そのほかのサービスの動作に影響を及ぼす可能性がある

参考(Libsafeの導入事例)

 本来であれば、先述の「暫定策3 特定の脆弱性をついた攻撃を無効にする」で詳しく取り上げる予定だったが、Libsafeは本稿で利用したOpenSSL SSLv2のバッファオーバーフロー問題を検知してくれなかった。そのため、ここでは参考程度にLibsafeの導入事例を紹介する。

 Avayaが提供するLibsafeは、スタックバッファオーバフローやフォーマットストリング攻撃を防ぐことを目的としたツールである。DLL(Dynamically Loadable Library)形式で動作し、C言語のスタックバッファオーバーフローを引き起こす関数(strcpy()やgets())に渡すデータを事前に受け取り境界値チェックを行ったり、スタックのリターンアドレスやフレームポインタの正当性チェックを行うことでフォーマットストリング攻撃も検知し、防御することが可能*2。また、そのほかのスタックオーバーフローを防ぐツールと比べ、運用環境への導入および取り外しが容易に行える。

*2
Libsafeの詳細:
- Libsafe:Protecting Critical Elements of Stacks
http://www.research.avayalabs.com/project/libsafe/doc/libsafe.pdf

- Libsafe 2.0:Detection of Format String Vulnerability Exploits
http://www.research.avayalabs.com/project/libsafe/doc/whitepaper-20.pdf

Libsafe導入前の注意点

  • 使用するとサービスのパフォーマンスが多少落ちる
    上記文献にも記されているが、Libsafeを利用するソフトウェアのパフォーマンスが低下する可能性がある。導入前にパフォーマンステストの実施をお勧めする。
  • GNU C Library 2 (libc6)をリンクしているソフトウェアが対象
    古いlibc5をリンクしているソフトウェアでは動作しない。その場合は、libc6をリンクするようにソフトウェアの再コンパイルが必要になる。

Libsafeのインストールと設定

(1)Libsafeの入手

 http://www.avayalabs.com/project/libsafe/index.htmlより、LibsafeのRPM版を入手する。

(2)Libsafeのインストール

 Red Hat Linux 7.3 i386に、入手したRPM版のLibsafeをインストールする。

# rpm -ihv libsafe-2.0-16.i386.rpm
Preparing... ########################################### [100%]
1:libsafe ########################################### [100%]
Adding libsafe to ld.so.preload for system wide protection

(3)動作確認

 インストールした時点でLibsafeが有効になる。/etc/ld.so.preloadファイルの中身をみると、/lib/libsafe.so.2というLibsafeの動的ライブラリが指定されていることが分かる。

# cat /etc/ld.so.preload
/lib/libsafe.so.2

※注意
/etc/ld.so.preloadの内容はすべてのソフトウェアに影響するため、このファイルを編集する場合は十分に注意すること。ファイルパスを間違えると、すべてのコマンドが利用できなくなってしまう。

 /etc/ld.so.preloadに指定したライブラリは、そのOS上のすべてのソフトウェアの実行時にさきがけてロードされる。以下はlddコマンドで/usr/sbin/httpdの動的に呼び出される共有ライブラリの状況を見た結果である。/lib/libsafe.so.2が存在することが分かる。

# ldd /usr/sbin/httpd
/lib/libsafe.so.2 => /lib/libsafe.so.2 (0x40014000)
libpthread.so.0 => /lib/libpthread.so.0 (0x40020000)
libm.so.6 => /lib/libm.so.6 (0x40035000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x40056000)
libgdbm.so.2 => /usr/lib/libgdbm.so.2 (0x40083000)
libdb-3.3.so => /lib/libdb-3.3.so (0x40089000)
libmm.so.11 => /usr/lib/libmm.so.11 (0x40118000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x4011c000)
libdl.so.2 => /lib/libdl.so.2 (0x4013c000)
libc.so.6 => /lib/libc.so.6 (0x4013f000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

ログの確認

 Libsafeでは、対応するスタックバッファオーバフローなどの攻撃を検知すると、デフォルトで/var/log/secureにその内容を記録する。以下は、スタックの境界値を越えた書き込みを行おうとした行為を記録している。問題は、/usr/sbin/httpd(Apache)プロセスの/usr/lib/apache/mod_dir.soのmemcpy()で発生している。

Nov 10 16:55:32 www libsafe.so[6994]: Libsafe version 2.0.16
Nov 10 16:55:32 www libsafe.so[6994]: Detected an attempt to write across stack boundary.
Nov 10 16:55:32 www libsafe.so[6994]: Terminating .
Nov 10 16:55:32 www libsafe.so[6994]: uid=48 euid=48 pid=6994
Nov 10 16:55:32 www libsafe.so[6994]: Call stack:
Nov 10 16:55:32 www libsafe.so[6994]: 0x4001731a /lib/libsafe.so.2.0.16
Nov 10 16:55:32 www libsafe.so[6994]: 0x400177a6 /lib/libsafe.so.2.0.16
Nov 10 16:55:32 www libsafe.so[6994]: 0x8052f8a /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x8063c68 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x8063db0 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x805ac8d /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x8054708 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x8066fa7 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x4026fd2e /usr/lib/apache/mod_dir.so
Nov 10 16:55:32 www libsafe.so[6994]: 0x80546c8 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x8066fa7 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x806701e /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x805f462 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x805f6a4 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x805f748 /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x805fd9b /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x806068e /usr/sbin/httpd
Nov 10 16:55:32 www libsafe.so[6994]: 0x42017494 /lib/i686/libc-2.2.5.so
Nov 10 16:55:32 www libsafe.so[6994]: Overflow caused by memcpy()
Libsafe: /var/log/secureに出力された内容

メールで通知

 Libsafeでは、先述のLibsafeで検知したログを特定のメールアドレス宛にも送信できる。ただし、本稿で使用したRPM版のLibsafeは標準対応しておらず、メール通知機能を有効にしたい場合は、ソースコードのコンパイル時に以下の手順でNOTIFY_WITH_EMAILフラグを有効にしておく必要がある。

(1)ソースコードの入手と展開

 RPM版と同様に、http://www.avayalabs.com/project/libsafe/index.htmlより入手して、展開する。

$ tar zxvf libsafe-2.0-16.tgz

(2)NOTIFY_WITH_EMAILオプションを有効にする

$ cd libsafe-2.0-16
$ vi src/Makefile

 CCFLAGSが設定されている最後あたりに、以下の1行を追加し保存終了する。

CCFLAGS += -DNOTIFY_WITH_EMAIL

(3)コンパイルとインストール

$ make
# make install

(4)宛先の設定

 Libsafeメールの送信先は、/etc/libsafe.notifyファイルに記述する。

 例:security@www.example.co.jp宛にメールを送信する場合

# echo security@www.example.co.jp > /etc/libsafe.notify

 /etc/libsafe.notifyにsecurity@www.example.co.jpの1行が追加される。設定内容は、ファイルに書き込んだ時点で有効になる。なお、検知時は以下のようなメールが指定した宛先に送信される。

From:libsafe@www.example.co.jp
Subject:***** libsafe violation detected *****
To:security@example.co.jp


Libsafe violation detected on www.example.co.jp at Thu Nov 10 16:55:32 2002
Libsafe version 2.0.16
Detected an attempt to write across stack boundary.
Terminating .
uid=48 euid=48 pid=6994
Call stack:
0x4001731a /lib/libsafe.so.2.0.16
0x400177a6 /lib/libsafe.so.2.0.16
0x8052f8a /usr/sbin/httpd
0x8063c68 /usr/sbin/httpd
0x8063db0 /usr/sbin/httpd
0x805ac8d /usr/sbin/httpd
0x8054708 /usr/sbin/httpd
0x8066fa7 /usr/sbin/httpd
0x4026fd2e /usr/lib/apache/mod_dir.so
0x80546c8 /usr/sbin/httpd
0x8066fa7 /usr/sbin/httpd
0x806701e /usr/sbin/httpd
0x805f462 /usr/sbin/httpd
0x805f6a4 /usr/sbin/httpd
0x805f748 /usr/sbin/httpd
0x805fd9b /usr/sbin/httpd
0x806068e /usr/sbin/httpd
0x42017494 /lib/i686/libc-2.2.5.so
Overflow caused by memcpy()
Libsafe:電子メールで送信された内容

特定サービスでのみ利用する

 /etc/ld.so.preloadに指定すると、すべてのソフトウェアでLibsafeが呼び出されることになるが、これを特定のソフトウェアに限定させることも可能である。その場合は、LD_PRELOAD変数を使えばよい。

 例えば、Apacheのみに限定する場合は、Apacheの起動スクリプト/etc/init.d/httpdに以下を追加すればよい。設定はApacheを再起動することで有効となる。

LD_PRELOAD=/lib/libsafe.so.2
export LD_PRELOAD

 また、/etc/init.d以下のすべての起動スクリプトのみに適用する場合は、/etc/init.d/functionsに上記の設定を追加するとよい。

特定サービスを除外する

 特定サービスのみを除外したい場合は、/etc/libsafe.excludeファイルに、除外するサービスのプログラムの絶対パスを追加する。

 例えば、Apacheのみを対象外にする場合は、Apacheのデーモンプログラムの/usr/sbin/httpdの1行を/etc/libsafe.excludeに追加すればよい。 

 以上、Libsafeを用いたスタックバッファオーバーフローへの対策例を紹介した。なお、Libsafeは、あくまでメモリのスタック領域上における不正な操作に対して有効となるものであり、まれに報告されているヒープ領域*3で発生するバッファオーバーフローに対しては有効とはならないことに注意してほしい。

*3
メモリ上のスタックが、C言語でいうところの変数や配列が静的に確保される領域であるのに対し、ヒープはmalloc()などを実行したときに動的に確保される領域のことを指す。

 また、Libsafeは、まれに正常に動作(検知)してくれないことがある。そのため必ず検知し防御してくれるものと思わない方がよいだろう。


 次回は、バックドアの設置事例とその対策方法について説明する。

筆者紹介

三井物産株式会社GTIプロジェクトセンタ

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

木村 靖(きむら やすし)

セキュリティコンサルタントとして、不正アクセス監視やセキュリティ検査 などに従事している。金融機関、官公庁、大手製造業などへのセキュリティシ ステムの導入、セキュリティ検査などの実績を持つ。



前のページへ 1|2       

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

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

メールマガジン登録

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