覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

CVE-2022-21449 が対象となるJavaバージョンはどれ?

Javaの脆弱性である CVE-2022-21449 が巷で話題・問題になってますが、


CVE-2022-21449は、ECDSA(楕円曲線デジタル署名アルゴリズム)のJavaの実装に欠陥があるため、不正なデジタル署名に対する検証が 誤って成功してしまう

というものです。


この脆弱性に関して、結局どの Java バージョンが影響を受けるのかについて、情報が錯綜しているようです。

ネットの情報の正しさを調べるのも面倒なので、どのJavaが影響を受けるのかはコードを書けば一応わかります。


検証用のコード

以下は、CVE-2022-21449が該当するJavaバージョンであるかを検証できるコードになります (IEEE P1363 の署名形式)

import java.security.*;

public class SignatureVerifyCheck {

    public static void main(String[] args) {
        // どのJava使ってるのか確認
        System.out.println(System.getProperty("java.vendor") + " : " + System.getProperty("java.version"));

        KeyPair keyPair;
        try {
            // Elliptic Curveアルゴリズムのキー・ペアを生成します。
            keyPair = KeyPairGenerator.getInstance("EC").generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return;
        }
        System.out.println(keyPair);

        //  ECDSAシグネチャ・アルゴリズム(IEEE P1363 の署名形式)
        //  NONEwithECDSAinP1363Format / SHA1withECDSAinP1363Format / SHA224withECDSAinP1363Format /
        //  SHA256withECDSAinP1363Format / SHA384withECDSAinP1363Format / SHA512withECDSAinP1363Format
        Signature ecdsaSignature;
        try {
            ecdsaSignature = Signature.getInstance("SHA256withECDSAinP1363Format");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return;
        }
        System.out.println(ecdsaSignature);

        // 不正な署名の代わりとなる値
        byte[] blankSignature = new byte[64];

        try {
            // 署名オブジェクトを、検証操作のために指定された公開鍵で初期化します
            ecdsaSignature.initVerify(keyPair.getPublic());
            // 署名検証する対象をセットする
            ecdsaSignature.update("Hello, World".getBytes());

            // ※渡された署名を検証する。 署名が正しく検証されたなら true, そうでなければ false が返される  はずだが...
            boolean verifyResult = ecdsaSignature.verify(blankSignature);

            System.out.println("Invalid Signature verify result : " + verifyResult);  // ※不正な署名なら false となるはず
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        }
    }
}

このコードの実行結果 で Invalid Signature verify result : true というものが出力されてしまうと、脆弱性の影響を受ける Java であることがわかります。


IEEE P1363 の署名形式 が使えない古いバージョンのJavaの場合以下の ASN.1 DER 署名形式を利用したコードで確認できます

import java.security.*;

public class SignatureVerifyCheck {

    public static void main(String[] args) {
        // どのJava使ってるのか確認
        System.out.println(System.getProperty("java.vendor") + " : " + System.getProperty("java.version"));

        KeyPair keyPair;
        try {
            // Elliptic Curveアルゴリズムのキー・ペアを生成します。
            keyPair = KeyPairGenerator.getInstance("EC").generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return;
        }
        System.out.println(keyPair);

        // ECDSAシグネチャ・アルゴリズム (ASN.1 DER 署名)
        //  NONEwithECDSA / SHA1withECDSA / SHA224withECDSA /
        //  SHA256withECDSA / SHA384withECDSA / SHA512withECDSA ...
        Signature ecdsaSignature;
        try {
            ecdsaSignature = Signature.getInstance("SHA256withECDSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return;
        }
        System.out.println(ecdsaSignature);

        // 不正な署名の代わりとなる値 (ASN.1 DER 用)
        byte[] invalidSignature = new byte[]{ 0x30, 6, 2, 1, 0, 2, 1, 0 };
        
        try {
            // 署名オブジェクトを、検証操作のために指定された公開鍵で初期化します
            ecdsaSignature.initVerify(keyPair.getPublic());
            // 署名検証する対象をセットする
            ecdsaSignature.update("Hello, World".getBytes());

            // ※渡された署名を検証する。 署名が正しく検証されたなら true, そうでなければ false が返される  はずだが...
            boolean verifyResult = ecdsaSignature.verify(invalidSignature);

            System.out.println("Invalid Signature verify result : " + verifyResult);  // ※不正な署名なら false となるはず
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        }
    }
}


いくつかのJavaで試した結果

いくつかの Java で実際に試してみて、結果がどうなるかを確認しました。


Eclipse Adoptium (AdoptOpenJDK) - 1.8.0_322

Temurin : 1.8.0_322
java.security.KeyPair@deb6432
Signature object: SHA256withECDSA<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


Eclipse Adoptium (AdoptOpenJDK) - 11.0.14.1

Eclipse Adoptium : 11.0.14.1
java.security.KeyPair@371a67ec
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


Eclipse Adoptium (AdoptOpenJDK) - 17.0.2

Eclipse Adoptium : 17.0.2
java.security.KeyPair@7a79be86
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : true

最終的な結果が true となっているので 脆弱性の影響を受けます


Amazon corretto - 1.8.0_332

Amazon.com Inc. : 1.8.0_332
java.security.KeyPair@3581c5f3
Signature object: SHA256withECDSA<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


Amazon corretto - 11.0.14.1

Amazon.com Inc. : 11.0.14.1
java.security.KeyPair@eafc191
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


Amazon corretto - 17.0.2

Amazon.com Inc. : 17.0.2
java.security.KeyPair@1d251891
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : true

最終的な結果が true となっているので 脆弱性の影響を受けます


Amazon corretto - 17.0.3

Amazon.com Inc. : 17.0.3
java.security.KeyPair@3f3afe78
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません(脆弱性に対する修正が行われています)


Oracle OpenJDK - 17.0.2

Oracle Corporation : 17.0.2
java.security.KeyPair@2752f6e2
Signature object: SHA256withECDSAinP1363Format<not initialized>
Invalid Signature verify result : true

最終的な結果が true となっているので 脆弱性の影響を受けます


Oracle JDK - 1.7.0_80

Oracle Corporation : 1.7.0_80
java.security.KeyPair@60dd1773
Signature object: SHA256withECDSA<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


Oracle JDK - 1.8.0_201

Oracle Corporation : 1.8.0_201
java.security.KeyPair@7daf6ecc
Signature object: SHA256withECDSA<not initialized>
Invalid Signature verify result : false

最終的な結果が false となっているので 脆弱性の影響を受けません


まとめ

いくつかの環境で脆弱性の影響を受けることが確認できました。

また、既に修正済みのバージョンや、そもそも対象の署名アルゴリズムが使えないバージョンも確認できました。


関連リンク