JavaとPythonで不正な公開鍵証明書を持つサーバに接続する

はじめに

不正な公開鍵証明書(SSLサーバ証明書)を持つサーバ接続時のパケットや例外ってどうなるんだろうと気になったので調べてみました。

不正な公開鍵証明書を持つサーバ

badssl.comというTLS/SSLクライアントの接続テストができるサイトがあります。
今回はこちらのサイトを使い、不正な公開鍵証明書を持つサーバに接続した際のパケットや例外を見ていきます。

検証に使ったTLS/SSLクライアント

検証に使った環境情報

  • Windows10 Home Edition
  • Java 9.0.1
  • Python 3.6.3
  • Wireshark 2.4.2

Javaのサンプルコード

Java Secure Socket Extension (JSSE)リファレンス・ガイド コード例を参考に作成。

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        String hostName = "<検証するホスト名>";
        SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        try (SSLSocket socket = (SSLSocket) factory.createSocket(hostName, 443)) {
            socket.startHandshake();
        }
    }
}

Pythonのサンプルコード

Python公式ドキュメント 18.2. ssl — ソケットオブジェクトに対する TLS/SSL ラッパーを参考に作成。

import socket
import ssl

if __name__ == '__main__':
    hostname = "<検証するホスト名>"
    context = ssl.create_default_context()
    try:
        ssl_socket = context.wrap_socket(socket.socket(socket.AF_INET), server_hostname=hostname)
        ssl_socket.connect((hostname, 443))
    finally:
        ssl_socket.close()

検証結果

※以下検証結果は、上記のサンプルコードを使った場合の実行結果であり、SSLContextのオプションなど変えれば例外の出方も変わります。

正常な公開鍵証明書

検証ホスト名 : badssl.com
Java/Pythonともに例外は発生せず、正常にハンドシェイクができています。

TLSv1.2	Client Hello
TLSv1.2	Server Hello,Certificate, Server Key Exchange, Server Hello Done
TLSv1.2	Client Key Exchange
...

不正な公開鍵証明書(オレオレ証明書)

検証ホスト名 : self-signed.badssl.com
Java/PythonともにAlertパケットが飛びました。

TLSv1.2	Client Hello
TLSv1.2	Server Hello,Certificate, Server Key Exchange, Server Hello Done
TLSv1.2	Alert (Level: Fatal, Description: Unknown CA)
...

またJavaでは例外発生しませんでしたが、Pythonでは以下の例外が発生しました。

...
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

不正な公開鍵証明書(ホスト名違い)

検証ホスト名 : wrong.host.badssl.com
Java/Pythonともにパケット上は、正常にハンドシェイクができています。

TLSv1.2	Client Hello
TLSv1.2	Server Hello,Certificate, Server Key Exchange, Server Hello Done
TLSv1.2	Client Key Exchange
...

Javaでは例外が発生しませんでしたが、Pythonでは以下の例外が発生しました。

...
ssl.CertificateError: hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'

不正な公開鍵証明書(期限切れ)

検証ホスト名 : expired.badssl.com
Java/PythonともにAlertパケットが飛びました。

TLSv1.2	Client Hello
TLSv1.2	Server Hello,Certificate, Server Key Exchange, Server Hello Done
TLSv1.2	Alert (Level: Fatal, Description: Certificate Unknown)
...

Javaでは以下の例外が発生。

...
Exception in thread "main" javax.net.ssl.SSLHandshakeException
...
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Mon Apr 13 08:59:59 JST 2015
...

Pythonでは以下の例外が発生。

...
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)
...

まとめ

普段SSLSocketから作成する機会はあまりないですが、ミニマムの実装で試すと他の余計な情報が入ってこないので、プロトコルレベルの確認がやりやすいですね。

参考リンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA