exponenta event banner

Отсутствует список центра сертификации

Сертификат для проверки подлинности не может быть доверенным

Описание

Этот дефект возникает при использовании контекста для обработки соединений TLS/SSL с этими функциями, но список центра сертификации не загружается в контекст.

  • SSL_connect

  • SSL_accept

  • SSL_do_handshake

  • SSL_write

  • SSL_read

  • BIO_do_connect

  • BIO_do_accept

  • BIO_do_handshake

ЦС является доверенным третьим лицом, которое выдает цифровые сертификаты другим лицам. Сертификат содержит сведения о его владельце. Эти сведения используются сервером или клиентами для проверки подлинности подключений к владельцу сертификата.

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

  • Для проверки подлинности сервера у клиента нет списка ЦС для определения того, является ли сертификат сервера доверенным источником.

  • Для проверки подлинности клиента сервер не имеет списка ЦС для определения того, является ли сертификат клиента доверенным источником.

Риск

Без списка ЦС невозможно определить, выдан ли сертификат доверенным ЦС. Объект, который представляет сертификат для проверки подлинности, может не быть объектом, описанным в сертификате. Ваше соединение уязвимо для атак MITM.

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

Загрузите список центра сертификации в контекст, созданный для обработки подключений TLS/SSL.

Примеры

развернуть все

#include <openssl/ssl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;

int OpenConnection(char* hostname, int port)
{
    /* Open the connection */
}

SSL_CTX* InitCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(TLSv1_2_client_method());
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void func()
{
    SSL_CTX* ctx;
    int server;
    SSL* ssl;
    char buf[1024];
    int bytes;
    char* hostname, *portnum;
    int ret;

    SSL_library_init();
    hostname = "localhost";
    portnum = "4433";

    ctx = InitCTX();
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, server);
    ret = SSL_connect(ssl);
    if (SSL_get_error(ssl, ret) <= 0) {
        char* msg = "Hello???";
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        SSL_write(ssl, msg, strlen(msg));
        bytes = SSL_read(ssl, buf, sizeof(buf));
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);
    } else
        ERR_print_errors_fp(stderr);
    close(server);
    SSL_CTX_free(ctx);
}

В этом примере контекст ctx инициализируется для обработки соединений TLS/SSL. Когда SSL_connect инициализирует квитирование TLS/SSL с сервером с помощью структуры SSL ssl создан из ctx, отсутствует список ЦС для проверки действительности сертификата сервера.

Исправление - перед началом квитирования TLS/SSL загрузите список ЦС в контекст

Одно из возможных исправлений состоит в том, чтобы перед инициализацией структуры SSL указать список сертификатов ЦС для контекста ctx, например, с SSL_CTX_load_verify_locations.

#include <openssl/ssl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/err.h>

unsigned char* buf;

int OpenConnection(char* hostname, int port)
{
    /* Open the connection */
}

SSL_CTX* InitCTX(void)
{
    SSL_CTX* ctx;
    OpenSSL_add_all_algorithms();
    ctx = SSL_CTX_new(TLSv1_2_client_method());
    if (ctx == NULL) {
        /*handle errors */
    }
    return ctx;
}

void LoadCA(SSL_CTX* ctx, char* CertFile, char* CertPath)
{
    if (SSL_CTX_load_verify_locations(ctx, CertFile, CertPath) <= 0) {
        /* handle errors */
    }
}

void func()
{
    SSL_CTX* ctx;
    int server;
    SSL* ssl;
    char buf[1024];
    int bytes;
    char* hostname, *portnum;
    int ret;

    SSL_library_init();
    hostname = "localhost";
    portnum = "4433";

    ctx = InitCTX();
    LoadCA(ctx, "cacert.pem", "ca/");
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);
    SSL_set_fd(ssl, server);
    ret = SSL_connect(ssl);
    if (SSL_get_error(ssl, ret) <= 0) {
        char* msg = "Hello???";
        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        SSL_write(ssl, msg, strlen(msg));
        bytes = SSL_read(ssl, buf, sizeof(buf));
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);
    } else
        ERR_print_errors_fp(stderr);
    close(server);
    SSL_CTX_free(ctx);
}

Информация о результатах

Группа: Криптография
Язык: C | C++
По умолчанию: Откл.
Синтаксис командной строки: CRYPTO_SSL_NO_CA
Воздействие: среднее
CWE ID: 310
Представлен в R2019b