Robert Love · Blog

Tuesday, January 20, 2015

Key pinning comprises the most practical hope for TLS security over the next few years, making targeted Certificate Authority-based attacks much riskier. While we wait for new systems built on top of key pinning, HTTP Public Key Pinning (HPKP) allows website operators to perform opportunistic key pinning, today.

Chain of Trust

Identity, not encryption, is the most important component of a cryptographic protocol: The best encryption in the world is worthless if you aren't speaking to whom you intend. SSL/TLS verifies identity through a chain of trust represented by a series of X.509 public key certificates. Your browser trusts a set of root certificates owned by Certificate Authorities; those Certificate Authoritess in turn extend their trust to the websites you visit. When you visit rlove.org, your browser verifies the certificate chain starting with rlove.org's own, moving down to the root certificate. If your browser ultimately trusts that root, you know you are talking to me and not an adversary.

A Giant Hole

A flaw in this system is that any compromised root certificate can in turn subvert the entire identity model. If I steal the Crap Authority's private key and your browser trusts their certificate, I can forge valid certificates for any website. In fact, I could execute this on a large scale, performing a man-in-the-middle (MITM) attack against every website that every user on my network visits. Indeed, this happens.

Nothing short of pre-shared keys are a perfect solution to such MITM attacks. This blog post, nonetheless, describes a technology that can significantly decrease the risk of MITM by allowing website operators to limit the certificates that can participate in their website's chain of trust and to detect in-progress attacks.

Public Key Pinning

HPKP is a draft IETF standard that implements a public key pinning mechanism via HTTP header, instructing browsers to require a whitelisted certificate for all subsequent connections to that website. This can greatly reduce the surface area for an MITM attack: Down from any root certificate to requiring a specific root, intermediate certificate, or even your exact public key.

The HTTP Header

The HPKP header looks like this:

Public-Key-Pins: pin-sha256="XXX"; pin-sha256="YYY"; max-age=ZZZ

where XXX is the base64-encode of the SHA256 hash of the public key to whitelist for this site; YYY is a backup of the same; and ZZZ is the time-to-live in seconds for the whitelist. The header may also provide the includeSubdomains directive, instructing browsers to apply the whitelist to all hosts on this domain, and the report-uri=X directive, which instructs browsers to report pin validation failures to X.

You may specify as many pin-sha256 directives as you wish. Only one fingerprint must be in your trust chain. Additionally, you must specify at least one fingerprint that is not included in your current chain. In other words, the standard forces you to have a backup pinned key.

What to Pin

The obvious and most secure public key to pin is your own. This will require fastidious management of your backup keys, however, and can be difficult if you rotate or revoke your certificates often. A simpler but less secure approach is pinning the first intermediate certificate in your trust chain i.e. one certificate up from your site's certificate. This will allow you to easily manage your own certificates while still greatly limiting the surface of any MITM attack.

Generating the SPKI Fingerprint

HPKP requires a base64-encode of a SHA256 hash of the public key you wise to pin. You can generate these easily given a public key, a certificate signing request (CSR), or a X.509 certificate. You only need one.

These commands will output a single string that looks something like this:

LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=

You'll drop that in a pin-sha256 directive. You can repeat this process for each key you wish to pin—for example, if you have two possible certificates for your site, you would pin both. As discussed above, you will also need a pin-sha256 directive with a backup key. Browsers enforce this by requiring one such directive to contain a fingerprint not in your current certificate chain.

Verification is nontrivial as the draft standard requires a successful key validation before storing a pinned fingerprint. Thus, you can't serve a gibberish fingerprint to verify pinning failure. Nor does successfully connecting to your website mean the pin is actually stored. The easiest way to verify success is via Chrome's network internals page at chrome://net-internals/#hsts. Under Query domain, enter your website, and verify that your keys' fingerprints are listed under dynamic_spki_hashes. Chrome will store them only if they successfully validated.

Reporting

