exponenta event banner

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