Public Key Pinning

PKP (HTTP)

[70] PKP (Public Key Pinning) は、 HTTPS サーバー証明書指紋ピンとして利用者エージェントが記憶しておき、 以後のアクセス時にサーバー証明書と比較することで、 MITM 攻撃を検出しようと試みるものです。

[71] PKPHTTPヘッダーとして Public-Key-Pins:Public-Key-Pins-Report-Only: を使います。

仕様書

呼称

[8] Public-Key-Pins ヘッダーPublic-Key-Pins-Report-Only ヘッダーは、それぞれ PKPPKP-RO と省略されます >>5

意味

[69] PKP は、 HTTPS サーバーへの初回接続時の証明書の情報を利用者エージェントが記憶しておくことにより、 以後のアクセスでの MITM 攻撃を検出することを可能とするものです。 初回接続時の MITM は防げませんし、初回接続時に MITM 攻撃者が PKP を注入する危険性もあるとはいえ、まずまず有用であろうと思われています。 >>50

[9] PKP ヘッダーPKP-RO ヘッダーは、サーバー利用者エージェントに対して当該ホストについて Pin Validation を行うべきことを示し、そのために必要な情報を提供するものです >>5

[17] PKPPKP-RO はそれぞれ別個に処理されるものです >>5

構文

[7] PKPPKP-RO は、どちらも指令の1つ以上の列を値としなければなりません指令間は ; で区切ります。 ; の前後には OWS を挿入できます。 >>5

  1. 指令
  2. *
    1. OWS
    2. ;
    3. OWS
    4. 指令

[10] 指令は、名前と値で構成されますが、値は省略できます。 値が存在する場合は、間に = を置きます。 >>5

[11] 指令の名前は字句です。大文字・小文字不区別です。 >>5

[12] 指令の値は字句または引用文字列です。 >>5

[23] 両構文の意味の違いや用法の制限があるのかどうかは不透明です。 pin-* の構文では引用文字列であることが要求されており、 max-age の規定ではどちらも等価である旨の規定があります。
  1. 字句
  2. ?
    1. =
    2. |
      1. 字句
      2. 引用文字列

[13] 指令の順序は意味を持ちません >>5

[19] pin-* を除き、同名の指令が複数現れてはなりません >>5

[65] pin-* は、同名の指令が複数現れることができます。 (HTTP指令としては珍しいパターンです。)

指令について >>20

文脈

[15] サーバーが指定できます >>5

[25] Pinned Host は、保安輸送路上の HTTP要求に対する応答では、 PKP ヘッダーをちょうど1つか、 PKP-RO ヘッダーをちょうど1つか、 その両方を含めるべきです >>5

[26] Pinned Host は、非保安輸送路上の HTTP要求に対する応答PKP ヘッダーを含めるべきではありません >>5

処理

[21] PKP 応答ヘッダーは、次の条件をすべて満たす時は、 妥当なピン付けヘッダー (Valid Pinning Header) です >>5

[30] 利用者エージェントは、応答を次のように処理しなければなりません

  1. [27]保安輸送路上なら、停止します >>5
  2. [33] 保安輸送路のエラーや警告があれば、停止します >>5
  3. [31] 応答PKP ヘッダーがあれば、その最初のものを次の通り処理します >>5
    1. [14] 構文的に正しければ >>5
      1. [32] 構文解析して指令のリストを得ます。
      2. [16] 認識できない指令を除去します >>5
      3. [29] 妥当なピン付けヘッダーなら >>5
        1. [38] max-age に 0 が指定されているなら、
          1. [39] Pinning Policy があれば、削除します >>5
        2. [40] それ以外で、当該ホスト既知ピン付きホストでなければ、
          1. [36] 既知ピン付きホストのキャッシュに本ホストを追加します。 >>5
        3. [35] それ以外なら、
          1. [37] 既知ピン付きホストの情報を (必要なら) 更新します。 >>5
  4. [41] 応答PKP-RO ヘッダーがあれば、その最初のものを次の通り処理するべきです >>5
    1. [45] 構文的に正しければ >>5
      1. [42] 構文解析して指令のリストを得ます。
      2. [43] 認識できない指令を除去します >>5
      3. [44] report-uri がなければ、無視して次へ進んで構いません >>5
        1. [47] max-age 以外の指令を使って、 ピン検証と報告の処理 (>>54) を行うべきです >>5