The Public Key Pinning specification includes a reporting mechanism. Key validation failures are reported to the URI specified by the optional report-uri directive. This is useful not only for debugging your own use of Public Key Pinning but also for detecting MITM attacks against your users. In fact, the mere possibility of reporting makes Public Key Pinning a deterrent against MITM attacks.

Reporting is performed via an HTTP POST of the following JSON message:

There are several shortcomings to HPKP, although on balance I still recommend its use. The single largest flaw is that HPKP is a trust-on-first-use (TOFU) mechanism. A user will not be able to detect an MITM attack on their first connection to a site. To repeatedly MITM a user, however, an adversary would need to intercept all connections to the target website. Given the nature of today's threats, HPKP thus provides reasonable protection against attacks. Notably, a global adversary would need to know whether a target had an HPKP pinning stored in their browser before initiating an MITM attack, lest the target's browser aggressively warn of (and potentially report) the failure.

Sunday, April 13, 2014

Perhaps hard to tell given how many users remain, but Windows XP reached its end of life on 8 April 2014. This means no more support, updates, or bug fixes—not even of critical security flaws. Windows XP use has been dwindling, but its end-of-life provides an excellent opportunity to consider removing support for it from your applications and websites.

Dropping Windows XP support provides particularly interesting results for SSL/TLS configurations, as most of the compromises one makes in their provided cipher suites are in support of old versions of Internet Explorer on Windows XP. Since those users are now even more of a walking botnet and malware infestation, we needn't continue to support them to the detriment of the rest of the Internet.

And what changes can we make? In my previous cryptography guide, I advocate disabling SSLv3 support, which breaks Internet Explorer 6 on Windows XP, but prevents a downgrade attack for everyone else. If we're willing to drop support for all versions of Internet Explorer on Windows XP†, we can accomplish two other goals:

With this cipher suite ordering, Chrome and Firefox will both use TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256—a mighty fine choice—but even your least-favored cipher, TLS_DHE_RSA_WITH_AES_128_CBC_SHA provides forward security and a strong cipher.

For all your hard effort, this will earn you an "A+" grade and near-perfect SSL Labs Rating:

As before, you cannot do better without silly compromises, such as only supporting TLS 1.2, which would earn you a 100 in "Protocol Support," but then only Chrome and Firefox 27 could access your site.

† Which likely just means the addition of IE 7 and 8.

‡ Indeed, I'm not thrilled to recommend only one cipher. Even if AES were perfect, we ought to have choice. I believe ChaCha20+Poly1305 is an excellent alternative. It is currently supported by Chrome but is not yet in OpenSSL. Once in the latter I will update my recommendations.

Monday, December 2, 2013

I recently moved my homepage, Robert Love, from HTTP to HTTPS. My goal was to configure the server with strong cryptography while making less compromises for compatibility and against security than many of the "best practice" configurations others provide. I thought I'd share the result. Notably, I recommend a cipher suite ordering that enables Perfect Forward Secrecy (PFS) with AES-GCM, disables broken ciphers, neutralizes known attacks, and still works on nearly every browser. I provide configuration for both Apache and Nginx.

Many feel encryption is the raison d'être of HTTPS, but I argue that the verification of identity and prevention of man-in-the-middle attacks are more important. Consequently, given the sophistication of today's adversaries, I believe HTTPS is important even for situations such as static content where you may feel encryption is of minimal value. I hope this guide inspires more webmasters to put all of their content under HTTPS.

Your Server's Certificate

Let's start with your digital certificate, which is at the core of HTTPS. The certificate enables clients to verify the identity of servers, through a chain of trust from your server's certificate through intermediate certificates and up to a root certificate trusted by users' browsers. Your server certificate should be 2048 bits in length. I really ought be recommending a 4096-bit certificate, but the computation required (for both the client and server) is currently cost prohibitive. Consequently, 2048 bits is a necessary compromise.

For a certificate authority, I recommend DigiCert, but plenty of folks are happy with StartSSL, who offers free certificates for personal websites.

