-
Notifications
You must be signed in to change notification settings - Fork 4
/
777.txt
317 lines (241 loc) · 16.2 KB
/
777.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
[70] [DFN[[[PKP]]]] ([DFN[[[Public Key Pinning]]]]) は、 [[HTTPS]]
[[サーバー証明書]]の[[指紋]]を[[ピン]]として[[利用者エージェント]]が記憶しておき、
以後のアクセス時に[[サーバー証明書]]と比較することで、
[[MITM]] 攻撃を検出しようと試みるものです。
[71] [[PKP]] は [[HTTPヘッダー]]として
[DFN[[CODE(HTTP)@en[[[Public-Key-Pins:]]]]]] と
[DFN[[CODE(HTTP)@en[[[Public-Key-Pins-Report-Only:]]]]]]
を使います。
* 仕様書
[REFS[
- [5] '''[CITE@en[RFC 7469 - Public Key Pinning Extension for HTTP]] ([TIME[2015-05-05 21:00:37 +09:00]] 版) <https://tools.ietf.org/html/rfc7469>'''
-- [53] [CITE@en[RFC 7469 - Public Key Pinning Extension for HTTP]] ([TIME[2015-05-05 21:00:37 +09:00]] 版) <https://tools.ietf.org/html/rfc7469#section-1>
-- [50] [CITE@en[RFC 7469 - Public Key Pinning Extension for HTTP]] ([TIME[2015-05-05 21:00:37 +09:00]] 版) <https://tools.ietf.org/html/rfc7469#section-5>
- [80] [CITE@en[RFC 7838 - HTTP Alternative Services]] ([TIME[2016-04-17 23:25:39 +09:00]] 版) <https://tools.ietf.org/html/rfc7838#section-9.2>
]REFS]
* 呼称
[8] [CODE(HTTP)@en[[[Public-Key-Pins]]]] [[ヘッダー]]と
[CODE(HTTP)@en[[[Public-Key-Pins-Report-Only]]]] [[ヘッダー]]は、それぞれ
[DFN[[[PKP]]]]、[DFN[[[PKP-RO]]]] と省略されます [SRC[>>5]]。
* 意味
[69] [[PKP]] は、 [[HTTPS]] サーバーへの初回接続時の[[証明書]]の情報を[[利用者エージェント]]が記憶しておくことにより、
以後のアクセスでの [[MITM]] 攻撃を検出することを可能とするものです。
初回接続時の [[MITM]] は防げませんし、初回接続時に [[MITM]] 攻撃者が [[PKP]]
を注入する危険性もあるとはいえ、まずまず有用であろうと思われています。 [SRC[>>50]]
[9] [[PKP]] [[ヘッダー]]と [[PKP-RO]] [[ヘッダー]]は、[[サーバー]]が[[利用者エージェント]]に対して当該[[ホスト]]について
[[Pin Validation]] を行うべきことを示し、そのために必要な情報を提供するものです [SRC[>>5]]。
[17] [[PKP]] と [[PKP-RO]] はそれぞれ別個に処理されるものです [SRC[>>5]]。
* 構文
[7] [[PKP]] と [[PKP-RO]] は、どちらも[[指令]]の1つ[[以上]]の列を値としなければ[['''なりません''']]。
[[指令]]間は [CODE(HTTP)[[[;]]]] で区切ります。 [CODE(HTTP)[[[;]]]]
の前後には [[OWS]] を挿入できます。 [SRC[>>5]]
[FIG(railroad)[
= [[指令]]
= *
== [[OWS]]
== [CODE(HTTP)[[[;]]]]
== [[OWS]]
== [[指令]]
]FIG]
[10] [[指令]]は、名前と値で構成されますが、値は省略できます。
値が存在する場合は、間に [CODE(HTTP)[[[=]]]] を置きます。 [SRC[>>5]]
[11] [[指令]]の名前は[[字句]]です。[[大文字・小文字不区別]]です。 [SRC[>>5]]
[12] [[指令]]の値は[[字句]]または[[引用文字列]]です。 [SRC[>>5]]
;; [23] 両構文の意味の違いや用法の制限があるのかどうかは不透明です。
[CODE(HTTP)@en[[[pin-*]]]] の構文では[[引用文字列]]であることが要求されており、
[CODE(HTTP)@en[[[max-age]]]] の規定ではどちらも等価である旨の規定があります。
[FIG(railroad)[
= [[字句]]
= ?
== [CODE(HTTP)[[[=]]]]
== |
=== [[字句]]
=== [[引用文字列]]
]FIG]
[13] [[指令]]の順序は意味を持ちません [SRC[>>5]]。
[19] [CODE[[[pin-*]]]] を除き、同名の[[指令]]が複数現れては[['''なりません''']] [SRC[>>5]]。
;; [65] [CODE[[[pin-*]]]] は、同名の[[指令]]が複数現れることができます。
([[HTTP]] の[[指令]]としては珍しいパターンです。)
* 文脈
[15] [[サーバー]]が指定できます [SRC[>>5]]。
[25] [[Pinned Host]] は、[[保安輸送路]]上の [[HTTP要求]]に対する[[応答]]では、
[[PKP]] [[ヘッダー]]をちょうど1つか、
[[PKP-RO]] [[ヘッダー]]をちょうど1つか、
その両方を含める[['''べきです''']] [SRC[>>5]]。
[26] [[Pinned Host]] は、非[[保安輸送路]]上の [[HTTP要求]]に対する[[応答]]で
[[PKP]] [[ヘッダー]]を含める[['''べきではありません''']] [SRC[>>5]]。
* 処理
[21] [[PKP]] [[応答ヘッダー]]は、次の条件をすべて満たす時は、
[DFN[[RUBYB[妥当なピン付けヘッダー]@en[Valid Pinning Header]]]]です [SRC[>>5]]。
[FIG(list)[
- [22] [[TLS接続]]でエラーがないこと。[[ピン付きホスト]]においては、
[[ピン検証]]も通過していること。
- [24] [[TLS接続]]の[[証明書鎖]]の [[SPKI]] のいずれかが指定された [[SPKI Fingerprint]]
の最低1つにより示されたものであること。
- [28] [[ピン]]のいずれか最低1つが、[[証明書鎖]]中の [[SPKI]] を表さないものであること
([[バックアップピン]]が含まれていること)。
]FIG]
[30] [[利用者エージェント]]は、[[応答]]を次のように処理しなければ[['''なりません''']]。
[FIG(steps)[
= [27] 非[[保安輸送路]]上なら、停止します [SRC[>>5]]。
= [33] [[保安輸送路]]のエラーや警告があれば、停止します [SRC[>>5]]。
= [31] [[応答]]に [[PKP]] [[ヘッダー]]があれば、その最初のものを次の通り処理します [SRC[>>5]]。
== [14] 構文的に正しければ [SRC[>>5]]、
=== [32] 構文解析して[[指令]]のリストを得ます。
=== [16] 認識できない[[指令]]を除去します [SRC[>>5]]。
=== [29] [[妥当なピン付けヘッダー]]なら [SRC[>>5]]、
==== [38] [CODE(HTTP)@en[[[max-age]]]] に 0 が指定されているなら、
===== [39] [[Pinning Policy]] があれば、削除します [SRC[>>5]]。
==== [40] それ以外で、当該[[ホスト]]が[[既知ピン付きホスト]]でなければ、
===== [36] [[既知ピン付きホスト]]のキャッシュに本ホストを追加します。 [SRC[>>5]]
==== [35] それ以外なら、
===== [37] [[既知ピン付きホスト]]の情報を (必要なら) 更新します。 [SRC[>>5]]
= [41] [[応答]]に [[PKP-RO]] [[ヘッダー]]があれば、その最初のものを次の通り処理する[['''べきです''']] [SRC[>>5]]。
== [45] 構文的に正しければ [SRC[>>5]]、
=== [42] 構文解析して[[指令]]のリストを得ます。
=== [43] 認識できない[[指令]]を除去します [SRC[>>5]]。
=== [44] [CODE(HTTP)@en[[[report-uri]]]] がなければ、無視して次へ進んで構いません [SRC[>>5]]。
==== [47] [CODE(HTTP)@en[[[max-age]]]] 以外の[[指令]]を使って、
[[ピン検証]]と報告の処理 (>>54) を行う[['''べき''']]です [SRC[>>5]]。
]FIG]
[55] [[利用者エージェント]]は、
[[ピン付きホスト]]への [[TLS接続]]の場合、
[[TLS接続]]にエラーがあれば、[[接続]]を終端させなければ[['''なりません''']] [SRC[>>5]]。
[56] [[利用者エージェント]]は、
[[既知ピン付きホスト]]への接続の場合、
可能な限り早い段階で (例えば[[サーバー証明書]]の受信直後に)、
[[ピン検証]]と報告の処理 (>>54) を行う[['''べき''']]です [SRC[>>5]]。
[[TLSセッション]]の設定時で [[HTTP]] の開始前に[[ピン検証]]と報告の処理
(>>54) を行わなければ[['''なりません''']] [SRC[>>5]]。
;; [46] [[WebSocket]] にも適用するべきかどうかは明記されていません。
;; [49] [[既知ピン付きホスト]]かどうかの判定については、
[[既知ピン付きホスト]]の項を参照。
[54] [[ピン検証]]と報告の処理は、次のようにして行います。
[FIG(steps)[
= [57] [[利用者]]の設定により、特定[[ホスト]]の[[ピン検証]]を無効化できても構いません
[SRC[>>5]]。その場合、ここで停止します。
= [67] [[ピン検証]] (>>58) を行います。
= [68] 失敗した場合、 [CODE(HTTP)@en[[[report-uri]]]]
が指定されていれば、報告を送る[['''べきです''']] [SRC[>>5]]。
]FIG]
[58] [DFN[[RUBYB[[[ピン検証]]]@en[Pin Validation]]]]は、
次のようにしなければ[['''なりません''']] [SRC[>>5]]。
[FIG(steps)[
= [59] [[サーバー]]から受信した各[[証明書]]について、
== [60] [[証明書鎖]]の一部となっていない余分な[[証明書]]なら、無視して次の[[証明書]]へ進みます。
== [61] 対応する各[[ハッシュアルゴリズム]]により、
=== [66] [[SPKI Fingerprint]] を計算します。 (計算できない場合もあります。)
= [62] 計算して得られた[[ピン]]群と与えられた[[ピン]]群を比較し、一致するものがあるか調べます。
= [63] 一致するものがあれば、通過です。
= [64] 一致するものがなければ、回復できないエラーとします。
]FIG]
[72] 実際には、
[[証明書]]が公的なもの ([[OS]] や [[Webブラウザー]] (の開発者) が信用する[[ルート証明書]]にたどりつくもの)
なら仕様通り[[ピン検証]]を行い、
私的なもの (組織の管理者が [[MITM proxy]] 目的でインストールしたものなど)
なら[[ピン検証]]を実行しない実装になっているようです (>>48)。
[34] 報告の送信については、[CODE[[[report-uri]]]] を参照。
[81] [[PKP]] による[[証明書]]の検査は、[[代替サービス]]利用時も行わなければ[MUST[なりません]]
[SRC[>>80]]。
* 指令
[20] 次の[[指令]]があります。
[FIG(short list)[
- [CODE(HTTP)@en[[[includeSubDomains]]]]
- [CODE(HTTP)@en[[[max-age]]]]
- [CODE(HTTP)@en[[[pin-sha256]]]]
- [CODE(HTTP)@en[[[report-uri]]]]
]FIG]
;; [74] [[指令]]の一覧は、 >>73 の [[JSON]] データファイルに含まれています。
[REFS[
- [73] [CITE@en[data-web-defs/headers.txt at master · manakai/data-web-defs]] ([TIME[2015-06-06 23:38:30 +09:00]] 版) <https://github.com/manakai/data-web-defs/blob/master/doc/headers.txt>
]REFS]
* セキュリティー
[51] [[PKP]] は [[fingerprinting vector]] です。
[52] [[スーパークッキー]]として使われ得るため、 [[HSTS]] 共々注意が必要です [SRC[>>50]]。
* ポート
[76] [[ポート]]は指定・参照されませんから、 [[PKP]] はすべての[[ポート]]に共通で適用されることになります。
* 利用例
[86] [[PKP]] ヘッダーのあるサイトの例
[REFS[
- [87] [CITE[suche.org : Welcome]] ([[Thomas Lußnig]] 著, [TIME[2016-05-31 00:04:22 +09:00]] 版) <https://suche.org/>
-- [88] [[Firefox]] では[[開発者コンソール]]にエラーが表示されます。
[[Chrome]] では何も表示されません。正常に動作しているのかは不明。 [TIME[2016-05-30T15:19:02.000Z]]
]REFS]
* 歴史
[1] [CITE@en[draft-ietf-websec-key-pinning-11 - Public Key Pinning Extension for HTTP]]
( ([TIME[2014-02-08 10:53:37 +09:00]] 版))
<http://tools.ietf.org/html/draft-ietf-websec-key-pinning-11>
[2] [CITE@en[draft-ietf-websec-key-pinning-15 - Public Key Pinning Extension for HTTP]]
( ([TIME[2014-06-17 09:04:18 +09:00]] 版))
<http://tools.ietf.org/html/draft-ietf-websec-key-pinning-15>
[3] [CITE@en[Re: CSP: Problems with referrer and reflected-xss]]
( ([[Chris Palmer]] 著, [TIME[2014-06-17 03:33:33 +09:00]] 版))
<http://lists.w3.org/Archives/Public/public-webappsec/2014Jun/0177.html>
[4] [CITE@en[draft-ietf-websec-key-pinning-20 - Public Key Pinning Extension for HTTP]]
( ([TIME[2014-08-08 08:13:32 +09:00]] 版))
<https://tools.ietf.org/html/draft-ietf-websec-key-pinning-20>
* 関連
[6] [[HSTS]] との併用が想定されていますが、単独でも使えます [SRC[>>5]]。
[18] [CITE@en[SecurityEngineering/Public Key Pinning/Implementation Details - MozillaWiki]]
([TIME[2015-06-04 12:05:21 +09:00]] 版)
<https://wiki.mozilla.org/SecurityEngineering/Public_Key_Pinning/Implementation_Details>
[FIG(quote)[
[FIGCAPTION[
[48] [CITE[Security FAQ - The Chromium Projects]]
([TIME[2015-06-06 06:30:25 +09:00]] 版)
<http://www.chromium.org/Home/chromium-security/security-faq#TOC-How-does-key-pinning-interact-with-local-proxies-and-filters->
]FIGCAPTION]
> 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.
]FIG]
[75] [CITE@ja[Public Key Pinning - Web security | MDN]]
([TIME[2015-05-08 17:50:59 +09:00]] 版)
<https://developer.mozilla.org/ja/docs/Web/Security/Public_Key_Pinning>
[77] [CITE[不正なSSL証明書を見破るPublic Key Pinningを試す - ぼちぼち日記]]
([TIME[2016-01-13 10:46:05 +09:00]] 版)
<http://d.hatena.ne.jp/jovi0608/20140902/1409635279>
[FIG(quote)[
[FIGCAPTION[
[78] [CITE[不正なSSL証明書を見破るPublic Key Pinningを試す - ぼちぼち日記]]
([TIME[2016-01-13 10:46:05 +09:00]] 版)
<http://d.hatena.ne.jp/jovi0608/20140902/1409635279>
]FIGCAPTION]
> 4.7 Pre-loaded/HPKPの併用
> 仕様では実装依存になっていますが、 Chrome は HPKPを先にチェックするようになっています。
]FIG]
[FIG(quote)[
[FIGCAPTION[
[79] [CITE@en[GitHub]]
([TIME[2016-04-18 00:54:08 +09:00]] 版)
<https://github.com/>
]FIGCAPTION]
> 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
]FIG]
[FIG(quote)[
[FIGCAPTION[
[82] [CITE@en[gecko-dev/NSSCertDBTrustDomain.cpp at master · mozilla/gecko-dev]]
( ([TIME[2016-05-10 23:06:28 +09:00]]))
<https://github.com/mozilla/gecko-dev/blob/master/security/certverifier/NSSCertDBTrustDomain.cpp>
]FIGCAPTION]
>
> // If mHostname isn't set, we're not verifying in the context of a TLS
> // handshake, so don't verify HPKP in those cases.
]FIG]
[FIG(quote)[
[FIGCAPTION[
[83] [CITE@en[RFC 7858 - Specification for DNS over Transport Layer Security (TLS)]]
( ([TIME[2016-05-21 01:58:28 +09:00]]))
<https://tools.ietf.org/html/rfc7858#appendix-A>
]FIGCAPTION]
> 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:
]FIG]
[84] [CITE@en[Issue 445821 - chromium - crypto.cat certificate pinning update required - Monorail]]
( ([TIME[2016-05-31 00:01:14 +09:00]]))
<https://bugs.chromium.org/p/chromium/issues/detail?id=445821>
[85] [CITE@en[Issue 446240 - chromium - Remove pinning for cryptocat - Monorail]]
( ([TIME[2016-05-31 00:02:13 +09:00]]))
<https://bugs.chromium.org/p/chromium/issues/detail?id=446240>