在服務(wù)器上啟用HTTP公鑰固定擴展的教程
公鑰固定(Public Key Pinning)是指一個證書鏈中必須包含一個白名單中的公鑰,也就是說只有被列入白名單的證書簽發(fā)機構(gòu)(CA)才能為某個域名*.example.com簽發(fā)證書,而不是你的瀏覽器中所存儲的任何 CA 都可以為之簽發(fā)。本文講述了這種機制的背景知識,并提供了 Apache、 Lighttpd 和 NGINX 上的配置范例。
HTTP 公鑰固定擴展
用你使用的銀行做個例子,它一直使用 CA 公司 A 為其簽發(fā)證書。但是在當前的證書體系下,CA 公司 B、CA 公司 C 和 NSA 的 CA 都能給你的銀行創(chuàng)建證書,而你的瀏覽器會毫無疑慮的接受它們,因為這些公司都是你所信任的根 CA。
如果你的銀行實現(xiàn)了 HPKP 并固定了它們的第一個中級證書(來自 CA 公司 A),那么瀏覽器將不會接受來自CA 公司 B 和 CA 公司 C 的證書,即便它們也有一個有效的信任鏈。HPKP 也允許你的瀏覽器將這種違例行為報告給該銀行,以便銀行知道被偽造證書攻擊了。
HTTP 公鑰固定擴展是一個從2011年開始開發(fā)的針對 HTTP 用戶代理(即瀏覽器)的公鑰固定標準。它由 Google 發(fā)起,甚至在 Chrome 中實現(xiàn)的固定機制可以使用一個人工維護的網(wǎng)站公鑰固定列表,這個列表包含了固定的幾個網(wǎng)站的公鑰簽名。(LCTT 譯注:Chrome 和 FireFox 32 及以后版本都支持公鑰固定機制,并使用內(nèi)置的人工維護的公鑰固定列表數(shù)據(jù),這些數(shù)據(jù)隨著瀏覽器軟件的更新而更新,主要包括幾個大型站點。目前還只有 Chrome 38+ 支持通過 HTTP 響應(yīng)頭傳遞公鑰固定信息。)
以下是 HPKP 的幾個功能簡述:
- HPKP 是在 HTTP 層面設(shè)置的,使用 Public-Key-Pins (PKP)響應(yīng)頭。
- 該規(guī)則的保留周期通過 max-age 參數(shù)設(shè)置,單位是秒。
- PKP 響應(yīng)頭只能用于正確的安全加密通訊里面。
- 如果出現(xiàn)了多個這樣的響應(yīng)頭,則只處理第一個。
- 固定機制可以使用includeSubDomains參數(shù)擴展到子域。
- 當接收到一個新的 PKP 響應(yīng)頭時,它會覆蓋之前存儲的公鑰固定和元數(shù)據(jù)。
- 公鑰固定是用哈希算法生成的,其實是一個“主題公鑰信息(SKPI)”指紋。
本文首先會介紹一些 HPKP 工作的原理,接下來我們會展示給你如何得到需要的指紋并配置到 web 服務(wù)器中。
SPKI 指紋 - 理論
通常來說,對證書進行哈希是一個顯而易見的解決方案,但是其實這是錯的。不能這樣做的原因是 CA 證書可以不斷重新簽發(fā):同一個公鑰、主題名可以對應(yīng)多個證書,而這些證書有不同的延展或失效時間。瀏覽器從下至上地在證書池中構(gòu)建證書鏈時,另外一個版本的證書可能就替代匹配了你原本所期望的證書。
舉個例子,StartSSL 有兩個根證書:一個是以 SHA1 簽名的,另外是一個是 SHA256。如果你希望固定住 StartSSL 作為你的 CA,那么你該使用哪個證書呢?你也許可以使用這兩個,但是如果我不告訴你,你怎么會知道還有一個根證書呢?
相反地,對公鑰進行哈希則不會有這個問題:
瀏覽器假定子證書是固定不動的:它總是證書鏈的起點。子證書所攜帶的簽名一定是一個有效的簽名,它來自其父證書給這個證書專門簽發(fā)的。這就是說,父證書的公鑰相對于子證書來說是固定的。所以可推論公鑰鏈是固定的。
唯一的問題是你不能固定到一個交叉認證的根證書上。舉個例子,GoDaddy 的根證書是 Valicert 簽名的,這是為了讓那些不能識別 GoDaddy 根證書的老客戶可以信任其證書。然而,你不能固定到 Valicert 上,因為新的客戶在證書鏈上發(fā)現(xiàn)了 GoDaddy 證書就會停止上溯(LCTT 譯注:所以就找不到固定信息了)。
此外,我們是對 SubjectPublicKeyInfo(SPKI)進行哈希而不是對公鑰位串。SPKI 包括了公鑰類型、公鑰自身及其相關(guān)參數(shù)。這很重要,因為如果對公鑰進行哈希就有可能導(dǎo)致發(fā)生曲解攻擊。對于一個 Diffie-Hellman 公鑰而言:如果僅對公鑰進行哈希,而不是對完整的 SPKI,那么攻擊者可以使用同樣的公鑰而讓客戶端將其解釋為其它組。同樣地,這樣也有可能強制將一個 RSA 密鑰當成 DSA 密鑰解釋等等。
固定在哪里
你應(yīng)該固定在什么地方?固定你自己的公鑰并不是一個最好的辦法。你的密鑰也許會改變或撤銷。你也許會使用多個證書,經(jīng)常輪換證書的話密鑰就改變了。也許由于服務(wù)器被入侵而撤銷證書。
最容易但是不是太安全的方法是固定第一個中級 CA 證書。該證書是簽名在你的網(wǎng)站證書之上的,所以簽發(fā)該證書的 CA 的公鑰肯定是在證書鏈上的。
采用這種方法你可以從同一個 CA 更新你的證書而不用擔心固定信息不對。如果該 CA 發(fā)行了一個不同的根證書,也許你會遇到一些問題,對此并沒有太好的解決方案。不過你可以通過如下做法來減輕這種問題的影響:
從一個不同的 CA 申請一個備用的證書,并固定該備份。
RFC 里面說你至少需要做兩個固定。一個是當前連接所使用的證書鏈上的,另外一個是備份的。
另外的固定是對備份公鑰的,它可以是來自另外一個給你簽發(fā)證書的不同 CA 的 SKPI 指紋。
在這個問題上還有一種更安全的方法,就是事先創(chuàng)建好至少三個獨立的公鑰(使用 OpenSSL,參見此頁 了解 Javascript OpenSSL 命令生成器),并將其中兩個備份到一個安全的地方,離線存儲、不要放到網(wǎng)上。
為這三個證書創(chuàng)建 SPKI 指紋并固定它們,然后僅使用第一個作為當前的證書。當需要時,你可以使用備份密鑰之一。不過你需要讓 CA 給你做簽名來生成證書對,這可能需要幾天,依你的 CA 的工作情況而定。
對于 HPKP 來說這沒有問題,因為我們使用的是公鑰的 SPKI 哈希,而不是證書。失效或不同的 CA 簽名鏈并不影響。
如果你按照上述方法生成并安全存儲了至少三個獨立的密鑰,并固定它們,也可以防止你的 CA 撤銷你的網(wǎng)站證書并簽發(fā)一個假證書時出現(xiàn)問題。
SPKI 指紋
可以使用如下的 OpenSSL 命令來生成 SPKI 指紋,它出現(xiàn)在 RFC 草案 中:
openssl asn1parse -noout -inform pem -out public.key;
openssl dgst -sha256 -binary public.key | openssl enc -base64
結(jié)果:
上面輸入的 certificate.pem 文件是本站(https://raymii.org)的證書鏈中第一個證書。(在寫本文時, COMODO RSA Domain Validation Secure Server CA, 序列號 2B:2E:6E:EA:D9:75:36:6C:14:8A:6E:DB:A3:7C:8C:07 )。
你也需要同樣對你的另外兩個備份公鑰生成指紋。
故障
在寫本文時(2015/1),唯一支持 HPKP 的瀏覽器(chrome)有一個嚴重的問題:Chrome 并不能夠區(qū)分 HSTS 和 HPKP 響應(yīng)頭中的 max-age 和 includeSubdomains 參數(shù)。也就是說,如果你的 HSTS 和 HPKP 設(shè)置了不同的 max-age 和 includeSubdomains 參數(shù),它們會互相搞亂。關(guān)于這個故障的更多信息參見:https://code.google.com/p/chromium/issues/detail?id=444511。感謝 Scott Helme(https://scotthelme.co.uk)發(fā)現(xiàn)并告訴我這個 Chromium 項目的問題。
Web 服務(wù)器配置
下面你可以看到三個主流 Web 服務(wù)器的配置方法。這只是一個 HTTP 響應(yīng)頭,絕大多數(shù) Web 服務(wù)器都可以設(shè)置它。它只需要設(shè)置到 HTTPS 網(wǎng)站上。
下面的例子固定到 COMODO RSA Domain Validation Secure Server CA 及備份的 Comodo PositiveSSL CA 上,30天失效期,包括所有的子域。
Apache
編輯你的 Apache 配置文件(如 /etc/apache2/sites-enabled/website.conf 或 /etc/apache2/httpd.conf),并添加下列行到你的 VirtualHost 中:
LoadModule headers_module modules/mod_headers.so
Header set Public-Key-Pins "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains"
Lighttpd
Lighttpd 更簡單一些,將下列行添加到你的 Lighttpd 配置文件(如 /etc/lighttpd/lighttpd.conf):
$HTTP["scheme"] == "https" {
setenv.add-response-header = ( "Public-Key-Pins" => "pin-sha256=\"klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=\"; pin-sha256=\"633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q=\"; max-age=2592000; includeSubDomains")
}
NGINX
NGINX 的配置更簡短。添加以下行到你的 HTTPS 配置的 server 塊中:
add_header Public-Key-Pins 'pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; pin-sha256="633lt352PKRXbOwf4xSEa1M517scpD3l5f79xMD9r9Q="; max-age=2592000; includeSubDomains';
報告功能
HPKP 報告功能允許瀏覽器報告任何違例給你。
如果你在響應(yīng)頭中添加了附加的 report-uri="http://example.org/hpkp-report" 參數(shù),并用該 URI 處理接收到的數(shù)據(jù)的話,客戶端會在發(fā)現(xiàn)違例時發(fā)送報告給你。這個報告是以 POST 方式發(fā)送到你指定的 report-uri 上,并以類似下面的 JSON 格式:
"date-time": "2014-12-26T11:52:10Z",
"hostname": "www.example.org",
"port": 443,
"effective-expiration-date": "2014-12-31T12:59:59",
"include-subdomains": true,
"served-certificate-chain": [
"-----BEGINCERTIFICATE-----\nMIIAuyg[...]tqU0CkVDNx\n-----ENDCERTIFICATE-----"
],
"validated-certificate-chain": [
"-----BEGINCERTIFICATE-----\nEBDCCygAwIBA[...]PX4WecNx\n-----ENDCERTIFICATE-----"
],
"known-pins": [
"pin-sha256=\"dUezRu9zOECb901Md727xWltNsj0e6qzGk\"",
"pin-sha256=\"E9CqVKB9+xZ9INDbd+2eRQozqbQ2yXLYc\""
]
}
非強制,只報告
HPKP 也可以設(shè)置為非強制的,可以使用 Public-Key-Pins-Report-Only 來只發(fā)送違例報告給你。
這樣可以讓你在網(wǎng)站不可訪問或 HPKP 配置不正確時不固定,之后你可以將這個響應(yīng)頭改為 Public-Key-Pins 來強制固定。
相關(guān)文章
CentOS 7配置LNMP開發(fā)環(huán)境及配置文件管理詳解
本篇文章主要介紹了CentOS 7配置LNMP開發(fā)環(huán)境及配置文件管理,詳細的介紹了MySQL 5.6,PHP 5.6,Nginx的安裝與配置,有興趣的可以了解一下。2017-01-01Linux下查看binlog文件創(chuàng)建時間的命令
這篇文章主要介紹了Linux下查看binlog文件創(chuàng)建時間的命令,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05Linux 新的API signalfd、timerfd、eventfd使用說明
這篇文章主要介紹了Linux 新的API signalfd、timerfd、eventfd使用說明的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下2016-10-10Linux下的crontab定時執(zhí)行任務(wù)命令詳解
cron的配置文件稱為“crontab”,是“cron table”的簡寫。這篇文章主要介紹了Linux下的crontab定時執(zhí)行任務(wù)命令詳解,需要的朋友可以參考下2018-09-09Linux終端提示符(prompt)不如期生效的原因分析與解決
Linux命令行是系統(tǒng)管理員管理Linux的重要手段,我們管理Linux,首先要面對的就是Linux命令行提示符。下面這篇文章主要給大家介紹了Linux終端提示符(prompt)不如期生效的原因以及解決方法,需要的朋友可以參考下。2017-07-07