Basic HTTPS Setup

I don't intend to make this a general purpose "how to configure SSL" guide, as there are many of those around. But here are basic SSL configurations, first for Apache:

Make sure all of these files are at least mode 0444, except your private key, which should be 0400.

Cipher Suite Configuration

With the basic configuration covered, let's get to the meat: My recommended cipher suite configuration. Getting this right is difficult, as you need to consider myriad issues ranging from attacks such as BEAST to disabling compromised algorithms such as RC4 to supporting antiquated crap browsers. What follows is an aggressive, strong cryptography configuration.

For the key exchange, we prefer ephemeral key-exchange algorithms that provide PFS. We favor Elliptic Curve Diffie-Hellman (ECDHE) over the multiplicative version (DHE), as the former is less processor intense for a similar level of security, but we support both.

For identity, we only support RSA. That's fine, as your certificate is RSA (DSA certs are uncommon).

For message ciphers, we favor AES over everything else. For AES, we favor the GCM version over CBC, as GCM is more efficient and not susceptible to BEAST, and we favor AES-256 over AES-128.†

For message authentication, we favor SHA-2 with 256 or 384-bit digests.

We disable non-authenticated and non-encrypted suites, all of the legacy export-approved ciphers, Camellia, DES (but not 3DES), MD5, and pre-shared keys.

Controversially, we also disable RC4. This deserves a longer discussion.

Disabling RC4 isn't a common recommendation; even so-called "strong crypto" recommendations include it. Some recommendations even prioritize RC4, as it is not susceptible to BEAST. But RC4 has a growing list of attacks against it, many of which have crossed the line from theoretical to practical. Moreover, there is reason to believe that the NSA has broken RC4—their so-called "big breakthrough."

Disabling RC4 has several ramifications. One, users with shitty browsers such as Internet Explorer on Windows XP will use 3DES in lieu. Triple-DES is more secure than RC4, but it is significantly more expensive. Your server will pay the cost for these users. Two, RC4 mitigates BEAST. Thus, disabling RC4 makes TLS 1.0 users susceptible to that attack, by moving them to AES-CBC (the usual server-side BEAST "fix" is to prioritize RC4 above all else). I am confident that the flaws in RC4 significantly outweigh the risks from BEAST. Indeed, with client-side mitigation (which Chrome and Firefox both provide), BEAST is a nonissue. But the risk from RC4 only grows: More cryptanalysis will surface over time. It is time to retire its use.

Cipher Suites in the Real World

In practice, this cipher suite ordering will yield TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 under Firefox and Chrome.

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is pretty close to ideal, so let's use it as an example of how to read cipher suites: Protocol-Key exchange and identity-WITH-Cipher-Message authentication.

To prevent downgrade attacks, we will also disable old SSL protocols. Somewhat confusingly, folks use "SSL" as a synecdoche for HTTPS. In fact, SSL is one particular HTTPS protocol—one which is now considered horribly broken. SSL was superseded by TLS 1.0 in 1999; TLS 1.2 is the latest version. Everyone disables SSLv2, but we will also disable SSLv3, as TLS 1.0 suffers a downgrade attack, allowing an adversary to force a connection to use SSLv3 and thus disable PFS.

For Apache:

SSLProtocol all -SSLv2 -SSLv3

For Nginx:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

This disables all versions of SSL, enabling only TLS 1.0 and up. All versions of Chrome and Firefox support at least TLS 1.0. With this change you will break Internet Explorer 6 and earlier, who top out at SSLv3, but who cares about those assholes.

HTTPS Compression Considered Harmful

To mitigate the CRIME attack, you need to disable SSL/TLS compression. It is off by default in most versions of Nginx, but Apache only recently made that the default. Best be explicit:

SSLCompression Off

DHE Parameters

