Difference between revisions of "Pinning Cheat Sheet"

From OWASP
Jump to: navigation, search
(19 intermediate revisions by one user not shown)
Line 1: Line 1:
 
The [[Pinning Cheat Sheet]] is a technical guide to implementing certificate and public key pinning as discussed at the Virginia chapter's presentation [[Media:Securing-Wireless-Channels-in-the-Mobile-Space.ppt|Securing Wireless Channels in the Mobile Space]]. This guide is focused on providing clear, simple, actionable guidance for securing the channel in a hostile environment where actors could be malicious and the conference of trust a liability.
 
The [[Pinning Cheat Sheet]] is a technical guide to implementing certificate and public key pinning as discussed at the Virginia chapter's presentation [[Media:Securing-Wireless-Channels-in-the-Mobile-Space.ppt|Securing Wireless Channels in the Mobile Space]]. This guide is focused on providing clear, simple, actionable guidance for securing the channel in a hostile environment where actors could be malicious and the conference of trust a liability.
  
A verbose article is available at [[Certificate_and_Public_Key_Pinning|Certificate and Public Key Pinning]]. The article includes additional topics, Ephemeral Keys and Alternatives to Pinning.
+
A verbose article is available at [[Certificate_and_Public_Key_Pinning|Certificate and Public Key Pinning]]. The article includes additional topics, such as Alternatives to Pinning, Ephemeral Keys, Pinning Gaps, Revocation, and X509 Validation.
  
 
== What's the problem? ==
 
== What's the problem? ==
Line 9: Line 9:
 
== What Is Pinning? ==
 
== What Is Pinning? ==
  
