Partager via


Bonnes pratiques TLS/SSL

TLS (Transport Layer Security) est un protocole de chiffrement conçu pour sécuriser la communication entre deux ordinateurs via Internet. Le protocole TLS est exposé dans .NET via la SslStream classe.

Cet article présente les meilleures pratiques pour configurer la communication sécurisée entre le client et le serveur et suppose l’utilisation de .NET. Pour connaître les meilleures pratiques avec .NET Framework, consultez les meilleures pratiques tls (Transport Layer Security) avec .NET Framework.

Sélectionner la version TLS

Bien qu’il soit possible de spécifier la version du protocole TLS à utiliser via la EnabledSslProtocols propriété, il est recommandé de s'en remettre aux paramètres du système d’exploitation à l’aide de la valeur None (il s’agit de la valeur par défaut).

Remettre la décision au système d'exploitation utilise automatiquement la version la plus récente de TLS disponible et permet à l'application de récupérer les modifications après les mises à jour du système d'exploitation. Le système d’exploitation peut également empêcher l’utilisation de versions TLS qui ne sont plus considérées comme sécurisées.

Sélectionner des suites de chiffrement

SslStream permet aux utilisateurs de spécifier les suites de chiffrement qui peuvent être négociées par l’établissement d’une liaison TLS via la CipherSuitesPolicy classe. Comme avec les versions TLS, il est recommandé de laisser le système d’exploitation décider qui sont les meilleures suites de chiffrement avec lesquelles négocier, et par conséquent, il est recommandé d’éviter d’utiliser CipherSuitesPolicy.

Remarque

CipherSuitesPolicy n’est pas pris en charge sur Windows et les tentatives d’instanciation entraînent la levée d’une NotSupportedException.

Spécifier un certificat de serveur

Lors de l’authentification en tant que serveur, SslStream nécessite une X509Certificate2 instance. Il est recommandé d’utiliser toujours une X509Certificate2 instance qui contient également la clé privée.

Il existe plusieurs façons qu’un certificat de serveur puisse être passé à SslStream:

L’approche recommandée consiste à utiliser la SslServerAuthenticationOptions.ServerCertificateContext propriété. Lorsque le certificat est obtenu de l’une des deux autres façons, une SslStreamCertificateContext instance est créée en interne par l’implémentation SslStream . La création d’un SslStreamCertificateContext implique la création d’une X509Chain, une opération qui nécessite beaucoup de puissance CPU. Il est plus efficace de créer une SslStreamCertificateContext fois et de le réutiliser pour plusieurs SslStream instances.

La réutilisation des SslStreamCertificateContext instances active également des fonctionnalités supplémentaires telles que la reprise de session TLS sur les serveurs Linux.

Validation personnalisée X509Certificate

Il existe certains scénarios dans lesquels la procédure de validation de certificat par défaut n’est pas adéquate et une logique de validation personnalisée est requise. Les parties de la logique de validation peuvent être personnalisées en spécifiant SslClientAuthenticationOptions.CertificateChainPolicy ou SslServerAuthenticationOptions.CertificateChainPolicy. Vous pouvez également fournir une logique complètement personnalisée via la <propriété System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Pour plus d'informations, consultez Confiance des certificats personnalisés.

Approbation de certificat personnalisée

Lorsque vous rencontrez un certificat qui n’a pas été émis par les autorités de certification approuvées par l’ordinateur (y compris les certificats auto-signés), la procédure de validation de certificat par défaut échoue. Pour résoudre ce problème, vous pouvez ajouter les certificats d’émetteur nécessaires au magasin approuvé de l’ordinateur. Toutefois, cela peut affecter d’autres applications sur le système et n’est pas toujours possible.

La solution alternative consiste à spécifier des certificats racines de confiance personnalisés via un X509ChainPolicy. Pour spécifier une liste d’approbation personnalisée qui sera utilisée au lieu de la liste d’approbations système lors de la validation, considérez l’exemple suivant :

SslClientAuthenticationOptions clientOptions = new();

clientOptions.CertificateChainPolicy = new X509ChainPolicy()
{
    TrustMode = X509ChainTrustMode.CustomRootTrust,
    CustomTrustStore =
    {
        customIssuerCert
    }
};

