0x01 前言
世界上有许多CA机构,这些机构签发的证书都被我们的浏览器所信任。但并不是每个CA都十分安全,为了防止某些CA有意或无意地签发错误的证书,我们可以告诉浏览器:网站使用的是哪个CA,从而防止中间人攻击。
0x02 准备
首先nginx服务器需要配置好SSL服务,你可以查看以下文章了解nginx ssl的配置方法:
在启用HPKP之前需要先获取CA证书的指纹。无论是使用商业CA机构还是自签发的CA,都不建议直接使用根证书。因为一旦根证书被移除或泄漏,将会造成非常严重的问题。
建议自签发的用户需要签一个中级证书,再签发用户证书。然后我们再将这个中级证书的指纹添加到HPKP中。
HPKP需要两个指纹,分为主备。当其中一个证书的签发机构被标注为不授信时,可以切换至另一个签发机构。这是因为HPKP的配置中有一个max-age值,这将强制浏览器缓存相应的指纹。
接下来需要获取中级证书的指纹。先准备好中级证书并存放到一个文件中,例如我现在使用的Let’s Encrypt:
#新建临时文件夹 [root@web-t1 ~]# mkdir temp/crt/ #进入文件夹 [root@web-t1 ~]# cd temp/crt/ #将中级证书写入文件 [root@web-t1 crt]# cat intermediate.pem -----BEGIN CERTIFICATE----- MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== -----END CERTIFICATE-----
如果你的证书链有多级,则需要检查所用的中级证书是否正确:
[root@web-t1 crt]# openssl x509 -in intermediate.pem -noout -subject subject= /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
检查C、O、CN字段是否一致:
然后生成Public Key:
[root@web-t1 crt]# openssl x509 -noout -in intermediate.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key;
然后使用Public Key生成指纹:
[root@web-t1 crt]# openssl dgst -sha256 -binary public.key | openssl enc -base64 YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=
用同样的方法,生成备用中级证书的指纹。在这里我使用comodo的中级证书:
#将中级证书写入文件 [root@web-t1 crt]# cat intermediate_comodo.pem -----BEGIN CERTIFICATE----- MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0 Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6 ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51 UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz 30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/ e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc 2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4 HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII 0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf +AZxAeKCINT+b72x -----END CERTIFICATE----- #获取中级证书的subject字段 [root@web-t1 crt]# openssl x509 -in intermediate_comodo.pem -noout -subject subject= /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA #生成Public Key [root@web-t1 crt]# openssl x509 -noout -in intermediate_comodo.pem -pubkey | openssl asn1parse -noout -inform pem -out public.key; #使用Public Key生成指纹 [root@web-t1 crt]# openssl dgst -sha256 -binary public.key | openssl enc -base64 klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=
将上面两段指纹记录下来备用。
0x03 配置
在nginx中只需要一行配置信息即可,格式如下:
Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubDomains][; report-uri="reportURI"]
解释如下:
- pin-sha256:一段Base64编码的Subject Public Key Information (SPKI)指纹,这个字段至少需要2个,一主一备。
- max-age:单位为秒,浏览器在这个时间段内会缓存设定的指纹直至过期。
- includeSubDomains:这是一个可选项,如果启用,则会将指纹应用在子域名上。
- report-ur:这是一个可选项,所以pin失败的记录都会被反馈到这个地址。
在这里,我的配置为:
add_header Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg="; pin-sha256="klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY="; max-age=2592000; includeSubDomains';
- max-age=2592000 为30天
将以上内容添加到nginx中的server段即可。然后重新加载nginx配置:
[root@web-t1 crt]# nginx -s reload
0x04 检查
0x04.1 firefox
使用firefox控制台即可查看到相关的内容:
在Firefox控制台中的安全性选项卡也可以看到启用情况:
0x04.2 chrome
chrome控制台中查看相关情况:
在调试工具中查看启用情况:
chrome://net-internals/#hsts
0x04.3 ssllabs
最后使用ssllabs进行检测,在HPKP一栏中可以看到:
0x05 相关网站
- HTTP Public Key Pinning Extension HPKP for Apache, NGINX and Lighttpd
- HTTP Public Key Pinning (HPKP)
- ssllabs: SSL Report: ngx.hk
0x06 结语
在漏洞日日新的今天,安全手段也随之更新,安全第一。