Apache prior to version 2.4.7 and all versions of Nginx as of 1.4.4 rely on OpenSSL for input parameters to Diffie-Hellman (DH). Unfortunately, this means that Ephemeral Diffie-Hellman (DHE) will use OpenSSL's defaults, which include a 1024-bit key for the key-exchange. Since we're using a 2048-bit certificate, DHE clients will use a weaker key-exchange than non-ephemeral DH clients.

For Apache, there is no fix except to upgrade to 2.4.7 or later. With that version, Apache automatically selects a stronger key. For Nginx, we can generate a stronger DHE parameter:

You should put these in every VirtualHost/server block for HTTPS versions of your website, so that HTTPS request will receive the HSTS header in the reply. If you do that, you should also canonicalize HTTP requests to HTTPS. For Apache:

It is a pain in the ass, but you likely need to compile some software: You need the latest version of your web server software and (even more important) OpenSSL to support all of the ciphers discussed here, as well as functionality such as TLS 1.2 and fixes for vulnerabilities such as Lucky13. As of this writing, the latest OpenSSL is 1.0.1g. You really want (at least) that version.

In this guide, I've provided configuration for both Apache and Nginx, but after almost two decades of using the former, I now recommend the latter.

The End Result

For all your hard effort, this will earn you an "A+" grade and near-perfect SSL Labs Rating:

You cannot do better without silly sacrifices—for example, supporting only TLS 1.2 would earn you a 100 in "Protocol Support," but then only Chrome and Firefox 27 could access your site.

This configuration offers up the strongest cryptography provided by today's browsers, including PFS via ECDHE with AES in GCM mode as your cipher. For lesser browsers, the fallback crypto remains plenty tough—any browser in the last decade will find a compatible cipher suite of decent quality. The configuration disables anything with suspected vulnerabilities, most notably RC4. Modern browsers will use AES in lieu; antiquated crap will use 3DES. Next, the configuration disables not only SSLv2 but also SSLv3, which means Internet Explorer 6 is SOL but so prevents a nasty downgrade attack. Finally, the config enables HSTS and HTTP-to-HTTPS redirects, ensuring all traffic remains secure.

† It is unfortunate there is only one cipher without issue, AES-GCM, available to HTTPS. Even if AES-GCM were perfect, we ought to have alternatives. I believe ChaCha20+Poly1305 is that alternative. ChaCha20+Poly1305 is now supported by Chrome. Once supported by OpenSSL, I'll update my recommended cipher suite. The ordering (AES-GCM over ChaCha20+Poly1305 or vice versa) isn't yet clear to me; ChaCha20 is likely to be much faster than AES without hardware acceleration. Chrome smartly adjusts the relative ordering of AES versus ChaCha20+Poly1305 based on the presence of hardware acceleration. Similar logic for Nginx is desirable.

Tuesday, November 19, 2013

I used to have a bunch of recipes up online. But writing recipes is no fun; it is difficult to capture the beauty of a dish with a bunch of steps. Moreover, using recipes isn't how I cook. I want to understand the flavors of a dish and then execute it in my own way, in my own hands. So the recipes went away.

But one of the most popular—and one of my personal favorites—was a recipe for the Mexican pork dish carnitas. It was a fun, relatively easy recipe, not traditional in approach but fairly traditional (and really delicious) in output. Folks keep asking for it. So here it is, in hopes I can eat it at your next house party.

Carnitas is a wonderful Mexican dish, pork shoulder cooked until tender and then given a great crisp. In Mexico, carnitas is eaten on its own, in tacos, or in tortas. The traditional recipe is simple: several pounds of pork shoulder, a pound or two of lard, orange peel, and some water (or coca-cola), slow roasted and then "boiled" to a crisp. That is…a bit much. What follows is not an authentic approach.

Never ones to eschew taste for health, the French have nonetheless taught us nothing if not that we can make a succulent, flavorful dish without boiling a tough cut of meat in lard. In that vein, my recipe is more of a braiser de porc than a confit de porc—pork shoulder, aromatics, citrus juice, and a little Grand Marnier, slow cooked on the stove. Healthier for the heart, but also—more importantly—tastier to the tongue. To obtain that classic carnitas crisp, we braise the meat uncovered until the liquid evaporates and then move the pot to the oven and caramelize.