[55] 利用者エージェントは、 ピン付きホストへの TLS接続の場合、 TLS接続にエラーがあれば、接続を終端させなければなりません >>5

[56] 利用者エージェントは、 既知ピン付きホストへの接続の場合、 可能な限り早い段階で (例えばサーバー証明書の受信直後に)、 ピン検証と報告の処理 (>>54) を行うべきです >>5TLSセッションの設定時で HTTP の開始前にピン検証と報告の処理 (>>54) を行わなければなりません >>5

[46] WebSocket にも適用するべきかどうかは明記されていません。
[49] 既知ピン付きホストかどうかの判定については、 既知ピン付きホストの項を参照。

[54] ピン検証と報告の処理は、次のようにして行います。

  1. [57] 利用者の設定により、特定ホストピン検証を無効化できても構いません >>5。その場合、ここで停止します。
  2. [67] ピン検証 (>>58) を行います。
  3. [68] 失敗した場合、 report-uri が指定されていれば、報告を送るべきです >>5

[58] ピン検証 (Pin Validation) は、 次のようにしなければなりません >>5

  1. [59] サーバーから受信した各証明書について、
    1. [60] 証明書鎖の一部となっていない余分な証明書なら、無視して次の証明書へ進みます。
    2. [61] 対応する各ハッシュアルゴリズムにより、
      1. [66] SPKI Fingerprint を計算します。 (計算できない場合もあります。)
  2. [62] 計算して得られたピン群と与えられたピン群を比較し、一致するものがあるか調べます。
  3. [63] 一致するものがあれば、通過です。
  4. [64] 一致するものがなければ、回復できないエラーとします。

[72] 実際には、 証明書が公的なもの (OSWebブラウザー (の開発者) が信用するルート証明書にたどりつくもの) なら仕様通りピン検証を行い、 私的なもの (組織の管理者が MITM proxy 目的でインストールしたものなど) ならピン検証を実行しない実装になっているようです (>>48)。

[34] 報告の送信については、report-uri を参照。

[81] PKP による証明書の検査は、代替サービス利用時も行わなければなりません >>80

指令

[20] 次の指令があります。

セキュリティー

[51] PKPfingerprinting vector です。

[52] スーパークッキーとして使われ得るため、 HSTS 共々注意が必要です >>50

ポート

[76] ポートは指定・参照されませんから、 PKP はすべてのポートに共通で適用されることになります。

利用例

[86] PKP ヘッダーのあるサイトの例

歴史

[1] draft-ietf-websec-key-pinning-11 - Public Key Pinning Extension for HTTP ( ( 版)) http://tools.ietf.org/html/draft-ietf-websec-key-pinning-11

[2] draft-ietf-websec-key-pinning-15 - Public Key Pinning Extension for HTTP ( ( 版)) http://tools.ietf.org/html/draft-ietf-websec-key-pinning-15

[3] Re: CSP: Problems with referrer and reflected-xss ( (Chris Palmer 著, 版)) http://lists.w3.org/Archives/Public/public-webappsec/2014Jun/0177.html

[4] draft-ietf-websec-key-pinning-20 - Public Key Pinning Extension for HTTP ( ( 版)) https://tools.ietf.org/html/draft-ietf-websec-key-pinning-20

関連

[6] HSTS との併用が想定されていますが、単独でも使えます >>5

[18] SecurityEngineering/Public Key Pinning/Implementation Details - MozillaWiki ( 版) https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinning/Implementation_Details

[48] Security FAQ - The Chromium Projects ( 版) http://www.chromium.org/Home/chromium-security/security-faq#TOC-How-does-key-pinning-interact-with-local-proxies-and-filters-

Chrome’s key pinning feature is a strong form of web site authentication that requires a web server’s certificate chain not only to be valid and to chain to a known-good trust anchor, but also that at least one of the public keys in the certificate chain is known to be valid for the particular site the user is visiting. This is a good defense against the risk that any trust anchor can authenticate any web site, even if not intended by the site owner: if an otherwise-valid chain does not include a known pinned key (“pin”), Chrome will reject it because it was not issued in accordance with the site operator’s expectations.

