目前的JS语言标准不暴露证书信息;除此之外,这可能取决于您使用 JavaScript 的方式,如果您希望最终用户的浏览器公开证书信息,那么这将是非常有问题的,因为您需要至少获得 FF、Chrome、Safari、IE , Edge, ... 暴露它。
但是,正如 Information Security post 中提到的,这对于这些浏览器来说并不是一个真正理想的选择,因为它会允许网站开发人员编写代码错误地信任用户端凭据的情况。
与其说是阻止 javascript 访问浏览器当前 SSL 证书信息的可见性安全风险,不如说是 JS 开发人员必须意识到“用户接受”证书不一定是第四个墙屏障安全风险该网站提供的那个。 HTML 页面确实不应该处理客户端代码的安全问题,而是应该能够依赖安全层来正确完成它的工作。 (我完全可以理解想要检查安全层,但是您在顶层所做的任何管理工作都只是肤浅的,或者是对整个生物圈的改造)
因为让我们暂时假设 javascript 确实提供了一种使用证书的方法,那么当 Bob 已经信任 Mallory 因为他的安全性被破坏时,就无法停止以下交换:
办公室工作人员 Bob 位于 Mega Corp. 的防火墙的一侧,IT Mallory 负责将流量传入和传出公司本地的防火墙,而 Web 主机 Alice 的精彩网站则在 WWW 上。
- 根据 Mega Corp. 公司的政策,Bob 只接受马洛里所说的话。
- Bob 想要访问 Alice 的站点,但没有直接的外部访问权限,他试图通过持有他的证书(例如:“我在此声明我是 Bob”)通过防火墙建立一个安全连接,并询问 Alice真是令人费解,“我给你发了什么证书?”
- Mallory 收到 Bob 的请求,但她自己传递(例如:“呃,Bob 说我可以阅读他的网络邮件”),即使 Mallory 不理解 Bob 的复杂问题,她仍然向 Alice 重复, “akdvyfenwythnwerhy?”。
- Alice 做了一些数学运算,发现“akdvyfenwythnwerhy?”在问“我给你发了什么证书?”并用她看到的内容回复马洛里(“嗨,鲍勃,这是爱丽丝,你说:嗯,鲍勃说我可以阅读他的网络邮件”)。
- Mallory 做了一些数学运算,哈哈大笑“akdvyfenwythnwerhy?=我给你发了什么证书?”,并代表 Alice 回答 Bob 的问题(“嗨 Bob,这是 Alice(Mallory) 你说:我在此宣布我是 Bob")。
- Bob 相信生活是美好的,并继续阅读他的网络邮件,因为根据公司政策,他知道 Mallory 永远不会对他撒谎。
- Mallory 现在能够阅读对话的双方,将 Bob 的请求传递给 Alice,以阅读他的网络邮件。
- Alice 收到 Bob 的请求并说嘿等一下 Bob 我需要你运行这段 JS 代码来证明你知道你正在和 Alice 交谈。
- Mallory 获取代码并运行它,然后将结果表明她知道她正在与 Alice 交谈并发送回 Alice。
- Alice 说,这对我来说已经足够了,这是您的网络邮件。
- Mallory 阅读了 Bob 的网络邮件,然后将其传递给 Bob,每个人都非常高兴。
(注意:我没有解决您在服务器端运行 JS 的情况,这将取决于您使用什么程序来运行 JS 代码。)
编辑 2018 年 4 月 4 日——虽然上面没有错,但更多的是从嵌入式和链接 JS 的角度来看,而不是关于 `XMLHTTPRequest` JS 对象;此外,反对与 `XMLHTTPRequest` 共享 PKI 详细信息的最有力论据可能如下:
需要在 HTTPS 协议的 HTTP 部分和 S 部分之间保留一条强有力的分界线。 JavaScript 和它的 XMLHTTPRequest 对象位于该行的 HTTP(应用层)一侧,而整个证书交换过程位于该行的 S(trans/sec 层)一侧。为了保持安全方面的原子性(热插拔),它的内部工作不能跨线暴露给应用程序端;因为可能有一天,传输/安全层不再使用 PKI 证书来促进其安全通信服务,当那一天到来时,没有人需要重写任何依赖这些证书中包含的细节来处理的现有 JS 代码随着 www 社区逐渐采用他们最喜欢的任何新安全层风格引起的传播浪潮。
话虽如此,安全方面似乎也在进行法人实体审查——至少在某些情况下,例如 EV 证书——,而 IMO 的缺点是 RFC7230 section 2.7.2 没有重新定义 @ https-URI 中的 987654324@ 包括一个可选的 legalentity,安全层在验证与之通信的 url 时将使用它不仅是正确的端点,而且当前处于预期业务关系的控制之下。
authority = [ userinfo "@" ] host [ "#" legalentity ] [ ":" port ]
legalentity = *( unreserved / pct-encoded / sub-delims )