X.509 peer certificate not checked

Связь может быть уязвима для атак «человек посередине»

Описание

Дефект возникает при неправильной проверке сертификата X.509, используемого для аутентификации соединения TLS/SSL при обработке соединения. Чтобы правильно проверить сертификат, необходимо вызвать эти две функции вместе, чтобы получить и проверить сертификат.

  • SSL_get_peer_certificate: Получение сертификата от клиента или сервера, на котором выполняется проверка подлинности. Функция возвращает NULL, если сертификат отсутствует. Даже если функция возвращает сертификат, сертификат все равно должен быть проверен.

  • SSL_get_verify_result: Проверка сертификата, представленного клиентом или сервером. Если вы не получите сертификат перед вызовом этой функции, нет ошибок верификации, и функция успешно возвращается.

Шашка поднимает дефект на функциях SSL_read или SSL_write при попытке чтения или записи в соединение TLS/SSL.

Шашка не поднимает дефект, если:

  • Контекст SSL объявляется вне возможностей функции, обрабатывающей соединение.

  • Вы используете анонимные наборы шифров.

Риск

Если вы неправильно проверяете валидность сертификата однорангового узла, который вы пытаетесь аутентифицировать, ваше подключение уязвимо для атак man-in-the-middle.

Зафиксировать

Чтобы правильно проверить валидность сертификата, вызовите оба SSL_get_peer_certificate и 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);
    }

    /*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 затем запрашивает сертификат клиента для проверки подлинности подключения. Однако затем сервер пытается считать с подключения, не проверяя валидность возвращенного сертификата. Возможно, сертификат недействителен, и подключение может быть уязвимо для атаки «человек посередине».

Коррекция - Проверяйте валидность возвращенного сертификата

Одной из возможных коррекций является проверка валидности возвращенного сертификата по телефону 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++
По умолчанию: Off
Синтаксис командной строки : CRYPTO_SSL_CERT_NOT_CHECKED
Влияние: Средний
ИДЕНТИФИКАТОР CWE: 287
Введенный в R2020a