HOME情報セキュリティ資料・報告書・出版物調査・研究報告書情報セキュリティ技術動向調査(2008 年上期)

本文を印刷する

情報セキュリティ

情報セキュリティ技術動向調査(2008 年上期)

11 Debian の openssl

田中 哲

  セキュリティ問題を予防するためにツールを使ってコードを検査することがあるが、それに関連して2008 年5 月13 日に公開された「DSA-1571-1 openssl -- 予測可能な乱数の生成」[1] というDebian セキュリティ勧告がある。
  この問題は、Debian において変更されたopenssl ライブラリでは乱数が予測可能となり、その結果として、生成される暗号鍵が予測可能となってしまった、というものである。これにより、多くの鍵を捨てて新しく作りなおすという多大な手間がかかる対処が必要になった。ここでは、なぜそのような変更が行われたのかという原因について述べる。
  この変更が行われたのは2006 年のことであり、openssl に対する「Valgrind25が発生させる警告を取り除いてほしい」という要望がきっかけであった。[2]
  Valgrind には、さまざまな機能があるが、デフォルトの機能で、もっともよく使用されるものはメモリの使いかたを検査するmemcheck というものである。memcheck はデフォルトなので、単にValgrind といった場合はmemcheck を指していることが多い。
memcheck 以外にはキャッシュシミュレータのcachegrind やヒーププロファイラのmassif などがあり、オプションで指定できる。
  memcheck は、例えば初期化されていないメモリの値に基づいて条件判断をすることに警告を発生させる。memcheck はこれを実現するためにプログラムが扱うデータが初期化されているかどうかのフラグを管理している。そして、初期化されていない値、もしくはそのような値から導出された値で条件判断が行われると、警告を発生する。なお、初期化されていない値をメモリから読んだり書いたりするだけでは警告されない。これは、フィールド間に空きがある構造体をmemcpy するなど、害が無いケースが多いためである。
  Debian に対する希望は、openssl を利用したアプリケーションで発生する警告を除去するため、openssl に変更を加えるというものである。一般に、初期化されていない値を使用することは不適切なので、この希望自体は妥当なものである。実際、openssl を利用するアプリケーションの検査をValgrind で行った場合に、openssl に起因する警告が大量に出ればアプリケーション自体の検査が難しくなる。そのため、openssl 自体に問題があれば、その問題を解決するのは方向性として正しい。
  この希望を受けて、Debian が行った変更は、openssl 内のcrypto/rand/md_rand.c というファイルで、下記の「MD_Update(&m,buf,j);」を含む2 行を除去することであった。

 ssleay_rand_add:
                ....
                MD_Update(&m,buf,j);
                ....
 ssleay_rand_bytes:
                ...
  #ifndef PURIFY
                MD_Update(&m,buf,j); /* purify complains */
  #endif
                ...
       

  最初の行はssleay_rand_add 関数にあり、もうひとつの行はssleay_rand_bytes 関数にある。セキュリティ問題となったのは前者を除去したことであった。
  ssleay_rand_add は 乱数の種となるデータを外部から追加する関数であり、ssleay_rand_bytes はその種から乱数を発生させて呼出元に返す関数である。どちらも与えられたバッファをハッシュして乱数の種に追加する。
  前者は乱数の種に追加することが目的の関数であるから、与えられたバッファのデータを使うのは必須である。これを除去したために、乱数の種にデータが追加されなくなり、/dev/urandom などから読んだデータが乱数の種に追加されることなく捨てられることとなった。その結果として、乱数が予測可能というセキュリティ問題につながった。
  これに対し、後者の除去はセキュリティ問題ではない。後者のssleay_rand_bytes では、呼出元が与えたバッファに発生した乱数を埋めて返すのであるが、同時に、埋める前の内容を乱数の種に追加する。これはopenssl のドキュメント[3] に明記された仕様である。
  ここで呼出元の興味が発生される乱数にしかなければ、ここには初期化されていないバッファが与えられることがあり、その場合、Valgrind は乱数の種が初期化されていない値に依存していると解釈することになる。そして、アプリケーションが生成された乱数を用いて条件判断などを行えば、memcheck で警告が発生する。しかし、この件に限定していえば、初期化されていない値に依存していても、結果として生成されるものは乱数であるから問題は起きない。
  この警告の問題についてはopenssl の開発者も認知しており、それがPURIFY マクロによる条件コンパイルに表れている。Purify は Valgrind の memcheck に類似した機能を持つ検査ツールであり、警告を避けるためにssleay_rand_bytes 内 の「MD_Update(&m,buf,j);」を除去する機構が用意されている。
  このような条件コンパイルが用意されていることからも分かるように、後者は除去してもセキュリティ上問題とはならない。後者の「MD_Update(&m,buf,j);」は、乱数の種にデータをいくらか追加するが、それはおまけのようなものであり必須ではない。このため、セキュリティ勧告後のパッケージでも除去されたままである。
  なお、Debian の開発者はこれらの除去を行うにあたり、事前にopenssl-dev メーリングリストで相談を行った。[4] その議論では、除去してもいいのではないかという反応もあれば、PURIFY マクロの定義でValgrind の警告を抑制できているといった反応もあった。

まとめ

  ソフトウェアの変更は、対象のコードを正しく理解して行う必要がある。あいまいな理解のもとに、検査ツールが警告を出したという理由だけで変更を行うのはかならずしも望ましい結果をもたらさない。また、-DPURIFY を用いる等によって、コードの変更無しに要求される効果が得られるのであれば変更すべきでない。変更を行わなければ、少なくとも新しい問題を発生させることはない。


以上


  1. http://valgrind.org/

参考文献

[1] Debian セキュリティ勧告DSA-1571-1 openssl -- 予測可能な乱数の生成
http://www.debian.org/security/2008/dsa-1571

[2] Debian BTS #363516 - valgrind-clean the RNG - Debian Bug report logs
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=363516

[3] OpenSSL: Documents, RAND_bytes(3)
http://www.openssl.org/docs/crypto/RAND_bytes.html

[4] 'Random number generator, uninitialised data and valgrind.' thread - MARC
http://marc.info/?t=114651088900003&r=1&w=2

目次へ