Skip to content

Pinning Cheat Sheet / 固定证书备忘录

Introduction / 介绍

The Pinning Cheat Sheet is a technical guide to implementing certificate and public key pinning as discussed by Jeffrey Walton 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.

《固定证书备忘录》是一份技术指南,用于实施证书和公钥固定,由Jeffrey Walton在弗吉尼亚分会场演讲中讨论(在移动空间中保护无线通道)。本指南旨在提供清晰、简单、可操作的建议,以保护在敌对环境中可能存在恶意行为者且信任会议可能成为负担的通道。

What's the problem / 问题是什么

For baseline TLS configuration, see the Transport Layer Security Cheat Sheet.

有关基线TLS配置,请参阅传输层安全性备忘录。

Users, developers, and applications expect security on their communication channels, but some channels may not meet this expectation. Channels built using well known protocols like SSL, and TLS can be vulnerable to Man-in-the-Middle (MITM) attacks if certificate-based trusts are misused. Malicious attacks come in two forms:

用户、开发者和应用程序期望他们的通信通道具有安全性,但某些通道可能无法满足这一期望。使用如SSL和TLS等知名协议构建的通道可能会受到中间人(MITM)攻击,如果基于证书的信任被滥用。恶意攻击有两种形式:

  1. An attacker is able to acquire a rogue digital certificate from a trusted certificate authority (CA) in the name of the victim site;
    中文:攻击者能够从受信任的证书颁发机构(CA)以受害网站的名义获取一个恶意数字证书;
  2. The attacker is able to inject a dangerous CA into the client’s trust store.
    中文:攻击者能够向客户端的信任存储中注入一个危险的CA。

In the case of the latter issue, an attacker with the access to update a trust store will have the access to change the workings of the mobile application, potentially defeating pinning.

在后一种情况下,如果攻击者有权更新信任存储,他们将有权更改移动应用程序的工作方式,这可能会破坏固定机制。

As Certificate and Public Key Pinning makes clear, this problem is very small due to years of security advancements by the certificate authority and browser communities.

正如证书和公钥固定所明确指出的,由于证书机构和浏览器社区多年的安全进步,这个问题非常小。

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 (taken from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised credential must match one of the elements in the pinset.

固定是将主机与其预期的X509证书或公钥关联的过程。一旦主机已知或看到了证书或公钥,该证书或公钥就会被关联或'固定'到主机上。如果可以接受多个证书或公钥,则程序会保留一个固定集(来自Jon Larimer和Kenny Root的Google I/O演讲)。在这种情况下,广告凭证必须与固定集中的某个元素匹配。

When to Add a Pin / 何时添加固定

A host or service's certificate or public key can be added to an application at development time, it can be added upon first encountering the certificate or public key (an approach commonly known as “Trust On First Use”, or TOFU), or it can be added and updated in real time via an unpinned channel. 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.

主机或服务的证书或公钥可以在开发时添加到应用程序中,也可以在首次遇到证书或公钥时添加(通常称为“首次使用即信任”,或TOFU),或者可以通过未固定的通道实时添加和更新。前者——在开发时添加——是首选的,因为离线预加载证书或公钥通常意味着攻击者无法污染固定。

Keep in mind that this "when" is about at what point in time you pin. The first question should be, “Should I Pin?”. The answer to this is probably never.

请注意,这里的“何时”是指你何时进行固定。首先应该问的问题是,“我应该固定吗?”对这个问题的回答可能是永远不应该。

When Do You Perform Pinning / 何时执行固定

There is almost no situation where you should consider pinning. The risk of outages almost always outweighs any security risks given advances in security. If you consider pinning, you should read Certificate and Public Key Pinning and fully understand the threat model.

几乎没有任何情况你应该考虑固定。由于安全方面的进步,停机风险几乎总是超过任何安全风险。如果你考虑固定,你应该阅读证书和公钥固定并完全理解威胁模型。

When Do You Not Pin? / 何时不进行固定?

  • If you don’t control the client and server side of the connection, don’t pin.
    中文:如果你无法控制连接的客户端和服务器端,不要进行固定。
  • If you can’t update the pinset securely, don’t pin.
    中文:如果你无法安全地更新固定集,不要进行固定。
  • If updating the pinset is disruptive, such as requiring application redeployment, probably don’t pin. (A possible exception is when you control the redeployment of the application, such as in forced updates within the confines of a corporation.)
    中文:如果更新固定集会带来破坏,例如需要重新部署应用程序,可能不要进行固定。(一个可能的例外是你控制应用程序的重新部署,例如在公司范围内的强制更新。)
  • If the certificate key pair cannot be predicted in advance before it is put into service, don’t pin.
    中文:如果在投入使用之前无法预测证书密钥对,不要进行固定。
  • If it is not a native mobile application, do not pin.
    中文:如果不是原生移动应用程序,不要进行固定。

When to Apply Exceptions / 何时应用例外

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. We like to refer to these things as "good" bad actors (as opposed to "bad" bad actors) since both break end-to-end security and we can't tell them apart. In this case, do not offer to allow-list 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.

如果你在为一家将“出口过滤”作为数据丢失预防(DLP)策略一部分的组织工作,你可能会遇到拦截代理。我们喜欢将这些称为“好”坏演员(与“坏”坏演员相对),因为它们都破坏了端到端安全,我们无法区分它们。在这种情况下,不要提供允许列表拦截代理,因为这会破坏你的安全目标。在风险接受团队指示后,将拦截代理的公钥添加到你的固定集中。

How Do You Pin / 如何固定

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

想法是重用现有的协议和基础设施,但以加固的方式使用。为了重用,程序会在建立安全连接时继续执行它以前做的事情。

To harden the channel, the program 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. See some examples below.

为了加固通道,程序会利用库、框架或平台提供的 OnConnect 回调。在回调中,程序将通过验证其证书或公钥来验证远程主机的身份。下面是一些示例。

What Should Be Pinned / 应该固定什么

In order to decide what should be pinned you can follow the following steps.

为了决定应该固定什么,你可以遵循以下步骤。

  1. Decide if you want to pin the root CA, intermediate CA or leaf certificate:
    中文:决定是否要固定根CA、中间CA或叶证书:
  • Pinning the root CA is generally not recommended since it highly increases the risk because it implies also trusting all its intermediate CAs.
    中文:固定根CA通常不推荐,因为它极大地增加了风险,因为它意味着也信任所有其中间CA。
  • Pinning a specific issuing or intermediate CA reduces the risk but the application will be also trusting any other certificates issued by that CA or sub-CAs, not only the ones meant for your application.
    中文:固定特定的签发或中间CA可以降低风险,但应用程序也将信任该CA或子CA签发的任何证书,而不仅仅是针对你的应用程序的证书。
  • Pinning a leaf certificate is recommended but must include backup (e.g. intermediate CA or a pinset containing alternates). This provides 100% certainty that the app exclusively trusts the remote hosts it was designed to connect to while adding resiliency for failover or certificate rotation.
    中文:推荐固定叶证书,但必须包括备份(例如中间CA或包含替代方案的固定集)。这提供了100%的确定性,即应用仅信任其设计连接的远程主机,同时增加了故障转移或证书轮换的弹性。

For example, the application pins the remote endpoint leaf certificate but includes a backup pin for the intermediate CA. This increases the risk by trusting more certificate authorities but decreases the chances of bricking your app. If there's any issue with the leaf certificate, the app can always fall back to the intermediate CA until you release an app update.

例如,应用程序固定了远程端点的叶证书,但包括中间CA的备份固定。这通过信任更多的证书颁发机构增加了风险,但减少了使您的应用无法使用的可能性。如果叶证书有任何问题,应用始终可以回退到中间CA,直到您发布应用更新。

  1. Choose if you want to pin the whole certificate or just its public key.
    中文:选择您是想固定整个证书还是仅固定其公钥。

  2. If you chose the public key, you have two additional choices:
    中文:如果您选择公钥,您有两个额外的选择:

  • Pin the subjectPublicKeyInfo.
    中文:固定subjectPublicKeyInfo。
  • Pin one of the concrete types such as RSAPublicKey or DSAPublicKey.
    中文:固定具体类型之一,例如RSAPublicKey或DSAPublicKey。

The three choices are explained below in more detail. You are encouraged 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.

以下将更详细地解释这三种选择。我们鼓励您固定subjectPublicKeyInfo,因为它具有公共参数(例如RSA公钥的{e,n})以及上下文信息,如算法和OID。上下文将帮助您在某些时候保持方向,右边的图显示了可用的附加信息。

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 can retrieve the website or server's certificate in a 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, log it on the client-side and alert the end user. If your threat model warrants pinning, understand that users will click past any warnings, so do not give the user an option to proceed and bypass the pin.

证书最容易固定。您可以跨带从网站获取证书,让IT人员将您的公司证书通过电子邮件发送给您,使用openssl s_client检索证书等。在运行时,您可以在回调中检索网站或服务器的证书。在回调中,您将检索到的证书与程序中嵌入的证书进行比较。如果比较失败,则失败该方法或函数,记录在客户端并警告最终用户。如果您的威胁模型需要固定,了解用户会忽略任何警告,因此不要给用户一个继续并绕过固定的选项。

Benefits:

优点:

  • It might be easier to implement than the other methods, especially in languages such as Cocoa/CocoaTouch and OpenSSL.
    中文:这可能比其他方法更容易实现,尤其是在 Cocoa/CocoaTouch 和 OpenSSL 等语言中。

Downsides:

缺点:

  • If the site rotates its certificate on a regular basis, then your application would need to be updated regularly. If you do not control when this certificate is put into service, then pinning will lead to an outage.
    中文:如果网站定期轮换其证书,则您的应用程序需要定期更新。如果您无法控制何时将此证书投入使用,则固定可能导致中断。

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. Given that most certificates today are only good for 90 days, using public key pinning can also make the timeline for updating pinsets longer, as you can pin a key where the certificate has not even been issued yet.

公钥固定比证书固定更灵活,但由于需要额外的步骤从证书中提取公钥,所以稍微复杂一些。与证书一样,程序将提取的公钥与其嵌入的公钥副本进行比较。鉴于今天的大多数证书仅有效期为90天,使用公钥固定也可以使更新固定集的时间线更长,因为您可以在证书尚未颁发的情况下固定密钥。

Benefits:

优点:

  • It allows access to public key parameters (such as {e,n} for an RSA public key) and contextual information such as an algorithm and OID.
    中文:它允许访问公钥参数(例如RSA公钥的{e,n})和上下文信息,如算法和OID。
  • It's more flexible than certificate pinning. The pin can be calculated long before the certificate is issued and if policy allows, the certificate can be renewed with the same key to avoid breaking pinning. The latter is a bad key management practice and should only be used in an emergency.
    中文:它比证书固定更灵活。固定可以在证书颁发之前很久就计算出来,如果策略允许,可以使用相同的密钥续订证书以避免破坏固定。后者是一种不良的密钥管理实践,并且仅在紧急情况下使用。

Downsides:

缺点:

  • It can be 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, but it's uncomfortable in the iOS Cocoa/CocoaTouch framework and OpenSSL.
    中文:与证书(而非密钥)相比,处理密钥可能更困难,因为您必须从证书中提取密钥。在 Java 和 .Net 中提取是一个小麻烦,但在 iOS Cocoa/CocoaTouch 框架和 OpenSSL 中则不太舒适。
  • Some service providers generate new keys upon renewal making pre-caching impossible.
    中文:一些服务提供商在续订时生成新的密钥,这使得预缓存变得不可能。

Hash / 哈希

While the three choices above used DER encoding, it's 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.

虽然上述三个选项使用了DER编码,但使用信息的哈希也是可以接受的。事实上,原始的示例程序是使用摘要证书和公钥编写的。这些示例被修改,以便程序员可以使用dumpasn1和其他ASN.1解码器等工具检查对象。

Benefits:

优点:

  • It's convenient to use. A digested certificate fingerprint is often available as a native API for many libraries.
    中文:使用起来很方便。摘要证书指纹通常可以作为许多库的本地API获得。
  • The hash is small and a fixed length.
    中文:哈希值小且长度固定。

Downsides:

缺点:

  • No access to public key parameters nor contextual information such as an algorithm and OID which might be needed in certain use cases.
    中文:无法访问公钥参数以及可能在某些用例中需要的算法和OID等上下文信息。
  • If the site rotates its certificate on a regular basis, then your application would need to be updated regularly. If you do not control when this certificate is put into service, then pinning would lead to an outage.
    中文:如果网站定期轮换其证书,那么您的应用程序需要定期更新。如果您不控制何时将此证书投入使用,那么固定会导致服务中断。

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.

本节讨论了Android Java、iOS、.Net和OpenSSL中的证书和公钥固定。为了简洁,代码已被省略,但平台的关键点已突出显示。

Android

Since Android N, the preferred way for implementing pinning is by leveraging Android's Network Security Configuration feature, which lets apps customize their network security settings in a safe, declarative configuration file without modifying app code.

自Android N以来,实现固定的首选方法是利用Android的网络安全配置功能,该功能允许应用在安全的声明性配置文件中自定义其网络安全设置,而无需修改应用代码。

To enable pinning, the <pin-set> configuration setting can be used.

要启用固定,可以使用配置设置。

Alternatively you can use methods such as the pinning from OkHTTP in order to set specific pins programmatically, as explained in the OWASP Mobile Security Testing Guide (MSTG) and the OKHttp documentation.

或者,您可以使用OkHTTP的固定方法等,以编程方式设置特定的固定值,如OWASP移动安全测试指南(MSTG)和OKHttp文档中所述。

The Android documentation provides an example of how SSL validation can be customized within the app's code (in order to implement pinning) in the Unknown CA implementation document. However, implementing pinning validation from scratch should be avoided, as implementation mistakes are extremely likely and usually lead to severe vulnerabilities.

Android文档提供了一个示例,说明如何在应用代码中自定义SSL验证以实现固定(为了实现固定),请参阅未知CA实现文档。然而,应避免从头开始实现固定验证,因为实现错误的可能性极高,通常会导致严重漏洞。

Lastly, if you want to validate whether the pinning is successful, please follow instructions from the introduction into testing network communication and the Android specific network testing chapters of the OWASP Mobile Security Testing Guide (MSTG).

最后,如果您想验证固定是否成功,请遵循OWASP移动安全测试指南(MSTG)中测试网络通信简介和Android特定网络测试章节的说明。

iOS

Apple suggests pinning a CA public key by specifying it in Info.plist file under App Transport Security Settings. More details in the article "Identity Pinning: How to configure server certificates for your app".

Apple建议通过在App Transport Security设置下的Info.plist文件中指定它来固定CA公钥。更多详情请参阅文章"Identity Pinning: How to configure server certificates for your app"(https://developer.apple.com/news/?id=g9ejcf8y)。

TrustKit, an open-source SSL pinning library for iOS and macOS is available. It provides an easy-to-use API for implementing pinning, and has been deployed in many apps.

Otherwise, more details regarding how SSL validation can be customized on iOS (in order to implement pinning) are available in the HTTPS Server Trust Evaluation technical note. However, implementing pinning validation from scratch should be avoided, as implementation mistakes are extremely likely and usually lead to severe vulnerabilities.

否则,有关如何在iOS上自定义SSL验证(以实现固定)的更多详细信息可在HTTPS服务器信任评估技术说明中找到。然而,应避免从头开始实现固定验证,因为实现错误的可能性极高,通常会导致严重漏洞。

Lastly, if you want to validate whether the pinning is successful, please follow instructions from the introduction into testing network communication and the iOS specific network testing chapters of the OWASP Mobile Security Testing Guide (MSTG).

最后,如果您想验证固定是否成功,请遵循OWASP移动安全测试指南(MSTG)中测试网络通信简介和iOS特定网络测试章节的说明。

.Net

.Net pinning can be achieved by using ServicePointManager. An example can be found at the OWASP MSTG.

可以通过使用ServicePointManager实现.Net的固定。一个示例可以在OWASP MSTG中找到。

Download the .Net sample program.

下载.Net示例程序。

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.

固定可以发生在OpenSSL的两个位置之一。首先是用户提供的verify_callback。第二个是在通过SSL_get_peer_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:

尽管 OpenSSL 执行 X509 检查,但在出错时你必须拒绝连接并断开套接字。按照设计,未提供证书的服务器会导致 X509_V_OK 并带有 NULL 证书。为了检查常规验证的结果:

  1. You must call SSL_get_verify_result and verify the return code is X509_V_OK;
    中文:你必须调用 SSL_get_verify_result 并验证返回码是否为 X509_V_OK;
  2. You must call SSL_get_peer_certificate and verify the certificate is non-NULL.
    中文:你必须调用 SSL_get_peer_certificate 并验证证书是否 非 NULL。

Download: OpenSSL sample program.

下载:OpenSSL 示例程序。

Electron

electron-ssl-pinning, an open-source SSL pinning library for Electron based applications. It provides an easy-to-use API for implementing pinning and also provides a tool for fetching configuration based on needed hosts.

Otherwise, you can validate certificates by yourself using ses.setCertificateVerifyProc(proc).

否则,你可以使用 ses.setCertificateVerifyProc(proc) 自己验证证书。

References / 参考