exponenta event banner

X.509 одноранговый сертификат не проверен

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

Описание

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

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

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

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

Проверка не вызывает дефектов, если:

  • Контекст 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);
    }

    /*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++
По умолчанию: Откл.
Синтаксис командной строки: CRYPTO_SSL_CERT_NOT_CHECKED
Воздействие: среднее
CWE ID: 287
Представлен в R2020a