メインコンテンツ

X.509 ピア証明書が確認されていません

接続が中間者攻撃に対して脆弱な可能性がある

説明

この欠陥は、接続の処理時に TLS/SSL 接続の認証に使用される X.509 証明書を適切にチェックしなかった場合に発生します。証明書を適切にチェックするには、次の 2 つの関数を一緒に呼び出して証明書を取得し、検証する必要があります。

  • SSL_get_peer_certificate:認証しようとしているクライアントまたはサーバーから証明書を取得します。この関数は、証明書が存在しない場合に NULL を返します。関数が証明書を返した場合でも、証明書をチェックする必要があります。

  • SSL_get_verify_result:クライアントまたはサーバーから提供された証明書を検証します。この関数を呼び出す前に証明書を取得していなかった場合は、検証エラーが発生せず、関数は正常に戻されます。

チェッカーは、TLS/SSL 接続に対して読み書きしようとしたときに関数 SSL_read または SSL_write に関する欠陥を報告します。

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

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

  • 匿名の暗号スイートを使用している。

リスク

認証しようとしているピアの証明書の妥当性を適切にチェックしなかった場合は、接続が中間者攻撃に対して脆弱になる可能性があります。

修正方法

証明書の妥当性を適切にチェックするには、SSL_get_peer_certificateSSL_get_verify_result の両方を呼び出します。

すべて展開する


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

#define fatal_error() exit(-1)

int len;
unsigned char buf;

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();

    /* Set to require peer (client) certificate */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

    /* Handle connection */
    ssl = SSL_new(ctx);
    if (ssl == NULL) fatal_error();
    ret = SSL_set_fd(ssl, NULL);
    if (!ret) fatal_error();
    ret = SSL_connect(ssl);
    if (ret <= 0) fatal_error();

    /* 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);
    }

    /*Read message from the client.*/
    ret = SSL_read(ssl, (void*)buf, len);
    if (ret <= 0) fatal_error();

    /* Close connection */
    SSL_free(ssl);
    SSL_CTX_free(ctx);
}

この例では、サーバー接続メソッド用の TLS/SSL コンテキストが作成されます。その後で、関数 SSL_get_peer_certificate が接続を認証するためにクライアント証明書を要求します。しかし、サーバーは、返された証明書の妥当性をチェックせずに、接続から読み取ろうとします。証明書が無効である可能性があるため、接続は中間者攻撃に対して脆弱になります。

修正 — 返された証明書の妥当性をチェックする

1 つの修正方法として、SSL_get_verify_result を呼び出すことによって、返された証明書の妥当性をチェックします。


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

#define fatal_error() exit(-1)

int len;
unsigned char buf;

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();

    /* Set to require peer (client) certificate */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

    /* Handle connection */
    ssl = SSL_new(ctx);
    if (ssl == NULL) fatal_error();
    ret = SSL_set_fd(ssl, NULL);
    if (!ret) fatal_error();
    ret = SSL_connect(ssl);
    if (ret <= 0) fatal_error();

    /* 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);
    }

    if (SSL_get_verify_result(ssl) != X509_V_OK) {
        printf("SSL Client Authentication error\n");
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        exit(0);
    }

    /*Read message from the client.*/
    ret = SSL_read(ssl, (void*)buf, len);
    if (ret <= 0) fatal_error();

    /* Close connection */
    SSL_free(ssl);
    SSL_CTX_free(ctx);
}

結果情報

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

バージョン履歴

R2020a で導入