メインコンテンツ

認証機関リストが見つかりません

認証のための証明書が信頼できない

説明

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

  • SSL_connect

  • SSL_accept

  • SSL_do_handshake

  • SSL_write

  • SSL_read

  • BIO_do_connect

  • BIO_do_accept

  • BIO_do_handshake

CA は信頼性の高い第三者機関であり、外部機関に対しデジタル証明書を発行します。証明書には、そのオーナーに関する情報が含まれます。サーバーまたはクライアントは、この情報を使用して、証明書のオーナーに対する接続を認証します。

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

  • サーバー認証に関して、信頼できる発行元によるサーバー証明書かどうかを判断するための CA リストをクライアントがもっていない。

  • クライアント認証に関して、信頼できる発行元によるクライアント証明書かどうかを判断するための CA リストをサーバーがもっていない。

リスク

CA リストがないと、信頼できる CA によって発行された証明書かどうかを判断できません。認証用の証明書を提示する機関が、その証明書に記載された機関ではない可能性もあります。接続は中間者 (MITM) 攻撃に対して脆弱です。

修正方法

作成するコンテキストに認証機関リストを読み込んで TLS/SSL 接続を処理します。

すべて展開する

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

unsigned char* buf;

int OpenConnection(char* hostname, int port)
{
    /* Open the connection */
}

SSL_CTX* InitCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(TLSv1_2_client_method());
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void func()
{
    SSL_CTX* ctx;
    int server;
    SSL* ssl;
    char buf[1024];
    int bytes;
    char* hostname, *portnum;
    int ret;

    SSL_library_init();
    hostname = "localhost";
    portnum = "4433";

    ctx = InitCTX();
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, server);
    ret = SSL_connect(ssl);
    if (SSL_get_error(ssl, ret) <= 0) {
        char* msg = "Hello???";
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        SSL_write(ssl, msg, strlen(msg));
        bytes = SSL_read(ssl, buf, sizeof(buf));
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);
    } else
        ERR_print_errors_fp(stderr);
    close(server);
    SSL_CTX_free(ctx);
}

この例では、TLS/SSL 接続を処理するためにコンテキスト ctx が初期化されます。SSL_connectctx で作成された SSL 構造体 ssl を使用してサーバーとの TLS/SSL ハンドシェイクを初期化する場合、サーバー証明書の有効性をチェックするための CA リストは存在しません。

修正 — TLS/SSL ハンドシェイクの開始前に CA リストをコンテキストに読み込む

1 つの修正方法として、SSL 構造体を初期化する前に、たとえば SSL_CTX_load_verify_locations を使用して、コンテキスト ctx 用に CA 証明書リストを指定します。

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

unsigned char* buf;

int OpenConnection(char* hostname, int port)
{
    /* Open the connection */
}

SSL_CTX* InitCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(TLSv1_2_client_method());
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void LoadCA(SSL_CTX* ctx, char* CertFile, char* CertPath)
{
    if (SSL_CTX_load_verify_locations(ctx, CertFile, CertPath) <= 0) {
        /* handle errors */
    }
}

void func()
{
    SSL_CTX* ctx;
    int server;
    SSL* ssl;
    char buf[1024];
    int bytes;
    char* hostname, *portnum;
    int ret;

    SSL_library_init();
    hostname = "localhost";
    portnum = "4433";

    ctx = InitCTX();
    LoadCA(ctx, "cacert.pem", "ca/");
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, server);
    ret = SSL_connect(ssl);
    if (SSL_get_error(ssl, ret) <= 0) {
        char* msg = "Hello???";
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        SSL_write(ssl, msg, strlen(msg));
        bytes = SSL_read(ssl, buf, sizeof(buf));
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);
    } else
        ERR_print_errors_fp(stderr);
    close(server);
    SSL_CTX_free(ctx);
}

結果情報

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

バージョン履歴

R2019b で導入