Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Certificate Pinning in Windows 10 Universal app

I need a good way to implement certificate or public-key pinning in a Windows 10 Universal application. All the code is in C#, and all connections are HTTPS, so something for the Windows.Web.Http.HttpClient class would be great. Is there a simple class/library, or at least a step-by-step guide, for how to implement this stuff that can be done safely by somebody who doesn't know the arcane details of X.509 certificates and so on?

Some things I've found talk about using native code, or third-party libraries like OpenSSL (very complicated!). The best thing I've found is this question about pinning in WP8.0, which includes a code sample that should work on WP8.1 and hopefully also Win10, but it's kind of ugly and confusing, and I'm not sure how to require that the server's certificate is one of the pinned ones when sending the request with the sensitive information. Checking beforehand doesn't seem safe because of time-of-check/time-of-use (TOCTOU) attacks (unless the HttpRequestMessage.TransportInformation function opens the connection and then holds it open so there's no chance for an attacker to gain a man-in-the-middle position on a new connection). Ideally there'd be a way to filter the HttpClient so it only connects to servers with pinned certs, but the closest thing I can find to that does exactly the opposite (ignore certain cert errors, as talked about here) via the HttpBaseProtocolFilter.IgnorableServerCertificateErrors property, which doesn't seem to have any option to restrict the valid certificates.

Does anybody have a good solution here? If the HttpRequestMessage.TransportInformation approach (with custom cert validation code) is the only option, is it safe against TOCTOU attacks to check that property before sending the request?

like image 814
CBHacking Avatar asked Jan 07 '16 23:01

CBHacking


People also ask

Is certificate pinning obsolete?

HTTP Public Key Pinning (HPKP) is an obsolete Internet security mechanism delivered via an HTTP header which allows HTTPS websites to resist impersonation by attackers using misissued or otherwise fraudulent digital certificates.

How do I setup a pinning certificate?

To deploy enterprise certificate pinning, you need to: Create a well-formatted certificate pinning rule XML file. Create a pin rules certificate trust list file from the XML file. Apply the pin rules certificate trust list file to a reference administrative computer.

Is SSL pinning mandatory?

All internet communications must be secure with SSL certificates. Since these kinds of attacks are complex to execute, SSL pinning is of utmost priority.

What is app certificate pinning?

Cert pinning is a security mechanism in which an app developer specifies certain trusted certificates used to verify the identity of computers on the network(s). Android and iOS devices are shipped with a default list of trusted root certificate authorities (CA) pre-installed by the manufacturer.


2 Answers

Have you taken a look at the ServerCustomValidationRequested event off of HttpBaseProtocolFilter? The tricky part for me was extracting the public certificate out of the Certificate object. To do that I had to bring in the System.Security.Cryptography.X509Certificates nuget package. My code looks like this:

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

p.s. I ended up writing a blog post about certificate pinning in UWP if you're interested in more details

like image 121
Lee Richardson Avatar answered Oct 12 '22 06:10

Lee Richardson


Following article has a good solution. Try it.

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

I have no much experience in UWP but in Window 8.1 store apps has package.appxmanifest file which enables you to define your root certificates on "Declaration tab" so, on the code you can do a proper validation.

following article also have few good ways defined on how to secure you app and HTTP connections. https://blogs.windows.com/buildingapps/2015/10/13/create-more-secure-apps-with-less-effort-10-by-10/#bWSeoR0pMyW2H8fg.97

like image 31
SurenSaluka Avatar answered Oct 12 '22 07:10

SurenSaluka