Add the Grand Marnier, orange juice, and lime juice. Stir, scrapping the bottom of the pot.

Add chicken stock as needed such that the pork is two-thirds submerged in liquid.

Stirring, raise heat to high and bring to a boil. Once boiling, lower heat until the liquid is at a simmer and braise, uncovered, stirring occasionally, until the pork is cooked and tender but not disintegrating and the liquid is reduced by at least two-thirds, about three hours. If the liquid gets perilously-low while cooking, add a little chicken stock.

Remove pork from pot. Once cool enough to handle, use a fork to shred the pork into bite-sized, but fairly large, chunks, removing any fatty pieces as desired.

Preheat oven to 450°F.

Return pork chunks to pot. Place uncovered pot in oven. Continue cooking until the liquid has evaporated and the pork is crispy and starting to caramelize, about 20 minutes.

Tuesday, May 21, 2013

I'm pleased to announce the release of the second edition of Linux System Programming, my guide to system programming on Linux.

I updated the entire book to reflect new interfaces and behavior in the latest versions of the Linux kernel, glibc, and gcc—3.9, 2.17, and 4.8, respectively—as well as giving the text a universal overhaul with even more examples and interesting anecdotes.

What I am most excited about, however, is an all-new chapter on threading. I cover the basics of Pthreads, of course, but the meat of the chapter is a discussion on threading design and patterns in Linux. Should you use event-driven or thread-per-connection as your threading model? How do Linux's threading solutions scale? What are the costs of and alternatives to threading? How can you mitigate the risk of races? And other such fun topics.

Wednesday, April 25, 2012

By now you've likely heard the proposal that the University of Florida plans to drastically restructure its Computer Science department, CISE.

While the details are not as provocative a picture as the Forbes article paints, the proposal is still bad for the university and its students (read the actual proposal). Also, as an alumnus, the proposal is, frankly, embarrassing.

At a time when the United States needs more STEM graduates than ever, universities ought be doubling down on their Computer Science programs. I encourage you to write to the university. Even if unaffiliated with Florida, this restructuring sets a bad precedent for other institutions.

Today, I sent this email:

President Machen & Dean Abernathy,

I am writing to express my concern with the proposed changes to CISE. Contra more provocative coverage, I understand that the department is to undergo restructure and not outright elimination. I also understand the significant budgetary pressures facing Florida. Nonetheless, the proposed changes to CISE are wrong for the university and wrong for its students. Moreover, they set an ill precedent for other institutions at a time when the world needs not fewer, but more, CS graduates.

The proposed restructuring will irremediably harm the ability of Florida to attract top-caliber CS instructors, researchers, and students. The elimination of graduate and research programs will result in the loss of existing top faculty and place current students, who enrolled in graduate programs in good faith, in an unfortunate and precarious situation.

I am an engineer at Google and sit on a Hiring Committee, responsible for hiring decisions across my office. I am also an engineering manager. While we look for smart, driven individuals of varied and many backgrounds, this proposal will assuredly hurt Florida graduates beginning their careers. Universities with strong software--that is, CS--curricula and deep research programs matriculate students best equipped to excel in today's technology companies--or start the companies of tomorrow.

When the largest, most successful companies in the world are software companies clamoring for more and better engineers, Florida should increase, not decrease, its investment in Computer Science.

I understand these budget cuts were imposed upon you. I wish they were not. Important decisions are rarely easy, but you must revert this proposal.

Engineering Dean Abernathy has agreed to set aside the previously announced proposal as the department chairmen of CISE and ECE continue to flesh out details of a new proposal in consultation with students, faculty, staff, alumni and industry partners. The college has no plans to close any departments.

The budgetary issues facing our states and public universities are not over. Nor do I believe that the threat to Florida's CISE department is past. Nonetheless, this is an important victory, a crucial step worthy of celebration.