Les clients configurés avec la stratégie précédente acceptent uniquement les certificats approuvés par customIssuerCert.

Ignorer les erreurs de validation spécifiques

Envisagez un appareil IoT sans horloge persistante. Après la mise sous tension, l’horloge de l’appareil démarrerait plusieurs années dans le passé et, par conséquent, tous les certificats seraient considérés comme « non encore valides ». Considérez le code suivant qui montre une implémentation de rappel de validation ignorant les violations de période de validité.

static bool CustomCertificateValidationCallback(
    object sender,
    X509Certificate? certificate,
    X509Chain? chain,
    SslPolicyErrors sslPolicyErrors)
{
    // Anything that would have been accepted by default is OK
    if (sslPolicyErrors == SslPolicyErrors.None)
    {
        return true;
    }
    
    // If there is something wrong other than a chain processing error, don't trust it.
    if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
    {
        return false;
    }
    
    Debug.Assert(chain is not null);

    // If the reason for RemoteCertificateChainError is that the chain built empty, don't trust it.
    if (chain.ChainStatus.Length == 0)
    {
        return false;
    }

    foreach (X509ChainStatus status in chain.ChainStatus)
    {
        // If an error other than `NotTimeValid` (or `NoError`) is present, don't trust it.
        if ((status.Status & ~X509ChainStatusFlags.NotTimeValid) != X509ChainStatusFlags.NoError)
        {
            return false;
        }
    }

    return true;
}

Épinglage de certificat

Une autre situation où la validation de certificat personnalisée est nécessaire lorsque les clients s’attendent à ce que les serveurs utilisent un certificat spécifique ou qu’un certificat d’un petit ensemble de certificats connus. Cette pratique est appelée épinglage de certificat. L’extrait de code suivant montre un rappel de validation qui vérifie que le serveur présente un certificat avec une clé publique connue spécifique.

static bool CustomCertificateValidationCallback(
    object sender,
    X509Certificate? certificate,
    X509Chain? chain,
    SslPolicyErrors sslPolicyErrors)
{
    // If there is something wrong other than a chain processing error, don't trust it.
    if ((sslPolicyErrors & ~SslPolicyErrors.RemoteCertificateChainErrors) != 0)
    {
        return false;
    }
    
    Debug.Assert(certificate is not null);

    const string ExpectedPublicKey =
        "3082010A0282010100C204ECF88CEE04C2B3D850D57058CC9318EB5C" +
        "A86849B022B5F9959EB12B2C763E6CC04B604C4CEAB2B4C00F80B6B0" +
        "F972C98602F95C415D132B7F71C44BBCE9942E5037A6671C618CF641" +
        "42C546D31687279F74EB0A9D11522621736C844C7955E4D16BE8063D" +
        "481552ADB328DBAAFF6EFF60954A776B39F124D131B6DD4DC0C4FC53" +
        "B96D42ADB57CFEAEF515D23348E72271C7C2147A6C28EA374ADFEA6C" +
        "B572B47E5AA216DC69B15744DB0A12ABDEC30F47745C4122E19AF91B" +
        "93E6AD2206292EB1BA491C0C279EA3FB8BF7407200AC9208D98C5784" +
        "538105CBE6FE6B5498402785C710BB7370EF6918410745557CF9643F" +
        "3D2CC3A97CEB931A4C86D1CA850203010001";

    return certificate.GetPublicKeyString().Equals(ExpectedPublicKey);
}

Considérations relatives à la validation des certificats clients

Les applications serveur doivent être prudentes lors de la nécessité et de la validation des certificats clients. Les certificats peuvent contenir l’extension AIA (Authority Information Access) qui spécifie où le certificat émetteur peut être téléchargé. Le serveur peut donc tenter de télécharger le certificat émetteur à partir d’un serveur externe lors de la génération X509Chain du certificat client. De même, les serveurs peuvent avoir besoin de contacter des serveurs externes pour s’assurer que le certificat client n’a pas été révoqué.

La nécessité de contacter des serveurs externes lors de la génération et de la validation de X509Chain l’application peut exposer l’application à des attaques par déni de service si les serveurs externes sont lents à répondre. Par conséquent, les applications serveur doivent configurer le comportement de génération de X509Chain à l’aide du/de la CertificateChainPolicy.