2022年4月下旬に、Javaで実装されているECDSAの脆弱性(CVE-2022-21449)が発見されました。これはどういった脆弱性なのでしょうか、また、この脆弱性はどういったことが原因で起きたのでしょうか。
今回は暗号についてあまり詳しくない方にもわかりやすいようポイントを絞って解説したいと思います。
ECDSA(楕円曲線DSA)とは
ECDSAは、楕円曲線暗号と呼ばれる公開鍵暗号方式(※)の派生形です。DSAのアルゴリズムに楕円曲線を使用するものであり、身近にはSSL証明書に使われていたりします。
※公開鍵暗号方式とは・・・受信者が作成する2つの鍵(公開鍵と秘密鍵)を利用して、データのやり取りを行う方式です。「片方の鍵で暗号化したものはもう片方の鍵でのみ復号できる」という性質を持っており、一般に公開する方の鍵を公開鍵、公開しない方の鍵を秘密鍵と呼びます。そのため、公開鍵で暗号化された暗号文は同じ公開鍵では復号できず、復号には秘密鍵が必要ですが公開されていないため、安全に通信をすることが可能になります。
DSA(デジタル暗号アルゴリズム)とは
では、DSA(デジタル署名アルゴリズム)とはなんでしょうか。
DSAとは、「このメッセージが〇〇さんが作成したものであり、かつ中身が改ざんされていないことを確認するための仕組み」のひとつです。
DSAについてもう少し補足しますと、離散対数問題と呼ばれる数学上の問題を安全性の根拠とするデジタル署名方式の一つで、署名者(メッセージの送信者)は送信メッセージから生成したハッシュ値と秘密鍵を含む計算によりデジタル署名 r , s を生成してメッセージに添付します。
検証者(メッセージの受信者)は署名者(メッセージの送信者)の公開鍵を取得し署名の検証を行うことで、その署名が真正で改ざんされていないことを確かめることができます。署名の検証では、デジタル署名sと公開鍵を用いてr’を生成します。それとrを比較して同一であれば改ざんされていない(=真正性が担保されている)という判定を行います。
つまり繰り返しになりますが、署名の検証を行うことでAさんからのメッセージが間違いなくAさんから送信されたものであり内容も改ざんされていないということが証明できる、というものです。
こうした仕組みがあると、オレオレ詐欺のように赤の他人が本人に成りすましているのではないかということを疑う必要なく、安心してメッセージに反応することができますね。
脆弱性の概要
ここまでDSAについて解説してきましたが、続けて本脆弱性の概要にうつります。
JavaにはECDSAの署名を検証する仕組みが存在します。
上述している通り、署名を検証する際には r , s の2つの値が必要です。2つの値 r , s はなんでも良いわけではなく、「1以上、n-1以下」という制約があります(nは署名生成時に使用した大きな素数)。今回の脆弱性はr , s のどちらかの値を0にする、または両方の値を0にした場合に「署名は有効」と返してしまうというものです。
一体何故このようなことになってしまったのでしょうか。
脆弱性の原因は・・・チェック漏れ?
ECDSAは先に記載したとおり数学において解を求めるのが非常に困難であることを安全性の根拠としています。具体的には署名を検証する過程で下記に記述する計算を行います。
\begin{align} m = s^{-1}\bmod n \end{align} \begin{align} u_1 = rw\bmod n \end{align}他にも計算は行っていますが今回のJavaの脆弱性では、この計算を行う前の入力値のチェックがされておらず、r か s が0であっても署名の検証を行ってしまい結果としてこのような脆弱性に発展することとなってしまいました。
今回の報告を受けて修正された内容の一部分が以下の図です。赤が修正前、緑が修正後です。しっかり修正されて r と s が0より上の数値であることのチェックが入っています。
まとめ
今回の脆弱性は、面倒ではありますが閾値のチェックをしないと大惨事の危険性がある、ということの具体例ですね。こうした脆弱性は稀に見つかっています。閾値チェック自体は難しいことではないですが見落としがちです。このような事態を踏まえ、今後のWebサイト運営では是非怠らないよう閾値チェックすることをお勧めします。
なお、自社のWebサイトの脆弱性を一度全体的に確認したい、という場合に、弊社では脆弱性診断サービスがございますので、宜しければご検討ください。
この記事が皆さんの管理するWebサイトとインターネットの世界を安全にする一助となれば幸いです。