Main Content

X.509 peer certificate not checked

Connection might be vulnerable to man-in-the-middle attacks

Since R2020a

Description

The defect occurs when you do not properly check the X.509 certificate used to authenticate the TLS/SSL connection when handling the connection. To properly check the certificate, you must call these two functions together to obtain and verify the certificate.

  • SSL_get_peer_certificate: Obtains a certificate from the client or server you are trying to authenticate. The function returns NULL if no certificate is present. Even if the function returns a certificate, the certificate must still be checked.

  • SSL_get_verify_result: Verifies the certificate presented by the client or server. If you do not obtain a certificate before calling this function, there are no verification errors and the function returns successfully.

The checker raises a defect on the functions SSL_read or SSL_write when you attempt to read from or write to the TLS/SSL connection.

The checker raises no defect if:

  • You declare the SSL context outside the scope of the function handling the connection.

  • You use anonymous cypher suites.

Risk

If you do not properly check the validity of the certificate of the peer you are attempting to authenticate, your connection is vulnerable to man-in-the-middle attacks.

Fix

To properly check the validity of the certificate, call both SSL_get_peer_certificate and SSL_get_verify_result.

Examples

expand all


#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);
}

In this example, a TLS/SSL context is created for a server connection method. The function SSL_get_peer_certificate then requests the client certificate to authenticate the connection. However, the server then attempts to read from the connection without checking the validity of the returned certificate. The certificate might be invalid, and the connection could be vulnerable to a man-in-the-middle attack.

Correction — Check the Validity of the Returned Certificate

One possible correction is to check the validity of the returned certificate by calling 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);
}

Result Information

Group: Cryptography
Language: C | C++
Default: Off
Command-Line Syntax: CRYPTO_SSL_CERT_NOT_CHECKED
Impact: Medium

Version History

Introduced in R2020a