メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

サーバー証明書の共通名が確認されていません

攻撃者が有効な証明書を使用して信頼できるホストになりすます可能性がある

説明

この欠陥は、サーバー証明書で指定された共通名をサーバーのドメイン名に照らしてチェックしなかった場合に発生します。

通常は、クライアントがサーバーに接続すると、サーバーを信頼できるエンティティとして識別するデジタル証明書をそのサーバーからクライアントに送信します。この証明書には、サーバーの共通名などのサーバーに関する情報が含まれています。共通名は、証明書によって信頼できるエンティティとして識別されるサーバー ドメイン名と一致します。

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

  • SSL_new を呼び出す関数に引数として SSL コンテキストを渡す。

  • 接続を処理する関数のスコープの外部で SSL コンテキストを宣言する。

リスク

悪意のある攻撃者が有効な証明書を使用して信頼できるホストになりすました結果、クライアントが信頼されていないサーバーと相互に対話する可能性があります。

修正方法

以下のいずれかの関数を使用して、プログラムによってサーバー証明書で指定された共通名に照らしてチェックされるサーバー ドメイン名を指定します。

  • SSL_set_tlsext_host_name

  • SSL_set1_host

  • SSL_add1_host

すべて展開する


#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>

#define fatal_error() exit(-1)

void check_certificate(SSL_CTX* ctx, SSL* ssl)
{
    /* Check for Client authentication error */
    if (!SSL_get_peer_certificate(ssl)) {
        printf("SSL Client Authentication error\n");
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        exit(0);
    }
    /* Check for Client authentication error */
    if (SSL_get_verify_result(ssl) != X509_V_OK) {
        printf("SSL Client Authentication error\n");
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        exit(0);
    }
}

void func()
{
    int ret;
    SSL_CTX* ctx;
    SSL* ssl;

    /* creation context for the SSL protocol */
    ctx = SSL_CTX_new(SSLv23_client_method());
    if (ctx == NULL) fatal_error();

    /* Handle connection */
    ssl = SSL_new(ctx);
    SSL_set_connect_state(ssl);
    check_certificate(ctx, ssl);
    ret = SSL_connect(ssl);
    if (ret <= 0) fatal_error();

    SSL_free(ssl);
    SSL_CTX_free(ctx);
}

この例では、SSL 構造体がクライアント接続メソッドを使用して開始されます。クライアントが check_certificate を使用してサーバー証明書を検証します。しかし、クライアントは、証明書の共通名がサーバーのドメイン名と一致するかはチェックしません。攻撃者が有効な証明書を使用して信頼できるホストになりすます可能性があります。

修正 — 証明書共通名に照らしてチェックするためのドメイン名を指定する

1 つの修正方法として、SSL_set1_host を使用して、プログラムがサーバー証明書の共通名に照らしてチェックする必要があるドメイン名を指定します。


#include <stdio.h>
#include <stdlib.h>
#include <openssl/ssl.h>

#define fatal_error() exit(-1)

void check_certificate(SSL_CTX* ctx, SSL* ssl)
{
    /* Check for Client authentication error */
    if (!SSL_get_peer_certificate(ssl)) {
        printf("SSL Client Authentication error\n");
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        exit(0);
    }
    /* Check for Client authentication error */
    if (SSL_get_verify_result(ssl) != X509_V_OK) {
        printf("SSL Client Authentication error\n");
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        exit(0);
    }
}

void func()
{
    int ret;
    SSL_CTX* ctx;
    SSL* ssl;

    /* creation context for the SSL protocol */
    ctx = SSL_CTX_new(SSLv23_client_method());
    if (ctx == NULL) fatal_error();

    /* Handle connection */
    ssl = SSL_new(ctx);
    SSL_set_connect_state(ssl);
    check_certificate(ctx, ssl);
    ret = SSL_set1_host(ssl, "www.mysite.com");
    if (ret <= 0) fatal_error();
    ret = SSL_connect(ssl);
    if (ret <= 0) fatal_error();

    SSL_free(ssl);
    SSL_CTX_free(ctx);
}
 

結果情報

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

バージョン履歴

R2020a で導入