なぜPHPアプリにセキュリティホールが多いのか?

第43回 PHP 5.3のcrypt関数の問題

この記事を読むのに必要な時間:およそ 8 分

Crypt BlowfishやMD5 Cryptのバグは攻撃できるのか?

筆者はcrypt関数はシステム依存の関数であったので使うべきでない関数として分類していました。ほとんどのLinuxシステムでMD5 Cryptしか利用できない(DESは問題外)のは非常に問題です。crypt関数を使ったオープンソースアプリケーションはそれほどないだろう,と予想していましたが,調べてみるとかなりあるようです。

Google Code Searchで「" crypt(" lang:^php$」とキーワードに指定して検索してみると,執筆時点で2,400件もヒットしました。その多くがcrypt関数を特殊な用途に使っているADODBとphpassでした。ADODBは暗号化キーを生成するためにcrypt関数を使用しており,明らかに本来の用途以外の目的で利用していました。しかし,筆者も利用をお薦めしているphpassライブラリはPHPのcrypt関数を本来の用途である認証に利用できるようになっています。

phpassを利用している主なPHPアプリケーション
  • WordPress 2.5+
  • Drupal 7+
  • SquirrelMail

phpassは,ポータブルなMD5を利用したphpassのユーザー定義関数を利用するか,ポータブルでないハッシュ関数(CRYPT_BLOWFISHまたはCRYPT_EXT_DES)を利用するか選べるようになっています。

phpassのPasswordHashメソッドはストレッチング(ハッシュ関数を何回も適用してクラックを困難にする手法)をサポートしているのでMD5でも比較的安全です。ハッシュ関数がMD5なのでできれば少なくとも数千回($iteration_cont_log2 > 13),できれば万単位の回数($iteration_count_log2 > 15)はストレッチしたほうがよいでしょう。ログインにある程度CPU時間が必要になりますが,そのCPU時間がパスワードのクラックを困難にさせます。

$iteration_count_log2は4から31の間で指定し,それ以外の場合は8が設定されます。ストレッチ回数(ハッシュ関数の適用回数)

  • $count = 1 << $iteration_count_log2;

として計算されます。つまり,$iteration_count_log2が13の場合,2^13=4096回ストレッチ(ハッシュ関数が適用)されます。

PHP 5.3からは必ずCRYPT_BLOWFISHもCRYPT_EXT_DESも組み込まれることが保証されており,phpassはCRYPT_BLOWFISHのほうが優先順位が高く設定されています。WordPressとDrupalは非常に大きなインストールベースを持っています。しかし,phpassのMD5 CryptはPHPで実装されているのでMD5 Cryptのバグの影響は受けません。Crypt blowfishのバグの影響はプラットフォームによって変わります。BSD系OSの場合は影響を受けない場合が多く,Linux/Windows系の場合はほぼすべての環境で影響を受けるでしょう。

Google Code Searchで検索しヒットしたコードの上位200くらいを見た限りでは,影響を受けるアプリケーションもそれなりにあると考えてよいでしょう。

脆弱性の影響評価は一般に

  • 影響度 = 攻撃が成功した場合のダメージ × 攻撃が成功する確率 × 攻撃経路が存在する割合

と考えます。攻撃経路の存在は非常に重要で,脆弱性があり高確率で攻撃できダメージが大きくても,誰もその機能を利用していないので攻撃経路が存在しない場合は影響はないと言えます※2⁠。

※2

CVEでも利用されているCVSSでは,人為的な感覚などが入らないように確率や割合などの要素は最小限になるようになっています。しかし,特定のシステムへの影響評価では攻撃が成功する確率や攻撃経路の存在は非常に重要な要素になります。

Crypt MD5でパスワードが無効になるバグの「攻撃が成功した場合のダメージ × 攻撃が成功する確率」はとても高いですが,ざっと見た限りでは広く利用されているアプリケーションへの影響(⁠⁠攻撃経路が存在する確率⁠⁠)は大きいとは言えないようです。 Crypt Blowfishの問題は「攻撃経路が存在する確率」はかなり高いようですが,実際に攻撃するにはパスワードデータベースを盗む必要があるので「攻撃が成功した場合のダメージ × 攻撃が成功する確率」は低いと言えるでしょう。

自分の利用しているシステムへの影響を評価する場合,⁠攻撃経路が存在する確率」が非常に重要です。攻撃経路となる機能を利用していなければシステムが脆弱性の影響を受けないからです。

十分に知識を持っていると思われる経験者でも,セキュリティ脆弱性の評価を誤ることはよくあります。評価した時点で脆弱でなくてもアプリケーションやサービスの仕様変更で脆弱になってしまうこともよくあります。このため,PCIDSSなどのセキュリティ標準ではすべてのセキュリティパッチを速やかに適用することを求めています。

なぜMD5 Cryptのバグが混入したか?

MD5 CryptのバグとCrypt Blowfishのバグは関連しているように見えるかも知れませんが,まったく別のバグです。MD5 Cryptのバグが混入してしまった原因は二つあります。

第一の原因はリリースプロセス中にソースコードの安全性強化を目的にCの文字列関数をより安全と考えられている関数に置き換える作業をしたことです。

第二の原因はMD5 CryptのバグはPHPのテストコードでエラーとして検出していたにも関わらず見逃されたことです。折角のテストコードも実行して確認しなければ意味がありません。

上記の二つが原因ですが,第三の原因をあげるとすればCrypt Blowfishの脆弱性がリリースプロセス中に発見され,対応せざるを得なかったことでしょう。PHPプロジェクトにも品質管理を担当するQAチームがあります。QAチームはテストが失敗していることに気付いていても,Crypt Blowfishの脆弱性対応のためにテストが失敗するようになったと考えた可能性があります。リリースプロセス中の修正は新たなバグを生みやすいので最小限にすべきですが,今回はこの方針が守られていませんでした。

まとめ

PHP 5.3.7,PHP 5.3.8で修正された脆弱性は非常に深刻なものでした。しかし,深刻な脆弱性であるからといって自分が利用・開発しているシステムに大きな影響があるかどうかは別問題です。深刻な脆弱性が見つかった場合,冷静にどのような脆弱性か確認し,自身のシステムへの影響を見極める必要があります。

MD5 Cryptの問題はユニットテストを実行し確認すれば簡単に発見できる問題でした。PHPのリリース候補は広く公開されています。オープンソースはボランティアによって支えられています。余裕のある方はリリース候補のソースコードをダウンロードし,⁠make test⁠を実行して失敗するテストの原因をフィードバックしてはいかがでしょうか? もしかすると今回のようなとんでもないバグを見つけるような貢献ができるかも知れません。

Google Code Searchでcrypt関数が利用されているコードを検索した結果を見ていて,crypt関数の使い方を明らかに間違えているプロジェクトが複数あることが分かりました。次回はcrypt関数の使い方について解説したいと思います。

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書