-
FiddlerCertGen, a certificate generator for Fiddler
Eric Lawrence wrote a pretty interesting post on how Fiddler intercepts HTTPS traffic. Essentially, it generates a root x509 certificate and asks the user to trust it, then generates end-entity certificates on-the-fly for each domain visited with the root as the signer. One bit caught my interest especially:
If you’re so inclined, you can even write your own certificate generator (say, by wrapping OpenSSL) and expose it to Fiddler using the
ICertificateProvider3
interface.In my ever expanding interest in writing extensions for Fiddler, I decided this would be something fun to try, especially because I’ve written such code in the past. It should have been easy to just take that code and fit it to the interface.
The result of that is a GitHub project called FiddlerCertGen. It provides a few advantages over the built in ones that Fiddler provides.
For Windows Vista (and Server 2008) and later, it uses Microsoft’s CNG API (Cryptographic Next Generation) instead of CAPI. CNG offers some benefits, such as being able to use elliptic curve cryptography. In fact, for Vista+, the project will use ECDSA 256-bit keys. The key generation here is slightly faster than that of RSAs, so it may offer a slight bump in performance from Fiddler having to generate RSA keys. For Windows XP and Windows Server 2003, it will fall back to RSA 2048.
It’s fairly easy to change this, if you want. The static constructor for for the
FiddlerCertificate
class initializes the configuration:_algorithm = PlatformSupport.HasCngSupport ? Algorithm.ECDSA256 : Algorithm.RSA; _keyProviderEngine = PlatformSupport.HasCngSupport ? KeyProviders.CNG : KeyProviders.CAPI; _signatureAlgorithm = HashAlgorithm.SHA256;
You can use RSA keys with CNG – in fact if you are on Windows Vista or greater I’d recommend using CNG no-matter-what. What you cannot do is use ECDSA with CAPI. The signature algorithm is set to SHA256 by default, however if for whatever reason you need to test something on Windows XP pre-service pack 2, then you can set it to SHA1; or you can set it to SHA384.
The only compatibility thing to keep in mind is that some browsers do not support end-entity certificates that are ECC 384 keys. Root / intermediates are fine, but end-entities of this key length don’t work. A particular one with that behavior is Safari (both desktop and mobile).
The extension is broken down into two projects, a core .NET 2.0 project that does the bulk of the certificate generation, and a .NET 4.0 one that implements the Fiddler interface. If you are using Fiddler 2, you should be able to change the Framework Target for the .NET 4.0 one to 2.0 and it will work fine. Just remove the Fiddler reference and add the one for the .NET 2.0 Fiddler.
The GitHub repository’s README contains installation instructions.
-
Examining the details of public key pinning
I’ve been working on adding some features around HTTP Public Key Pinning to my FiddlerCert Fiddler extension.
Specifically, I added indicators next to each certificate if it was pinned by either the
Public-Key-Pins
orPublic-Key-Pins-Report-Only
header as well as display the SPKI hash.While implementing this, I learned quite a bit about what a pinned key is.
So, what is a pinned key? They are called a public key pin, but the pin is more than a hash of just the public key. You could for example, look at the public key of my domain:
04 35 D7 8F 8C 16 18 9D 1E 95 95 67 1C 39 D8 83 B3 32 1C 89 BA A3 56 78 8D C2 43 DB 20 4F 1D FA 80 93 6B 23 AF 1C 5A 59 F9 1B 74 A7 6F 62 38 97 A9 1B 29 2A 0F DA 40 B0 6F F9 6A 98 CE 45 48 48 2C
However if we were to take these bytes and hash them, it would not produce the same hash that OpenSSL does when following the recommended guidelines for producing a Public-Key-Pin hash.
The hash needs to include a little more information. For example, hashing just the public key doesn’t include certain other components, like what algorithm the key is, such as RSA or ECDSA. Other relevant information should be included as well, such as the public key exponent for RSA, or the identifier of the elliptic curve for ECDSA, or algorithm parameters.
Why do we need these extra values? Adam Langley has the details on his blog:
Also, we’re hashing the SubjectPublicKeyInfo not the public key bit string. The SPKI includes the type of the public key and some parameters along with the public key itself. This is important because just hashing the public key leaves one open to misinterpretation attacks. Consider a Diffie-Hellman public key: if one only hashes the public key, not the full SPKI, then an attacker can use the same public key but make the client interpret it in a different group. Likewise one could force an RSA key to be interpreted as a DSA key etc.
One tricky thing with hashing is that the data format must always be consistent. Since a hash operates on pure data and knows nothing about the structure of the data, the structure must be consistent and platform independent. Should the public key exponent be included before or after the public key? What endianness is the data? How is the data consistently represented?
For all of the grief it gives people, that’s what ASN.1 encoding is exactly for. What actually ends up getting hashed is a SubjectPublicKeyInfo (SPKI) portion of the X509 certificate. This includes all of the data that we need. In OpenSSL, it’s this part:
Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:35:d7:8f:8c:16:18:9d:1e:95:95:67:1c:39:d8: 83:b3:32:1c:89:ba:a3:56:78:8d:c2:43:db:20:4f: 1d:fa:80:93:6b:23:af:1c:5a:59:f9:1b:74:a7:6f: 62:38:97:a9:1b:29:2a:0f:da:40:b0:6f:f9:6a:98: ce:45:48:48:2c ASN1 OID: prime256v1 NIST CURVE: P-256
In ASN.1 form, it looks like this.
30 59 30 13 06 07 2a 86 48 ce 3d 02 01 06 08 2a 86 48 ce 3d 03 01 07 03 42 00 04 35 d7 8f 8c 16 18 9d 1e 95 95 67 1c 39 d8 83 b3 32 1c 89 ba a3 56 78 8d c2 43 db 20 4f 1d fa 80 93 6b 23 af 1c 5a 59 f9 1b 74 a7 6f 62 38 97 a9 1b 29 2a 0f da 40 b0 6f f9 6a 98 ce 45 48 48 2c
The green portion should look familiar, it’s the public key. The rest of the bytes are part of the ASN.1 encoding.
ASN.1 Primer
ASN.1 is simple in concept, but difficult to write code for in a secure manner. ASN.1 consists of tags. Each tag consists of three things: the type of the tag (tag identifier), the length of the tag’s value, and the value of the tag. Tags can consist of other tags. Take this example:
06 07 2a 86 48 ce 3d 02 01
This is an OBJECT_IDENTIFIER. 0x06 is the identifier for an OBJECT_IDENTIFIER. The next value is 7. The rest of the tag is the value, 2a 86 48 ce 3d 02 01 and we see that it is exactly 7 bytes long, just as the length value said it was. The data in an OBJECT_IDENTIFIER is a variable-length-quantity. This particular OBJECT_IDENTIFIER’s value is an OID of 1.2.840.10045.2.1, which is the OID for an ECC Public Key, or as we saw from OpenSSL’s output,
id-ecPublicKey
.0x30, as the data starts with, is the tag identifier for a SEQUENCE. A SEQUENCE is a collection of other tags. The length value of a sequence is not the number of items in the sequence, but rather the total byte length of it’s contents. The only way to get the number of items in a sequence is to examine each of the tags in it and parse them out.
How the data in the ASN.1 data is stored is defined by the encoding rules. It can be DER, which is what is used with X509, or BER.
Breaking down the ASN.1 data, it looks like this:
SEQUENCE SEQUENCE OBJECT_IDENTIFIER 1.2.840.10045.2.1 OBJECT_IDENTIFIER 1.2.840.10045.3.1.7 BIT STRING 000435D78F8C16189D1E9595671C39D883B3321C89BAA356788DC243DB204F1DFA80936B23AF1C5A59F91B74A76F623897A91B292A0FDA40B06FF96A98CE4548482C
This is for an ECC public key. For an RSA public key, it would not have two OBJECT_IDENTIFIERs, but rather also include the public exponent.
FiddlerCert needed to do this, but backwards. Given a public key blob and the parameters, convert it to ASN.1 data so it can be hashed. It was tempting to try assembling the data myself, but I quickly realized this was very error prone. Instead, I settled on using the
CryptEncodeObject
Win32 function with platform invoke. This made it much simpler. All I had to do was construct aCERT_PUBLIC_KEY_INFO
structure that had all of the values and it happily produced the ASN.1 data that was needed.The implementation details of this are on GitHub in the CertificateHashBuilder class.
-
A certificate inspector for Fiddler
Fiddler is an awesome web development tool developed by Eric Lawrence. It’s one of my “must haves” as a web developer and security researcher. If you haven’t used it, I would recommend you take a look at it. It’s a bit difficult to summarize what it does since it does so much, but it’s a tool inspecting, modifying, and replaying HTTP traffic.
I’ve been tinkering with an extension called FiddlerCert that reveals greater information about the certificates of an HTTPS enabled site. You can go get it on GitHub right now under vcsjones/FiddlerCert. The README contains installation and building instructions.
FiddlerCert is designed to make it easy to do common tasks with certificates such as viewing common properties, installing it, and saving it to disk.
If you run into any issues or have feature requests, please let me know on GitHub.
-
CloudFront and ECC
I for fun decided to switch to my ECC certificate for a bit at this risk of breaking HPKP for visitors.
I did this one, to test and make sure that I didn’t screw up pinning the new certificate – I would have seen HPKP violations myself if I did. I also did it to test something I hadn’t considered at first: CDNs.
Originally this website was set up to serve static content via Amazon’s CloudFront where my own server (vcsjones.dev) was an Origin for the distribution. CloudFront does support communicating with origins over HTTPS, but sadly they don’t support ECDSA cipher suites. According to their documentation, they actually have a pretty limited cipher suite support and top out at TLS 1.0. Their documentation also doesn’t agree with the behavior that I see, they seem to be missing the GCM suites that they claim to support when I actually examined an Client Hello from the distribution.
For now I’ve turned off CDN on my site while I consider my options – the most ikely being, “The CDN is not absolutely necessary”. I’ve raised the issue with Amazon and we’ll see if they do anything about it soon.
-
Disabling WiFi Sense on WiFi in Windows 10
There has been a lot of hullabaloo over Window 10’s WiFi Sense capability. If you aren’t familiar with it, here is ArsTechnica’s definition by Sebastian Anthony:
Windows 10 comes with a neat new feature called Wi-Fi Sense, which lets your PC automatically connect to Wi-Fi networks that your friends and acquaintances have previously connected to, even if you don’t know the network password. — Sebastian Anthony, ArsTechnica
I recommend you read Ars’s write up, it’s a fair and practical argument for why it should be left alone, and that it isn’t such a big deal. Indeed, many people make good arguments to why its a reasonable thing and people shouldn’t be freaking out about it. People have also told me that devices on a network using WiFi Sense can’t access devices on the network, just the default gateway for internet access.
There is only one suitable option for completely disabling it for an entire network: suffix your SSID with “_optout”:
If you run a Wi-Fi network and you want to prevent Windows 10 (or Windows Phone) users from sharing the passkey via Wi-Fi Sense, you can add _optout to the end of the network SSID. — Sebastian Anthony, ArsTechnica
Given all of the arguments as to why it’s a good thing, that it’s secure and all, I am still going to add the _optout to my network.
This isn’t any dig at Microsoft. Microsoft has some really, really smart people there especially security conscience ones. If it were Apple or Google, I would do the same (and I have for other services).
It’s something I just don’t need. Any practical security minded person would tell you, “If you don’t need something, turn it off”. Windows Server has been doing this for years with Roles and Features. One of the primary reasons Windows Server doesn’t come with everything enabled out of the box is so that only features which are actually installed need to be patched. This is one of the reasons I think Windows Nano is fantastic, and is summed up well in this tweet about what Jeff Snover said during MSIgnite:
@nanoserver One 10th the critical patches, dramatically increased security. VHD size 410Mbytes, almost 20 times smaller @jsnover #MSIgnite - @JeffreySchwartz
My point is this: if you won’t use it, turn it off. People can think of really creative vulnerabilities. There are still many concerns that I do have.
Devices that are on a WiFi network via WiFi Sense don’t get access to the whole network, just the default gateway (router in most cases) for internet access, and that is all. So even if WiFi Sense were misused, no one would get access to devices on my network, right? I don’t think so. Consumer router manufactures do a laughable job at security. Who knows what else will turn up. Even if you keep your router patched, there are probably dozens more left to be discovered.
Small businesses are in a bit of a tight spot, too. Most don’t deploy WPA2 Enterprise, they just use their ISPs router with built-in WiFi, or maybe they have a few APs they got from Best Buy, added a WPA2 PSK password, and moved on. How does a small business stop employees from doing this? I’m sure Group Policy can do it (which many small business also don’t deploy), but since WiFi Sense is on Windows Phone, and with BYOD on the rise (both with phones and laptops), it’s only a matter of time before someone uses the company’s WiFi with WiFi Sense.
Even more concerning is this is becoming a convention. Google famously collects information about WiFi SSIDs its streetcars sees. If you don’t want them doing it, you follow a similar approach: add “_nomap” to the end of your SSID. Are these at odds with one another? Probably. I don’t think I can have “_optout_nomap” – one defeats the other, which is disappointing.