メインコンテンツ

X.509 証明書が見つかりません

サーバーまたはクライアントが認証できない

説明

この欠陥は、TLS/SSL 接続を処理するコンテキストで以下の関数を使用したが、そのコンテキストに X.509 証明書を読み込まなかった場合に発生します。

  • SSL_accept

  • SSL_connect

  • SSL_do_handshake

  • SSL_write

  • SSL_read

  • BIO_do_accept

  • BIO_do_connect

  • BIO_do_handshake

X.509 証明書は、エンティティに対して発行されるデジタル証明書です。エンティティを識別する情報が含まれます。この証明書は、そこで識別されたエンティティに対する接続を認証するために使用されます。

チェッカーは以下の場合に欠陥を報告します。

  • サーバー認証に関して、接続処理の前に証明書が読み込まれていない。

  • クライアント認証に関して、クライアントが初回接続試行時に SSL_ERROR_WANT_X509_LOOKUP エラーを受けた後、再度サーバーへの接続を試みた。

リスク

コンテキストに X.509 証明書を読み込まずに TLS/SSL 接続を処理する場合、その接続は安全ではなく、中間者 (MITM) 攻撃に対して脆弱なものとなります。

修正方法

作成するコンテキストに X.509 証明書を読み込んで TLS/SSL 接続を処理します。

すべて展開する

#include <openssl/ssl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;
int len;

SSL_CTX* InitServerCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(SSLv23_server_method());
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

int OpenListener(int port)
{
    /* Create server socket */
}

void func()
{
    SSL_CTX* ctx;
    int server, port;
    int ret;
    SSL_library_init();

    ctx = InitServerCTX();
    server = OpenListener(port);
    while (1) {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL* ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);
        printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client);
        ret = SSL_accept(ssl);
        if (SSL_get_error(ssl, ret) <= 0)
            /* Serve connection */;
        else
            SSL_free(ssl);
    }
    close(server);
    SSL_CTX_free(ctx);
}

この例では、InitServerCTX() が TLS/SSL 接続のためにコンテキスト ctx を初期化しますが、証明書が ctx に読み込まれていません。SSL_acceptctx から作成された SSL 構造体の TLS/SSL ハンドシェイクをチェックする際、サーバーを認証するために利用できる証明書が存在していません。

修正 — SSL 構造体を作成する前に証明書をコンテキストに読み込む

1 つの修正方法として、SSL 構造体を作成する前に、たとえば SSL_CTX_use_certificate_file を使用して、TLS/SSL 接続用に作成するコンテキストに証明書を読み込みます。

#include <openssl/ssl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;
int len;

SSL_CTX* InitServerCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(SSLv23_server_method());
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) {
        /* Handle errors */
    }
}

int OpenListener(int port)
{
    /* Create server socket */
}

void func()
{
    SSL_CTX* ctx;
    int server, port;
    int ret;
    SSL_library_init();

    ctx = InitServerCTX();
    LoadCertificates(ctx, "mycert.pem", "mycert.pem");
    server = OpenListener(port);
    while (1) {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL* ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);
        printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client);
        ret = SSL_accept(ssl);
        if (SSL_get_error(ssl, ret) <= 0)
            /* Serve connection */;
        else
            SSL_free(ssl);
    }
    close(server);
    SSL_CTX_free(ctx);
}

結果情報

グループ: 暗号化
言語: C | C++
既定値: オフ
コマンド ライン構文: CRYPTO_SSL_NO_CERTIFICATE
影響度: Medium

バージョン履歴

R2019b で導入