In essence, pinning is the process of verifying a host's identity based on their ''expected'' X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is 'pinned' to the host. Put another way, its a whitelist of known certificates or public keys for a host, server, or service.  If more than one certificate or public key is acceptable, then the program holds a ''pinset'' for a host, server, or service. In this case, the peer's advertised identity must match one of the elements in the pinset.
+
Pinning is the process of associating a host with their ''expected'' X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a ''pinset'' (taking from [https://developers.google.com/events/io/sessions/gooio2012/107/ Jon Larimer and Kenny Root Google I/O talk]). In this case, the advertised identity must match one of the elements in the pinset.
  
 
A host or service's certificate or public key can be added to an application at development time, or it can be added upon first encountering the certificate or public key. The former - adding at development time - is preferred since ''preloading'' the certificate or public key ''out of band'' usually means the attacker cannot taint the pin.
 
A host or service's certificate or public key can be added to an application at development time, or it can be added upon first encountering the certificate or public key. The former - adding at development time - is preferred since ''preloading'' the certificate or public key ''out of band'' usually means the attacker cannot taint the pin.
  
== How Do You Pin? ==
+
=== When Do You Pin? ===
  
From 10,000 feet, the idea is to re-use the exiting protocols and infrastructure, but use them in a hardened manner. The 'pin' is the hardening.
+
You should pin anytime you want to be relatively certain of the remote host's identity or when operating in a hostile environment. Since one or both are almost always true, you should probably pin all the time.
  
For re-use, a program would keep doing the things it used to do when establishing a secure connection. To harden the channel, the program would would take advantage of the <tt>OnConnect</tt> callback offered by a library, framework or platform. In the callback, the program would verify the remote host's identity by validating its certificate or public key.
+
=== When Do You Whitelist? ===
  
While pinning does not have to occur in an <tt>OnConnect</tt> callback, its often most convenient because the underlying connection information is readily available.
+
If you are working for an organization which practices "egress filtering" as part of a Data Loss Prevention (DLP) strategy, you will likely encounter ''Interception Proxies''. I like to refer to these things as '''"good" bad guys''' (as opposed to '''"bad" bad guys''') since both break end-to-end security and we can't tell them apart. In this case, '''do not''' offer to whitelist the interception proxy since it defeats your security goals. Add the interception proxy's public key to your pinset after being '''instructed''' to do so by the folks in Risk Acceptance.
  
== When Do You Pin? ==
+
=== How Do You Pin? ===
  
You should pin anytime you want to be relatively certain of the remote host's identity or when operating in a hostile environment. Since one or both are almost always true, you should probably pin all the time.
+
The idea is to re-use the exiting protocols and infrastructure, but use them in a hardened manner. For re-use, a program would keep doing the things it used to do when establishing a secure connection.
  
== When Do You Whitelist? ==
+
To harden the channel, the program would would take advantage of the <tt>OnConnect</tt> callback offered by a library, framework or platform. In the callback, the program would verify the remote host's identity by validating its certificate or public key.
 
+
If you are working for an organization which practices "egress filtering" as part of a Data Loss Prevention (DLP) strategy, you will likely encounter ''Interception Proxies''. I like to refer to these things as '''"good" bad guys''' (as opposed to '''"bad" bad guys''') since both break end-to-end security and we can't tell them apart. In this case, '''do not''' offer to whitelist the interception proxy since it defeats your security goals. Add the interception proxy's public key to your pinset after being '''instructed''' to do so by the folks in Risk Acceptance.
+
  
 
== What Should Be Pinned? ==
 
== What Should Be Pinned? ==
Line 33: Line 31:
 
The first thing to decide is what should be pinned. For this choice, you have two options: you can (1) pin  the certificate; or (2) pin the public key. If you choose public keys, you have two additional choices: (a) pin the <tt>subjectPublicKeyInfo</tt>; or (b) pin one of the concrete types such as <tt>RSAPublicKey</tt> or <tt>DSAPublicKey</tt>.
 
The first thing to decide is what should be pinned. For this choice, you have two options: you can (1) pin  the certificate; or (2) pin the public key. If you choose public keys, you have two additional choices: (a) pin the <tt>subjectPublicKeyInfo</tt>; or (b) pin one of the concrete types such as <tt>RSAPublicKey</tt> or <tt>DSAPublicKey</tt>.
  
[[File:random-org-der-dump.png|thumb| 100px |subjectPublicKeyInfo]]The three choices are explained below in more detail. I would encourage you to pin the <tt>subjectPublicKeyInfo</tt> because it has the public parameters (such as <tt>{e,n}</tt> for an RSA public key) '''and''' contextual information such as an algorithm and OID. The context will help you keep your bearings at times, and Figure 1 below shows the additional information available.
+
[[File:random-org-der-dump.png|thumb| 100px |subjectPublicKeyInfo]]The three choices are explained below in more detail. I would encourage you to pin the <tt>subjectPublicKeyInfo</tt> because it has the public parameters (such as <tt>{e,n}</tt> for an RSA public key) '''and''' contextual information such as an algorithm and OID. The context will help you keep your bearings at times, and the figure to the right shows the additional information available.
  
 
=== Certificate ===
 
=== Certificate ===
  
[[File:pin-cert.png|thumb|right|100px|Certificate]] The certificate is easiest to pin. You can fetch the certificate out of band for the website, have the IT folks email your company certificate to you, use <tt>openssl s_client</tt> to retrieve the certificate etc. When the certificate expires, you would update your application. Assuming your application has no bugs or security defects, the application would be updated every year or two.
+
[[File:pin-cert.png|thumb|right|100px|Certificate]] The certificate is easiest to pin. You can fetch the certificate out of band for the website, have the IT folks email your company certificate to you, use <tt>openssl s_client</tt> to retrieve the certificate etc. At runtime, you retrieve the website or server's certificate in the callback. Within the callback, you compare the retrieved certificate with the certificate embedded within the program. If the comparison fails, then fail the method or function.  
 
+
At runtime, you retrieve the website or server's certificate in the callback. Within the callback, you compare the retrieved certificate with the certificate embedded within the program. If the comparison fails, then fail the method or function.  
+
  
 
There is a downside to pinning a certificate. If the site rotates its certificate on a regular basis, then your application would need to be updated regularly. For example, Google rotates its certificates, so you will need to update your application about once a month (if it depended on Google services). Even though Google rotates its certificates, the underlying public keys (within the certificate) remain static.
 
There is a downside to pinning a certificate. If the site rotates its certificate on a regular basis, then your application would need to be updated regularly. For example, Google rotates its certificates, so you will need to update your application about once a month (if it depended on Google services). Even though Google rotates its certificates, the underlying public keys (within the certificate) remain static.
Line 51: Line 47:
 
=== Hashing ===
 
=== Hashing ===
  
While the three choices above specifically callout the use of DER encoding, its also acceptable to use a hash of the information. In fact, the original sample programs were written using digested certificates and public keys. The samples were changed to allow a programmer to inspect the objects with tools like <tt>dumpasn1</tt> and other ASN.1 decoders.
+
While the three choices above used DER encoding, its also acceptable to use a hash of the information. In fact, the original sample programs were written using digested certificates and public keys. The samples were changed to allow a programmer to inspect the objects with tools like <tt>dumpasn1</tt> and other ASN.1 decoders.
  
 
Hashing also provides three additional benefits. First, hashing allows you to anonymize a certificate or public key. This might be important if you application is concerned about leaking information during decompilation and re-engineering. Second, a digested certificate fingerprint is often available as a native API for many libraries, so its convenient to use.
 
Hashing also provides three additional benefits. First, hashing allows you to anonymize a certificate or public key. This might be important if you application is concerned about leaking information during decompilation and re-engineering. Second, a digested certificate fingerprint is often available as a native API for many libraries, so its convenient to use.
  
Finally, an organization might want to supply a 'future' public key identity in case the primary identity is compromised. Hashing ensures your adversaries do not see the 'future' certificate or key in advance of its use. In fact, Google's IETF draft websec-key-pinning uses the technique.
+
Finally, an organization might want to supply a reserve (or back-up) identity in case the primary identity is compromised. Hashing ensures your adversaries do not see the reserved certificate or public key in advance of its use. In fact, Google's IETF draft ''websec-key-pinning'' uses the technique.
  
 
== Examples of Pinning ==
 
== Examples of Pinning ==
  
This section discusses certificate and public key pinning in Android Java, iOS, .Net, and OpenSSL. Code has been omitted for brevity, but the key points for the platform are highlighted.
+
This section discusses certificate and public key pinning in Android Java, iOS, .Net, and OpenSSL. Code has been omitted for brevity, but the key points for the platform are highlighted. All programs attempt to connect to [https://www.random.org random.org] and fetch bytes (Dr. Mads Haahr participates in AOSP's pinning program, so the site should have a static key). The programs enjoy a pre-existing relationship with the site (more correctly, ''a priori'' knowledge), so they include a copy of the site's public key and pin the identity on the key.
 
+
All programs attempt to connect to [https://www.random.org random.org] and fetch bytes (Dr. Mads Haahr participates in AOSP's pinning program, so the site should have a static key). Parameter validation, return value checking, and error checking have been omitted in the code below, but is present in the sample programs. So the sample code is ready for copy/paste. By far, the most uncomfortable languages are C-based: iOS and OpenSSL.
+
  
 
=== Android ===
 
=== Android ===
  
Pinning in Android is accomplished through a custom <tt>X509TrustManager</tt>. Be sure to call the base class to ensure customary checks are performed (thanks Nikolay Elenkov).
+
Pinning in Android is accomplished through a custom <tt>X509TrustManager</tt>. <tt>X509TrustManager</tt> should perform the customary X509 checks in addition to performing the pin.
  
 
Download: [[Media:pubkey-pin-android.zip|Android sample program]]
 
Download: [[Media:pubkey-pin-android.zip|Android sample program]]
Line 71: Line 65:
 
=== iOS ===
 
=== iOS ===
  
iOS pinning is performed through a <tt>NSURLConnectionDelegate</tt>. The delegate must implement <tt>connection:canAuthenticateAgainstProtectionSpace:</tt> and <tt>connection:didReceiveAuthenticationChallenge:</tt>.
+
iOS pinning is performed through a <tt>NSURLConnectionDelegate</tt>. The delegate must implement <tt>connection:canAuthenticateAgainstProtectionSpace:</tt> and <tt>connection:didReceiveAuthenticationChallenge:</tt>. Within <tt>connection:didReceiveAuthenticationChallenge:</tt>, the delegate must call <tt>SecTrustEvaluate</tt> to perform customary X509 checks.
  
 
Download: [[Media:pubkey-pin-ios.zip|iOS sample program]].
 
Download: [[Media:pubkey-pin-ios.zip|iOS sample program]].
Line 83: Line 77:
 
=== OpenSSL ===
 
=== OpenSSL ===
  
Pinning in OpenSSL is a lot of work, but the library offers the most control. Pinning can occur at one of two places. First is the OpenSSL <tt>SSL</tt> object pointer through use of the <tt>verify_callback</tt>. Second is after the connection is established via <tt> SSL_get_peer_certificate</tt>.
+
Pinning can occur at one of two places with OpenSSL. First is the user supplied <tt>verify_callback</tt>. Second is after the connection is established via <tt>SSL_get_peer_certificate</tt>. Either method will allow you to access the peer's certificate.
 +
 
 +
Though OpenSSL performs the X509 checks, you must fail the connection and tear down the socket on error. By design, a server that does not supply a certificate will result in <tt>X509_V_OK</tt> with a '''NULL''' certificate. To check the result of the customary verification: (1) you must call <tt>SSL_get_verify_result</tt> and verify the return code is <tt>X509_V_OK</tt>; and (2) you must call <tt>SSL_get_peer_certificate</tt> and verify the certificate is '''non-NULL'''.
  
 
Download: [[Media:pubkey-pin-openssl.zip|OpenSSL sample program]].
 
Download: [[Media:pubkey-pin-openssl.zip|OpenSSL sample program]].
Line 93: Line 89:
 
* OWASP [[Data_Validation|Data Validation]]
 
* OWASP [[Data_Validation|Data Validation]]
 
* OWASP [[Transport_Layer_Protection_Cheat_Sheet|Transport Layer Protection Cheat Sheet]]
 
* OWASP [[Transport_Layer_Protection_Cheat_Sheet|Transport Layer Protection Cheat Sheet]]
* IETF [https://tools.ietf.org/html/rfc1421 RFC 1421 (PEM Encoding)]
+
* IETF [http://www.ietf.org/rfc/rfc1421.txt RFC 1421 (PEM Encoding)]
* IETF [https://tools.ietf.org/html/rfc4648 RFC 4648 (Base16, Base32, and Base64 Encodings)]
+
* IETF [http://www.ietf.org/rfc/rfc4648.txt RFC 4648 (Base16, Base32, and Base64 Encodings)]
 +
* IETF [http://www.ietf.org/rfc/rfc5280.txt RFC 5280 (Internet X.509, PKIX)]
 
* IETF [http://www.ietf.org/rfc/rfc3279.txt RFC 3279 (PKI, X509 Algorithms and CRL Profiles)]
 
* IETF [http://www.ietf.org/rfc/rfc3279.txt RFC 3279 (PKI, X509 Algorithms and CRL Profiles)]
 
* IETF [http://www.ietf.org/rfc/rfc4055.txt RFC 4055 (PKI, X509 Additional Algorithms and CRL Profiles)]
 
* IETF [http://www.ietf.org/rfc/rfc4055.txt RFC 4055 (PKI, X509 Additional Algorithms and CRL Profiles)]
Line 103: Line 100:
 
* RSA Laboratories [http://www.rsa.com/rsalabs/node.asp?id=2128 PKCS#6, Extended-Certificate Syntax Standard]
 
* RSA Laboratories [http://www.rsa.com/rsalabs/node.asp?id=2128 PKCS#6, Extended-Certificate Syntax Standard]
  
= Authors and Editors  =
+
== Authors and Editors  ==
  
 
* Jeffrey Walton - jeffrey, owasp.org
 
* Jeffrey Walton - jeffrey, owasp.org

Revision as of 13:02, 19 February 2013

The Pinning Cheat Sheet is a technical guide to implementing certificate and public key pinning as discussed at the Virginia chapter's presentation Securing Wireless Channels in the Mobile Space. This guide is focused on providing clear, simple, actionable guidance for securing the channel in a hostile environment where actors could be malicious and the conference of trust a liability.

A verbose article is available at Certificate and Public Key Pinning. The article includes additional topics, such as Alternatives to Pinning, Ephemeral Keys, Pinning Gaps, Revocation, and X509 Validation.

Contents

What's the problem?

Users, developers, and applications expect end-to-end security on their secure channels, but some secure channels are not meeting the expectation. Specifically, channels built using well known protocols such as VPN, SSL, and TLS can be vulnerable to a number of attacks.

What Is Pinning?

Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a pinset (taking from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised identity must match one of the elements in the pinset.

A host or service's certificate or public key can be added to an application at development time, or it can be added upon first encountering the certificate or public key. The former - adding at development time - is preferred since preloading the certificate or public key out of band usually means the attacker cannot taint the pin.

When Do You Pin?

You should pin anytime you want to be relatively certain of the remote host's identity or when operating in a hostile environment. Since one or both are almost always true, you should probably pin all the time.

When Do You Whitelist?

If you are working for an organization which practices "egress filtering" as part of a Data Loss Prevention (DLP) strategy, you will likely encounter Interception Proxies. I like to refer to these things as "good" bad guys (as opposed to "bad" bad guys) since both break end-to-end security and we can't tell them apart. In this case, do not offer to whitelist the interception proxy since it defeats your security goals. Add the interception proxy's public key to your pinset after being instructed to do so by the folks in Risk Acceptance.

How Do You Pin?

The idea is to re-use the exiting protocols and infrastructure, but use them in a hardened manner. For re-use, a program would keep doing the things it used to do when establishing a secure connection.

To harden the channel, the program would would take advantage of the OnConnect callback offered by a library, framework or platform. In the callback, the program would verify the remote host's identity by validating its certificate or public key.

What Should Be Pinned?

The first thing to decide is what should be pinned. For this choice, you have two options: you can (1) pin the certificate; or (2) pin the public key. If you choose public keys, you have two additional choices: (a) pin the subjectPublicKeyInfo; or (b) pin one of the concrete types such as RSAPublicKey or DSAPublicKey.

subjectPublicKeyInfo
The three choices are explained below in more detail. I would encourage you to pin the subjectPublicKeyInfo because it has the public parameters (such as {e,n} for an RSA public key) and contextual information such as an algorithm and OID. The context will help you keep your bearings at times, and the figure to the right shows the additional information available.

Certificate

Certificate
The certificate is easiest to pin. You can fetch the certificate out of band for the website, have the IT folks email your company certificate to you, use openssl s_client to retrieve the certificate etc. At runtime, you retrieve the website or server's certificate in the callback. Within the callback, you compare the retrieved certificate with the certificate embedded within the program. If the comparison fails, then fail the method or function.

There is a downside to pinning a certificate. If the site rotates its certificate on a regular basis, then your application would need to be updated regularly. For example, Google rotates its certificates, so you will need to update your application about once a month (if it depended on Google services). Even though Google rotates its certificates, the underlying public keys (within the certificate) remain static.

Public Key

Public Key
Public key pinning is more flexible but a little trickier due to the extra steps necessary to extract the public key from a certificate. As with a certificate, the program checks the extracted public key with its embedded copy of the public key.

There are two downsides two public key pinning. First, its harder to work with keys (versus certificates) since you must extract the key from the certificate. Extraction is a minor inconvenience in Java and .Net, buts its uncomfortable in Cocoa/CocoaTouch and OpenSSL. Second, the key is static and may violate key rotation policies.

Hashing

While the three choices above used DER encoding, its also acceptable to use a hash of the information. In fact, the original sample programs were written using digested certificates and public keys. The samples were changed to allow a programmer to inspect the objects with tools like dumpasn1 and other ASN.1 decoders.

Hashing also provides three additional benefits. First, hashing allows you to anonymize a certificate or public key. This might be important if you application is concerned about leaking information during decompilation and re-engineering. Second, a digested certificate fingerprint is often available as a native API for many libraries, so its convenient to use.

Finally, an organization might want to supply a reserve (or back-up) identity in case the primary identity is compromised. Hashing ensures your adversaries do not see the reserved certificate or public key in advance of its use. In fact, Google's IETF draft websec-key-pinning uses the technique.

Examples of Pinning

This section discusses certificate and public key pinning in Android Java, iOS, .Net, and OpenSSL. Code has been omitted for brevity, but the key points for the platform are highlighted. All programs attempt to connect to random.org and fetch bytes (Dr. Mads Haahr participates in AOSP's pinning program, so the site should have a static key). The programs enjoy a pre-existing relationship with the site (more correctly, a priori knowledge), so they include a copy of the site's public key and pin the identity on the key.

Android

Pinning in Android is accomplished through a custom X509TrustManager. X509TrustManager should perform the customary X509 checks in addition to performing the pin.

Download: Android sample program

iOS

iOS pinning is performed through a NSURLConnectionDelegate. The delegate must implement connection:canAuthenticateAgainstProtectionSpace: and connection:didReceiveAuthenticationChallenge:. Within connection:didReceiveAuthenticationChallenge:, the delegate must call SecTrustEvaluate to perform customary X509 checks.

Download: iOS sample program.

.Net

.Net pinning can be achieved by using ServicePointManager.

Download: .Net sample program.

OpenSSL

Pinning can occur at one of two places with OpenSSL. First is the user supplied verify_callback. Second is after the connection is established via SSL_get_peer_certificate. Either method will allow you to access the peer's certificate.

Though OpenSSL performs the X509 checks, you must fail the connection and tear down the socket on error. By design, a server that does not supply a certificate will result in X509_V_OK with a NULL certificate. To check the result of the customary verification: (1) you must call SSL_get_verify_result and verify the return code is X509_V_OK; and (2) you must call SSL_get_peer_certificate and verify the certificate is non-NULL.

Download: OpenSSL sample program.


References

Authors and Editors

  • Jeffrey Walton - jeffrey, owasp.org
  • JohnSteven - john, owasp.org
  • Jim Manico - jim, owasp.org
  • Kevin Wall - kevin, owasp.org

Other Cheat sheets

OWASP Cheat Sheets Project Homepage

Developer Cheat Sheets (Builder)

Assessment Cheat Sheets (Breaker)

Mobile Cheat Sheets

OpSec Cheat Sheets (Defender)

Draft Cheat Sheets