Chrome does not perform pin validation when the certificate chain chains up to a private trust anchor. A key result of this policy is that private trust anchors can be used to proxy (or MITM) connections, even to pinned sites. “Data loss prevention” appliances, firewalls, content filters, and malware can use this feature to defeat the protections of key pinning.

We deem this acceptable because the proxy or MITM can only be effective if the client machine has already been configured to trust the proxy’s issuing certificate — that is, the client is already under the control of the person who controls the proxy (e.g. the enterprise’s IT administrator). If the client does not trust the private trust anchor, the proxy’s attempt to mediate the connection will fail as it should.

[75] Public Key Pinning - Web security | MDN ( 版) https://developer.mozilla.org/ja/docs/Web/Security/Public_Key_Pinning

[77] 不正なSSL証明書を見破るPublic Key Pinningを試す - ぼちぼち日記 ( 版) http://d.hatena.ne.jp/jovi0608/20140902/1409635279

[78] 不正なSSL証明書を見破るPublic Key Pinningを試す - ぼちぼち日記 ( 版) http://d.hatena.ne.jp/jovi0608/20140902/1409635279

4.7 Pre-loaded/HPKPの併用

仕様では実装依存になっていますが、 Chrome は HPKPを先にチェックするようになっています。

[79] GitHub ( 版) https://github.com/

Public-Key-Pins:max-age=5184000; pin-sha256="WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; pin-sha256="RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho="; pin-sha256="k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; pin-sha256="K87oWBWM9UZfyddvDfoxL+8lpNyoUB2ptGtn0fv6G2Q="; pin-sha256="IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4="; pin-sha256="iie1VXtL7HzAMF+/PVPR9xzT80kQxdZeJ+zduCB3uj0="; pin-sha256="LvRiGEjRqfzurezaWuj8Wie2gyHMrW5Q06LspMnox7A="; includeSubDomains

[82] gecko-dev/NSSCertDBTrustDomain.cpp at master · mozilla/gecko-dev ( ()) https://github.com/mozilla/gecko-dev/blob/master/security/certverifier/NSSCertDBTrustDomain.cpp

// If mHostname isn't set, we're not verifying in the context of a TLS

// handshake, so don't verify HPKP in those cases.

[83] RFC 7858 - Specification for DNS over Transport Layer Security (TLS) ( ()) https://tools.ietf.org/html/rfc7858#appendix-A

A DNS client system is configured with an out-of-band key-pinned

privacy profile from a network service, using a pin set containing

two pins. Represented in HTTP Public Key Pinning (HPKP) [RFC7469]

style, the pins are:

[84] Issue 445821 - chromium - crypto.cat certificate pinning update required - Monorail ( ()) https://bugs.chromium.org/p/chromium/issues/detail?id=445821

[85] Issue 446240 - chromium - Remove pinning for cryptocat - Monorail ( ()) https://bugs.chromium.org/p/chromium/issues/detail?id=446240

[89] gecko-dev/StaticHPKPins.h at master · mozilla/gecko-dev () https://github.com/mozilla/gecko-dev/blob/master/security/manager/ssl/StaticHPKPins.h

[90] Deprecations and removals in Chrome 67  |  Web  |  Google Developers () https://developers.google.com/web/updates/2018/04/chrome-67-deps-rems

It has very low adoption, and although it provides security against certificate mis-issuance, it also creates risks of denial of service and hostile pinning.

To defend against certificate misissuance, web developers should use the Expect-CT header, including its reporting function. Expect-CT is safer than HPKP due to the flexibility it gives site operators to recover from configuration errors, and due to the built-in support offered by a number of certificate authorities.

We expect to remove this in Chrome 69.

[91] Intent To Deprecate And Remove: Public Key Pinning - Google グループ () https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/he9tr7p3rZ8

[92] 自堕落な技術者の日記 : HPKP(HTTP Public Key Pinning)公開鍵ピニングについて考える - livedoor Blog(ブログ) () http://blog.livedoor.jp/k_urushima/archives/1811745.html

[93] net/http/transport_security_state_static.json - chromium/src - Git at Google () https://chromium.googlesource.com/chromium/src/+/master/net/http/transport_security_state_static.json

[94] GNU Wget 1.20 Manual () https://www.gnu.org/software/wget/manual/wget.html#index-SSL-Public-Key-Pin

[95] curl - How To Use (, ) https://curl.haxx.se/docs/manpage.html#--pinnedpubkey