【发布时间】:2011-01-25 00:27:05
【问题描述】:
是否有一种方法可以让浏览器中运行的 JavaScript 确定正在使用哪个 CA 证书来验证浏览器当前 HTTPS 连接的远程主机,并获取该证书的属性,例如 CA 的名称?
如果没有,是否有任何其他选项可用于以编程方式获取此信息,例如服务器端的 ActiveX、Java、CGI,...?
【问题讨论】:
标签: javascript browser ssl certificate ssl-certificate
是否有一种方法可以让浏览器中运行的 JavaScript 确定正在使用哪个 CA 证书来验证浏览器当前 HTTPS 连接的远程主机,并获取该证书的属性,例如 CA 的名称?
如果没有,是否有任何其他选项可用于以编程方式获取此信息,例如服务器端的 ActiveX、Java、CGI,...?
【问题讨论】:
标签: javascript browser ssl certificate ssl-certificate
您可以使用开源Forge project 来执行此操作。它在 JavaScript 中实现 SSL/TLS。您可以对服务器进行 ajax 调用并使用回调来检查证书。请记住,服务器是发送 JavaScript 的服务器,因此不应使用它来确定您是否信任 JavaScript 来自的服务器。 Forge 项目确实允许跨域请求,因此如果您将其用于信任,您可以从您已经信任的服务器加载 Forge JavaScript,然后联系您尚未信任的服务器。但是,除非其他服务器提供跨域策略,否则您将无法执行跨域请求。
https://github.com/digitalbazaar/forge/blob/master/README.md
自述文件中的博客链接提供了有关如何使用 Forge 及其工作原理的更多信息。
【讨论】:
从Is there any way to access certificate information from a Chrome Extension复制我自己的答案
您需要制作一个 WebExtension,也称为浏览器扩展。
见accessing security information on MDN
您还可以查看以下文档:
您需要 Firefox 62。
这是一个有效的background.js
var log = console.log.bind(console)
log(`\n\nTLS browser extension loaded`)
// https://developer.chrome.com/extensions/match_patterns
var ALL_SITES = { urls: ['<all_urls>'] }
// Mozilla doesn't use tlsInfo in extraInfoSpec
var extraInfoSpec = ['blocking'];
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/onHeadersReceived
browser.webRequest.onHeadersReceived.addListener(async function(details){
log(`\n\nGot a request for ${details.url} with ID ${details.requestId}`)
// Yeah this is a String, even though the content is a Number
var requestId = details.requestId
var securityInfo = await browser.webRequest.getSecurityInfo(requestId, {
certificateChain: true,
rawDER: false
});
log(`securityInfo: ${JSON.stringify(securityInfo, null, 2)}`)
}, ALL_SITES, extraInfoSpec)
log('Added listener')
manifest.json:
{
"manifest_version": 2,
"name": "Test extension",
"version": "1.0",
"description": "Test extension.",
"icons": {
"48": "icons/border-48.png"
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>"
]
}
它也可以在 Chromium 中实现一次this code is merged。
【讨论】:
在 Web 浏览器中运行的 JavaScript 无权访问证书信息。证书信息也不会通过 HTTP 传递给应用程序。我的研究表明,Web 应用程序无法确定中间人攻击是否在主机和客户端之间的某处注入了虚假证书。
【讨论】:
没有。您显然可以使用 AJAX/ActiveX/Java/Flash/Silverlight 和自定义服务器端脚本来实现,但我不明白您为什么需要它。
编辑:上面的想法是您将向服务器发出网络请求(使用上述技术之一)并询问用于该网络请求的证书。然后服务器可以检查自己的配置并回答问题。
如果浏览器以某种方式信任无效证书并连接到错误的服务器(例如 MITM 服务器),则服务器可能会撒谎。一旦浏览器的信任机制被破坏,我不知道如何避免。
据我所知,没有办法(纯粹使用客户端 API)直接询问浏览器它使用什么证书“用于浏览器当前的 SSL 连接”。即使是 Forge 也不这样做。它创建一个完全并行 SSL 会话,但它不允许您询问浏览器的本机 SSL 会话。
【讨论】:
AFAIK 不能单独使用 Javascript。但是一些网络服务器允许您访问线程或进程的连接参数。然后,服务器端脚本可以将这些值与请求一起发送并使用它。
我为 nginx 网络服务器找到了这个: http://wiki.nginx.org/NginxHttpSslModule (查看页面底部的变量)。应该可以将它们设置为环境变量并将它们传递给您的 FastCGI 进程或您使用的任何东西。
AOLServer/Naviserver 允许使用 nsssl 模块进行类似的访问。
【讨论】:
实际上,这几乎没有用——为什么您需要在已呈现的单个页面上从 JavaScript 中了解证书信息?
如果它不受信任,那么显然您的代码也可能被更改过,因此它也不能被信任。
如果证书实际上是受信任的,那么您如何能够将这种情况与证书不受信任的情况区分开来,但您的代码已通过中间人攻击被修改为不这样认为?
因此,检查证书仅在 Browser Extensions(假定为受信任的代码)中而不是在单个页面中的脚本中有用 他们自己。扩展使用的这种接口是特定于浏览器的,并不是所有的浏览器都提供它。例如,虽然 Mozilla 浏览器确实允许您查看证书(提供像 EFF SSL Observatory 这样的扩展名),但 Chromium is still lacking。
【讨论】: