Condividi tramite


Procedure consigliate per TLS/SSL

TLS (Transport Layer Security) è un protocollo crittografico progettato per proteggere la comunicazione tra due computer tramite Internet. Il protocollo TLS viene esposto in .NET tramite la SslStream classe .

Questo articolo presenta le procedure consigliate per configurare la comunicazione sicura tra client e server e presuppone l'uso di .NET. Per le procedure consigliate con .NET Framework, vedere Procedure consigliate per Transport Layer Security (TLS) con .NET Framework.

Selezionare la versione TLS

Sebbene sia possibile specificare la versione del protocollo TLS da usare tramite la EnabledSslProtocols proprietà , è consigliabile rinviare le impostazioni del sistema operativo usando None il valore (impostazione predefinita).

Rinviare la decisione al sistema operativo usa automaticamente la versione più recente di TLS disponibile e consente all'applicazione di rilevare le modifiche dopo gli aggiornamenti del sistema operativo. Il sistema operativo può anche impedire l'uso di versioni TLS che non sono più considerate sicure.

Selezionare suite di crittografia

SslStream consente agli utenti di specificare quali suite di crittografia possono essere negoziate dall'handshake TLS tramite la CipherSuitesPolicy classe . Come per le versioni di TLS, è consigliabile consentire al sistema operativo di decidere con quali sono le migliori suite di crittografia con cui negoziare e, di conseguenza, è consigliabile evitare di usare CipherSuitesPolicy.

Annotazioni

CipherSuitesPolicy non è supportato su Windows e ogni tentativo di istanziarlo causerà il lancio di NotSupportedException.

Specificare un certificato server

Quando si esegue l'autenticazione come server, SslStream richiede un'istanza di X509Certificate2. È consigliabile usare sempre un'istanza X509Certificate2 che contiene anche la chiave privata.

Esistono diversi modi in cui è possibile passare un certificato server a SslStream:

L'approccio consigliato consiste nell'usare la SslServerAuthenticationOptions.ServerCertificateContext proprietà . Quando il certificato viene ottenuto da uno degli altri due modi, un'istanza SslStreamCertificateContext viene creata internamente dall'implementazione SslStream . La creazione di un SslStreamCertificateContext oggetto comporta la creazione di un oggetto X509Chain che è un'operazione che richiede un utilizzo intensivo della CPU. È più efficiente creare una SslStreamCertificateContext sola volta e riutilizzarla per più SslStream istanze.

Il riutilizzo delle SslStreamCertificateContext istanze abilita anche funzionalità aggiuntive, ad esempio la ripresa della sessione TLS nei server Linux.

Convalida personalizzata X509Certificate

Esistono alcuni scenari in cui la procedura di convalida del certificato predefinita non è adeguata e è necessaria una logica di convalida personalizzata. Le parti della logica di convalida possono essere personalizzate specificando SslClientAuthenticationOptions.CertificateChainPolicy o SslServerAuthenticationOptions.CertificateChainPolicy. In alternativa, è possibile fornire logica completamente personalizzata tramite la <proprietà System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Per altre informazioni, vedere Attendibilità dei certificati personalizzati.

Fiducia certificato personalizzata

Quando viene rilevato un certificato che non è stato emesso da alcuna autorità di certificazione attendibile dal computer (inclusi i certificati autofirmati), la procedura di convalida del certificato predefinita avrà esito negativo. Un modo possibile per risolvere questo problema consiste nell'aggiungere i certificati dell'autorità di certificazione necessari all'archivio attendibile del computer. Ciò, tuttavia, potrebbe influire su altre applicazioni nel sistema e non è sempre possibile.

La soluzione alternativa consiste nel specificare certificati radice attendibili personalizzati tramite un oggetto X509ChainPolicy. Per specificare un elenco di attendibilità personalizzato che verrà usato anziché l'elenco di attendibilità del sistema durante la convalida, considerare l'esempio seguente:

SslClientAuthenticationOptions clientOptions = new();

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

I client configurati con i criteri precedenti accettano solo certificati attendibili da customIssuerCert.

Ignorare errori di convalida specifici

Si consideri un dispositivo IoT senza un orologio permanente. Dopo l'accensione, l'orologio del dispositivo inizierebbe molti anni in passato e, pertanto, tutti i certificati sarebbero considerati "non ancora validi". Si consideri il codice seguente che mostra un'implementazione di callback di convalida ignorando le violazioni del periodo di 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;
}

Aggiunta di certificati

Un'altra situazione in cui è necessaria la convalida personalizzata dei certificati è quando i client prevedono che i server usino un certificato specifico o un certificato da un piccolo set di certificati noti. Questa procedura è nota come bloccaggio dei certificati. Il frammento di codice seguente mostra un callback di convalida che verifica che il server presenti un certificato con una chiave pubblica nota specifica.

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

Considerazioni sulla convalida dei certificati client

Le applicazioni server devono fare attenzione quando richiedono e convalidano i certificati client. I certificati possono contenere l'estensione AIA (Authority Information Access) che specifica dove è possibile scaricare il certificato dell'autorità di certificazione. Il server può quindi tentare di scaricare il certificato emittente dal server esterno nella costruzione della X509Chain per il certificato del client. Analogamente, i server potrebbero dover contattare i server esterni per assicurarsi che il certificato client non sia stato revocato.

La necessità di contattare i server esterni durante la compilazione e la convalida del X509Chain può esporre l'applicazione ad attacchi di denial of service se i server esterni sono lenti a rispondere. Pertanto, le applicazioni server devono configurare il comportamento di X509Chain costruzione usando CertificateChainPolicy.