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 вне осциллографа функции, обрабатывающей связь.

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

Риск

Если вы правильно не проверяете валидность сертификата о коллеге, вы пытаетесь аутентифицировать, ваша связь уязвима для атак "человек посередине".

Фиксация

Чтобы правильно проверять валидность сертификата, вызовите оба 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
Удар: носитель
ID CWE: 287
Введенный в R2020a