ISS X-Force Database: openssl-cmsverify-security-bypass(49432): OpenSSL CMS_verify() function security bypass
OpenSSL could allow a remote attacker to bypass security restrictions, caused by an error in the CMS_verify() function when handling error conditions. An attacker could exploit this vulnerability using malformed signed attributes containing invalid signed attributes to bypass content digest checks.


2009年3月25日頃、OpenSSL 0.9.8のh、i、jの3世代のマイナーバージョンのCMS署名の検証に脆弱性があった問題が報告され、問題修正されたそうですね。

・OpenSSL 0.9.8h (2008.05.28) ×脆弱
・OpenSSL 0.9.8i (2008.09.15) ×脆弱
・OpenSSL 0.9.8j (2009.01.07) ×脆弱
・OpenSSL 0.9.8k (2009.03.25) ○問題修正

OpenSSLはいろいろな製品にも使われていて、汎用の署名アプリ、S/MIME署名メールやCAdES長期署名のベースとしてこれが使われていることもあるので、まぁ、それなりに影響があります。

今日は夕方暇だったので、何が問題だったのかちょっと見てみました。問題のコードは "crypto/cms/cms_smime.c" の CMS_verify() 関数なんだそうなんですが、修正されたのは条件式が "!" か "<=" かだけの違いです。


crypto/cms/cms_smime.c 428行目
×修正前:if (!CMS_SignerInfo_verify_content(si, cmsbio))
○修正後:if (CMS_SignerInfo_verify_content(si, cmsbio) <= 0)


CMS_SignerInfo_verify_content()関数は "crypto/cms/cms_sd.c" で定義されており、署名対象文書となるencapContentInfo中のeContentと署名情報SignerInfoに対して

・SignerInfoに署名属性あればMessageDigest属性中のハッシュ値と
  eContentから計算されたハッシュ値が一致するか
・SignerInfoに署名属性が無ければeContentに対する署名値が一致するか

検証する関数です。

では、CMS_SignerInfo_verify_content()関数の戻り値はどうなのかを調べてみますと、

戻り値 "1" の場合(署名対象文書eContentのハッシュ/署名一致):
・MessageDigest属性がありeContentのハッシュ値と一致する場合
・署名属性がなくeContentの署名値がsignatureフィールドと一致する場合

戻り値 "0" の場合(署名対象文書eContentのハッシュ/署名不一致エラー):
・MessageDigest属性がありハッシュ長一致だがハッシュ値が不一致の場合
・署名属性がなくeContentの署名値がsignatureフィールドと不一致の場合

戻り値 "-1" の場合(その他のエラー):
・署名属性フィールドがあるのにMessageDigest属性がない場合
・SignerInfoのdigestAlgorithmのアルゴリズムが不明など
 ハッシュ計算コンテキストの初期化に失敗した場合
・MessageDigest属性がありeContentからのハッシュ値計算に失敗した場合
・MessageDigest属性がありその属性値と計算結果のハッシュと結果長が不一致

なようです。で、問題のある OpenSSL 0.9.8 h〜j ではエラーケースである戻り値"-1"の場合でも、(! 1)==0と同じく(! -1)==0でありゃりゃスルーっと署名検証成功バッチリOKになってしまうようで、

・署名対象文書(eContent)とハッシュ値が不一致だろうが
・わざと知らなそうなマイナーなアルゴリズムをdigestAlgorithmを設定してやれば

CMS署名検証OKとできたようです。

署名対象文書(eContent)と一致確認をしていないのは、かなりマズーでしたね、、、(^^;こういうショボイ間違いしちゃうのも、戻り値とか関数の説明とかコメントを全く書かないせいなんじゃないかと思ってるんですがどうでしょうか、、、、

<リンク>
OpenSSL Security Advisory [25-Mar-2009]