Discover Performance

 

 


今すぐ登録する

「HP Software Discover Performance」日本語版

Open SSLのぜい弱性「Heartbleed」についての解説

今回は、セキュリティ情報として、OpenSSLに発覚した、いわゆる「HeartBleed」について説明します。

2014年4月7日に、OpenSSLに関しての脆弱性がCVE-2014-0160として発表されました。この脆弱性を悪用された場合、メモリ内の情報が閲覧され、SSL暗号化通信の内容や秘密鍵などの重要情報が漏洩する可能性があります。

この脆弱性は大きな問題となっており、現在テレビなどのメディアでも広く取り上げられるようになっています。また、この脆弱性を利用したと思われるインシデントが発生しています。

脆弱性の内容を詳しく見てみましょう。

脆弱性解説

今回の脆弱性は、OpenSSLのHeartBeat拡張(RFC6520)の実装上の不具合により発生しました。

OpenSSLのHeartBeat拡張(RFC6520)とは、TLS/DTSLに対してKeep-Aliveの機能を付けるものです。

通常、クライアント<->サーバ間の通信において、何も通信を行わないでいると、無通信で回線が切断されてしまったり、TCP接続がタイムアウトしてしまうため、一定間隔でなんらかのパケットを送って相手の生存を確認します。これは、TCPの3Wayハンドシェイクにかかるクライアント・サーバのリソースを減らすため、極力同じTCP接続を使いまわしたいためです。

このKeep-Aliveは、ネットワークレイヤの色々な層で実装されており、たとえばトランスポート層でのTCPのKeep-Aliveや、アプリケーション層でのHTTP1.0のKeep-Alive/HTTP1.1の持続的接続などがあります。
SSLでも、この機能を実装しようというのが狙いになります。



このRFC自体に関しても色々話があり、「TCPでkeep-aliveが行えるし、本来ユーザにとってありがたいのはもっと上のレイヤのKeep-aliveなのだから必要ないのではないか」という意見も出ていました。

例えば、SSL実装の一つのGnuTLSの開発者のNikos Mavrogiannopoulosは、この機能が必要な意味を提案者に要請し、最終的にGnuTLSではHeartBeat拡張機能は無効にされています。
このRFCに関してはOpenBSDの開発者であるTheo も”IETF, I don't trust you.”とかなり辛辣な言葉を出しています。

詳しくは、HackerNewsの下記のリンクを参照してください。
https://news.ycombinator.com/item?id=7569522 
https://news.ycombinator.com/item?id=7571263 

不具合の箇所

前述の通り、HeartBeat拡張機能はRFCとして出されており、実際に必要かどうかに関しては疑問を出されながらも、非常に簡単な仕組みのため、設計上は特に問題は発生しません。
実際には、今回はOpenSSLでの実装時に問題(バグ)が潜んでいました。

今回openssl-1.0.1gでの修正個所は ssl/d1_both.cファイルのdtls1_process_heartbeat() 関数になります。


HeartBeatのリクエストを受信すると、(1)のs->s3->rrec.dataで定義されるバッファにリクエストメッセージが入ってきます。ポインタはpとなります。

このリクエストメッセージはssl3.hで定義され、下記のフォーマットになっています。


(2)の通り、先頭1byteはHeartBeatのTypeを示し、次の2byteとなる(3)がリクエストの長さとなるlengthになっています。

このポインタpで表されるリクエストメッセージが、前述dtls1_process_heartbeat()で


として処理されます。
(4)でhbtype変数としてHeartBeatのTypeが入り、
(5)でpayload変数に次の2byteの(lengthにあたる)フィールドが入り、
(6)でpayloadの先頭アドレスがポインタplに格納されます。

ここで注目しておくことは、payloadとして、受け取ったリクエストメッセージ内で設定されているlengthがそのまま(チェックされることなしに)payloadとして格納されていることです。

次に、受信したHeartBeatに対するレスポンスとしてエコーバックを返す部分ですが、これは


(7)でバッファーとして(4)で読み取られたtype用の1byte、length用の2bytes、(5)で読み取られたpayload、paddingとして16bytesを確保します。
(8)でbufferへのポインタをbpとします。

このバッファーを使ってエコーバックを送り返すわけですが


(9)のように、リクエストから得られた値を基にしたメモリ内容をコピーしてバッファーに設定し、エコーバックを作成しています。

この一連の動作を絵にしたものが下記になります。


実に単純な作りになっているため、一見何も問題なさそうに思われます。

しかし、ここでリクエストメッセージ中のlengthを、実際のものよりも意図的に大きいものに設定した場合にはどうなるでしょうか?


このように、length値として不正な(実物のlengthよりも大きい)値を入れたリクエストメッセージを送った場合には、レスポンスとして不正lengthの値からpayloadを決定してしまうため、上述のように意図しないメモリ領域の漏えいが発生してしまいます。

実際、修正されたバージョンでは、ここのlength値をきちんと確認し、実物のlength値よりも大きかった場合にはパケットを破棄するようになっています。

影響範囲

今回の問題の対象となるバージョンは、

・OpenSSL 1.0.1 ~ 1.0.1f
・OpenSSL 1.0.2-beta ~ 1.0.2-beta1

となります。既に本脆弱性を修正した、

・OpenSSL 1.0.1g
は、今回のCVEが発表されたと同時に、4/7/2014にリリースされています。

各ベンダから該当バージョンのライブラリを使用しているパッケージに関して、情報が出ていますので、対応に関しては各ベンダに確認したほうがいいと思われます。

実際に発生したインシデント

この脆弱性を悪用したと思われるインシデントが、実際の現場でも発生しました。
4/18に三菱UFJニコスは、同社Webサービスから894人分の個人情報が流出した恐れがあることを明らかにしました。
これによると、4月上旬にインシデントが発生し、4月11日14時30分から4月12日7時48分まで、会員専用のWebサービスを停止しました。
今回の不正アクセスによって、同社発行のクレジットカード会員の情報(カード番号、氏名、生年月日、住所、電話番号など)894人分が第三者に閲覧された恐れがあるということです。
ただ、今回どういう経緯で攻撃を特定できたか、またWebサーバの秘密鍵が閲覧された恐れがあるのかなど、詳しい情報に関しては、セキュリティの都合上、コメントできないとのことです。

■ 考察

今回の脆弱性を受け、各ベンダが対策の施された製品をリリースしていますので、それらの情報をつかみ、最新のものにセキュリティアップデートを行いましょう。

企業のサーバ運営者は、OpenSSLを更新したのちに、SSLサーバ証明書を再発行する必要があります。また、パスワードが漏えいした可能性もありますので、パスワードのリセットも行ったほうがいいでしょう。

エンドユーザも、最新のバージョンにアップデートを行い、可能であればパスワードのリセットを検討したほうがいいでしょう。その際にWebツールなどでリセットを行う場合には、便乗犯としてパスワードリセットを装って悪質なサイトに誘導される可能性があるため、サイトのURLに注意したほうがいいでしょう。

また、今回のバグは、かなり初歩的な(値の妥当性の確認を怠っている程度の)ミスであり、コードのセキュリティチェックツールなどを使用していればリリース前に判明したはずです。企業などで開発を行っているユーザは、コードのセキュリティ品質チェックを欠かさずに行うべきと思われます。