5

Ich brauche eine gute Möglichkeit, Zertifikat oder Public-Key-Pinning in einer Windows 10 Universal-Anwendung zu implementieren. Der ganze Code ist in C# und alle Verbindungen sind HTTPS, also wäre etwas für die Klasse Windows.Web.Http.HttpClient großartig. Gibt es eine einfache Klasse/Bibliothek oder zumindest eine Schritt-für-Schritt-Anleitung, wie man diese Dinge implementiert, die sicher von jemandem ausgeführt werden können, der die obskuren Details von X.509-Zertifikaten nicht kennt?Zertifikat Pinning in Windows 10 Universal App

Einige Dinge, die ich gefunden habe, sprechen über die Verwendung von nativem Code oder Bibliotheken von Drittanbietern wie OpenSSL (sehr kompliziert!). Das Beste, was ich gefunden habe, ist this question über Pinning in WP8.0, die ein Code-Beispiel enthält, das auf WP8.1 und hoffentlich auch Win10 funktionieren sollte, aber es ist irgendwie hässlich und verwirrend, und ich bin mir nicht sicher, wie man es benötigt dass das Zertifikat des Servers ist eines der gepinnten beim Senden der Anfrage mit den sensiblen Informationen. Eine vorherige Überprüfung erscheint aufgrund von TOCTOU-Angriffen nicht sicher (es sei denn, die Funktion HttpRequestMessage. TransportInformation öffnet die Verbindung und hält sie offen, so dass ein Angreifer keine Chance hat, einen Mann zu gewinnen -in-the-middle Position auf einer neuen Verbindung). Idealerweise gibt es eine Möglichkeit, den HttpClient so zu filtern, dass er sich nur mit Servern mit gepinnten Zertifikaten verbindet, aber das nächste, was ich finden kann, macht genau das Gegenteil (ignorieren bestimmte Cert-Fehler, wie über here gesprochen) über die HttpBaseProtocolFilter.IgnorableServerCertificateErrors Eigenschaft, scheint keine Möglichkeit zu haben, die gültigen Zertifikate einzuschränken.

Hat jemand hier eine gute Lösung? Wenn der Ansatz HttpRequestMessage.TransportInformation (mit benutzerdefiniertem Cert-Validierungscode) die einzige Option ist, ist es gegen TOCTOU-Angriffe sicher, diese Eigenschaft vor dem Senden der Anforderung zu überprüfen?

+0

Hallo, habe ich die gleichen Probleme wie Sie, hatten Sie Glück, wie es geht? – toroveneno

Antwort

-1

Der folgende Artikel hat eine gute Lösung. Versuch es.

https://www.codeproject.com/Articles/849510/Certificate-Pinning-on-Windows-Phone

ich keine viel Erfahrung in der UWP haben aber in Fenster 8.1 Speicher-Anwendungen hat package.appxmanifest Datei, die Sie Ihre Stammzertifikate auf „Erklärung Registerkarte“ so auf den Code definieren, ermöglicht können Sie eine ordnungsgemäße Validierung zu tun.

folgenden Artikel haben auch einige gute Möglichkeiten, wie Sie Ihre App und HTTP-Verbindungen zu sichern. https://blogs.windows.com/buildingapps/2015/10/13/create-more-secure-apps-with-less-effort-10-by-10/#bWSeoR0pMyW2H8fg.97

1

Haben Sie sich das ServerCustomValidationRequested-Ereignis von HttpBaseProtocolFilter angesehen? Der schwierige Teil für mich war das Extrahieren des öffentlichen Zertifikats aus dem Zertifikatobjekt. Dazu musste ich das System.Security.Cryptography.X509Certificates nuget-Paket einspielen. Mein Code sieht so aus:

private void DoIt() 
{ 
    using (var filter = new HttpBaseProtocolFilter()) 
    { 
     filter.ServerCustomValidationRequested += FilterOnServerCustomValidationRequested; 
     var httpClient = new Windows.Web.Http.HttpClient(filter); 
     var myString = await httpClient.GetStringAsync(new Uri("https://myserver.com")); 
     // I guess we should be kind and unsubscribe? 
     filter.ServerCustomValidationRequested -= FilterOnServerCustomValidationRequested; 
    } 
} 

private void FilterOnServerCustomValidationRequested(HttpBaseProtocolFilter sender, HttpServerCustomValidationRequestedEventArgs args) 
{ 
    if (!IsCertificateValid(args.RequestMessage, args.ServerCertificate, args.ServerCertificateErrors)) 
    { 
     args.Reject(); 
    } 
} 

private bool IsCertificateValid(Windows.Web.Http.HttpRequestMessage httpRequestMessage, Certificate cert, IReadOnlyList<ChainValidationResult> sslPolicyErrors) 
{ 
    // disallow self-signed certificates or certificates with errors 
    if (sslPolicyErrors.Count > 0) 
    { 
     return false; 
    } 

    if (RequestRequiresCheck(httpRequestMessage.RequestUri)) 
    { 
     var certificateSubject = cert?.Subject; 
     bool subjectMatches = certificateSubject == CERTIFICATE_COMMON_NAME; 

     var certArray = cert?.GetCertificateBlob().ToArray(); 
     var x509Certificate2 = new X509Certificate2(certArray); 
     var certificatePublicKey = x509Certificate2.GetPublicKey(); 
     var certificatePublicKeyString = Convert.ToBase64String(certificatePublicKey); 
     bool publicKeyMatches = certificatePublicKeyString == CERTIFICATE_PUBLIC_KEY; 

     return subjectMatches && publicKeyMatches; 
    } 

    return true; 
} 

private bool RequestRequiresCheck(Uri uri) 
{ 
    return uri.IsAbsoluteUri && 
      uri.AbsoluteUri.StartsWith("https://", StringComparison.CurrentCultureIgnoreCase) && 
      uri.AbsoluteUri.StartsWith(BASE_URL, StringComparison.CurrentCultureIgnoreCase); 
} 
+0

Übrigens habe ich die Lösung zum Extrahieren des öffentlichen Schlüssels von hier: https://Stackoverflow.com/a/38126387/40783. Ich würde es gerne tun, ohne eine zusätzliche nugget-Referenz, vielleicht über 'Windows.Security.Cryptography.Core.PersistedKeyProvider.OpenPublicKeyFromCertificate', aber ich konnte die Argumente nicht korrekt erhalten, um es funktionieren zu lassen und die korrekte Anzahl an Bytes zurückzugeben. Bitte teilen Sie, wenn jemand eine sauberere Lösung finden kann. –

Verwandte Themen