Best practices voor TLS/SSL

TLS (Transport Layer Security) is een cryptografisch protocol dat is ontworpen om de communicatie tussen twee computers via internet te beveiligen. Het TLS-protocol wordt via de SslStream klasse in .NET weergegeven.

In dit artikel vindt u aanbevolen procedures voor het instellen van beveiligde communicatie tussen client en server en wordt ervan uitgegaan dat .NET wordt gebruikt. Zie best practices voor Transport Layer Security (TLS) met .NET Framework voor best practices voor best practices voor .NET Framework.

TLS-versie selecteren

Hoewel het mogelijk is om de versie van het TLS-protocol op te geven die via de EnabledSslProtocols eigenschap moet worden gebruikt, is het raadzaam om de instellingen van het besturingssysteem uit te stellen met behulp van None waarde (dit is de standaardinstelling).

Als u de beslissing voor het besturingssysteem uitstelt, wordt automatisch de meest recente versie van TLS gebruikt die beschikbaar is en kan de toepassing wijzigingen ophalen na upgrades van het besturingssysteem. Het besturingssysteem kan ook het gebruik van TLS-versies voorkomen die niet langer als veilig worden beschouwd.

Coderingssuites selecteren

SslStream staat gebruikers toe om op te geven welke coderingssuites kunnen worden onderhandeld door de TLS-handshake via de CipherSuitesPolicy klasse. Net als bij TLS-versies is het raadzaam om het besturingssysteem te laten beslissen met welke suites de beste coderingssuites moeten worden onderhandeld, en daarom wordt het aanbevolen om het gebruik CipherSuitesPolicyte vermijden.

Notitie

CipherSuitesPolicy wordt niet ondersteund in Windows en pogingen om het te instantiëren, zal ertoe leiden NotSupportedException dat er een fout optreedt.

Een servercertificaat opgeven

Voor verificatie als een server SslStream is een X509Certificate2 exemplaar vereist. Het is raadzaam altijd een X509Certificate2 instantie te gebruiken die ook de persoonlijke sleutel bevat.

Er zijn meerdere manieren waarop een servercertificaat kan worden doorgegeven aan SslStream:

De aanbevolen methode is om de SslServerAuthenticationOptions.ServerCertificateContext eigenschap te gebruiken. Wanneer het certificaat op een van de andere twee manieren wordt verkregen, wordt er intern een SslStreamCertificateContext exemplaar gemaakt door de SslStream implementatie. Het maken van een SslStreamCertificateContext taak omvat het bouwen van een X509Chain bewerking die een CPU-intensieve bewerking is. Het is efficiënter om één keer een SslStreamCertificateContext exemplaar te maken en opnieuw te gebruiken voor meerdere SslStream exemplaren.

Het hergebruik van SslStreamCertificateContext exemplaren maakt ook extra functies mogelijk, zoals TLS-sessiehervatting op Linux-servers.

Aangepaste X509Certificate validatie

Er zijn bepaalde scenario's waarin de standaardvalidatieprocedure voor certificaten niet voldoende is en een aantal aangepaste validatielogica is vereist. Onderdelen van de validatielogica kunnen worden aangepast door op te geven SslClientAuthenticationOptions.CertificateChainPolicy of SslServerAuthenticationOptions.CertificateChainPolicy. U kunt ook volledig aangepaste logica opgegeven via de <eigenschap System.Net.Security.SslClientAuthenticationOptions.RemoteCertificateValidationCallback> . Zie Aangepaste certificaatvertrouwensrelatie voor meer informatie.

Aangepast certificaatvertrouwen

Wanneer u een certificaat tegenkomt dat niet is uitgegeven door een van de certificeringsinstanties die worden vertrouwd door de computer (inclusief zelfondertekende certificaten), mislukt de standaardprocedure voor certificaatvalidatie. Een mogelijke manier om dit op te lossen, is door de benodigde certificaten van verleners toe te voegen aan het vertrouwde archief van de computer. Dat kan echter van invloed zijn op andere toepassingen op het systeem en is niet altijd mogelijk.

De alternatieve oplossing is het opgeven van aangepaste vertrouwde basiscertificaten via een X509ChainPolicy. Als u een aangepaste vertrouwenslijst wilt opgeven die wordt gebruikt in plaats van de lijst met systeemvertrouwensrelaties tijdens de validatie, kunt u het volgende voorbeeld bekijken:

SslClientAuthenticationOptions clientOptions = new();

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

Clients die zijn geconfigureerd met het voorgaande beleid, accepteren alleen certificaten die worden vertrouwd door customIssuerCert.

Specifieke validatiefouten negeren

Overweeg een IoT-apparaat zonder permanente klok. Na het inschakelen zou de klok van het apparaat vele jaren in het verleden beginnen en daarom worden alle certificaten beschouwd als 'nog niet geldig'. Bekijk de volgende code waarin een validatie-callback-implementatie wordt weergegeven, waarbij schendingen van de geldigheidsperiode worden genegeerd.

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

Certificaat vastmaken

Een andere situatie waarin validatie van aangepaste certificaten nodig is, is wanneer clients verwachten dat servers een specifiek certificaat of een certificaat van een kleine set bekende certificaten gebruiken. Deze procedure wordt certificaatpinning genoemd. Het volgende codefragment toont een validatieaanroep die controleert of de server een certificaat met een specifieke openbare sleutel presenteert.

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

Overwegingen voor validatie van clientcertificaten

Servertoepassingen moeten voorzichtig zijn bij het vereisen en valideren van clientcertificaten. Certificaten kunnen de AIA-extensie (Authority Information Access) bevatten die aangeeft waar het certificaat van de uitgever kan worden gedownload. De server kan daarom proberen om het certificaat van de uitgever te downloaden van externe server bij het bouwen van het X509Chain voor het clientcertificaat. Op dezelfde manier moeten servers mogelijk contact opnemen met externe servers om ervoor te zorgen dat het clientcertificaat niet is ingetrokken.

De noodzaak om contact op te maken met externe servers bij het bouwen en valideren van de X509Chain toepassing kan worden blootgesteld aan Denial of Service-aanvallen als de externe servers traag reageren. Daarom moeten servertoepassingen het gedrag van het X509Chain gebouw configureren met behulp van de CertificateChainPolicy.