?
This document uses PHP Chinese website manual Release
該公共密鑰鋼釘擴展HTTP(HPKP)是一種安全功能,它講述了一個Web客戶端與某個web服務器的特定密碼公鑰關聯(lián)到降低風險中間人偽造證書的攻擊。
為了確保在TLS會話中使用的服務器公鑰的真實性,該公鑰被封裝到通常由證書頒發(fā)機構(gòu)(CA)簽署的X.509證書中。Web客戶端(如瀏覽器)信任很多這些CA,它們都可以為任意域名創(chuàng)建證書。如果攻擊者能夠危害單個CA,他們可以對各種TLS連接執(zhí)行MITM攻擊。HPKP可以通過告訴客戶端哪個公鑰屬于某個Web服務器來規(guī)避HTTPS協(xié)議的這種威脅。
HPKP是首次使用信托(TOFU)技術(shù)。Web服務器第一次通過特殊的HTTP頭告訴客戶端公鑰屬于它,客戶端將這些信息存儲一段給定的時間。當客戶端再次訪問服務器時,它期望證書鏈中至少有一個證書包含已通過HPKP識別指紋的公鑰。如果服務器提供未知的公鑰,則客戶端應向用戶提供警告。
Firefox和Chrome 禁用了針對經(jīng)過驗證的證書鏈終止于用戶定義的信任錨(而不是內(nèi)置信任錨)的固定主機的引腳驗證。這意味著對于導入自定義根證書的用戶,所有釘住違規(guī)都會被忽略。
要為您的站點啟用此功能,您需要在Public-Key-Pins
通過HTTPS訪問站點時返回HTTP標頭:
Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubDomains][; report-uri="reportURI"]
pin-sha256
引用的字符串是Base64編碼的主題公鑰信息(SPKI)指紋。可以為不同的公鑰指定多個引腳。未來某些瀏覽器可能會允許其他哈希算法而不是SHA-256。請參閱下面有關如何從證書或密鑰文件中提取此信息。max-age
以秒為單位的瀏覽器應該記住,該站點只能使用其中一個定義的鍵來訪問。includeSubDomains
可選如果指定了此可選參數(shù),則此規(guī)則也適用于所有網(wǎng)站的子域。report-uri
可選如果指定了此可選參數(shù),則將引腳驗證失敗報告給給定的URL。
注意:目前的規(guī)范要求包含一個備用密鑰的第二個引腳,該密鑰尚未用于生產(chǎn)。這允許更改服務器的公鑰,而不會破壞已經(jīng)注意到引腳的客戶端的可訪問性。例如,當前一個密鑰受到攻擊時,這很重要。
注意:雖然下面的示例顯示了如何在服務器證書上設置管腳,但建議將管腳放置在頒發(fā)服務器證書的CA的中間證書上,以簡化證書更新和輪換。
首先,您需要從證書或密鑰文件中提取公鑰信息并使用Base64對其進行編碼。
以下命令將幫助您從密鑰文件,證書簽名請求或證書中提取Base64編碼的信息。
openssl rsa -in my-rsa-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
openssl ec -in my-ecc-key-file.key -outform der -pubout | openssl dgst -sha256 -binary | openssl enc -base64
openssl req -in my-signing-request.csr -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
openssl x509 -in my-certificate.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
以下命令將提取網(wǎng)站的Base64編碼信息。
openssl s_client -servername www.example.com -connect www.example.com:443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
Public-Key-Pins: pin-sha256="cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs="; pin-sha256="M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE="; max-age=5184000; includeSubDomains; report-uri="https://www.example.org/hpkp-report"
在本例中,pin-sha256 =“cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2 + soZS7sWs =”固定生產(chǎn)中使用的服務器公鑰。第二個引腳聲明pin-sha256 =“M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE =”也引腳備份密鑰。max-age = 5184000告訴客戶將這些信息存儲兩個月,根據(jù)IETF RFC這是一個合理的時間限制。此關鍵固定也適用于所有子域,這由includeSubDomains聲明告知。最后,report-uri =“ https://www.example.net/hpkp-report ”解釋報告引腳驗證失敗的位置。
Public-Key-Pins
您也可以使用Public-Key-Pins-Report-Only
標題,而不是使用標題。此標題僅將報告發(fā)送到report-uri
標題中指定的報告,并且仍允許瀏覽器連接到Web服務器,即使違反了固定也是如此。
提供HPKP頭文件所需的具體步驟取決于您使用的Web服務器。
注意:這些示例使用兩個月的最大年齡并包含所有子域。建議驗證此設置適用于您的服務器。
如果使用不當,HPKP可能會長時間鎖定用戶!建議使用備份證書和/或固定CA證書。
在您的web服務器的配置文件中添加一行類似于以下內(nèi)容的行將啟用Apache上的HPKP。這需要mod_headers
啟用。
Header always set Public-Key-Pins "pin-sha256=\"base64+primary==\"; pin-sha256=\"base64+backup==\"; max-age=5184000; includeSubDomains"
添加以下行并插入適當?shù)?code>pin-sha256="..."值將在您的nginx上啟用HPKP。這需要ngx_http_headers_module.
add_header Public-Key-Pins 'pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubDomains' always;
以下與相關密鑰信息(pin-sha256 =“...”字段)的行將啟用lighttpd上的HPKP。
setenv.add-response-header = ( "Public-Key-Pins" => "pin-sha256=\"base64+primary==\"; pin-sha256=\"base64+backup==\"; max-age=5184000; includeSubDomains")
注意:這需要mod_setenv
加載server.module,如果尚未加載,可以將其包含在內(nèi)。
server.modules += ( "mod_setenv" )
將以下行添加到Web.config文件以發(fā)送Public-Key-Pins
標頭:
<system.webServer> ... <httpProtocol> <customHeaders> <add name="Public-Key-Pins" value="pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubDomains" /> </customHeaders> </httpProtocol> ...</system.webServer>
規(guī)范 | 標題 |
---|---|
RFC 7469,第2.1節(jié):公鑰索引 | HTTP的公鑰固定擴展 |
Feature | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic Support | (Yes) | No1 | 35.0 | ? | (Yes) | ? |
report-uri | 46 | ? | No2 | ? | 33 | ? |
Feature | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
Basic Support | (Yes) | (Yes) | ? | 35.0 | ? | (Yes) | ? |
report-uri | (Yes) | (Yes) | ? | No | ? | 33 | ? |