在 Web 浏览器中,JavaScript 是否可以获取有关用于当前页面的 HTTPS 证书的信息?

IT技术 javascript browser ssl certificate ssl-certificate
2021-03-11 15:51:22

是否有一种方法可以让浏览器中运行的 JavaScript 确定使用哪个 CA 证书来验证浏览器当前 HTTPS 连接的远程主机,并获取该证书的属性,例如 CA 的名称?

如果没有,是否还有其他选项可以以编程方式获取此信息,例如服务器端的 ActiveX、Java、CGI,...?

6个回答

您可以使用开源Forge 项目来执行此操作。它在 JavaScript 中实现了 SSL/TLS。您可以对服务器进行 ajax 调用并使用回调来检查证书。请记住,服务器是发送 JavaScript 的服务器,因此不应使用它来确定您是否信任 JavaScript 来自的服务器。Forge 项目确实允许跨域请求,因此如果您将其用于信任,您可以从您已经信任的服务器加载 Forge JavaScript,然后联系您尚不信任的服务器。但是,除非其他服务器提供跨域策略,否则您将无法执行跨域请求。

https://github.com/digitalbazaar/forge/blob/master/README.md

自述文件中的博客链接提供了有关如何使用 Forge 及其工作原理的更多信息。

我不认为答案是正确的 - 充其量是误导。似乎没有办法在客户端获取证书信息。当然,Forge 是一个有趣的项目,但这比实际答案更有趣。
2021-04-18 15:51:22
看起来 Forge 可以使用以下方法之一(不能同时使用): 1. 将 Flash 用于原始套接字。2. 在 WebSockets 上使用 TLS(这不是标准的 HTTPS,但需要自定义服务器支持)。这可能对某些人有用,但重要的是要知道发生了什么。参见github.com/digitalbazaar/forge/issues/97#issuecomment-33161672
2021-05-07 15:51:22

有没有办法从 Chrome 扩展程序访问证书信息中复制我自己的答案

2018 年回答:是的,在 Firefox 62 中

您需要制作一个 WebExtension,也称为浏览器扩展。

请参阅在 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 中实现

根据 cnst 的回答,Mozilla 中的功能至少在 2014 年就已经存在。尽管无论哪种方式它本身都不能回答问题,因为您必须安装扩展程序而不是标准的网站应用程序。
2021-04-16 15:51:22
@AlexisWilke cnst 的答案是针对已被删除的弃用 API。问题是“在浏览器中运行的 JS”,这是,并且还询问了替代方法(即使您不认为它们是“在浏览器中运行的 JS”,它也肯定包括扩展)。
2021-04-23 15:51:22

在 Web 浏览器中运行的 JavaScript 无法访问证书信息。证书信息也不会通过 HTTP 传递给应用程序。我的研究表明,Web 应用程序无法确定中间人攻击是否在主机和客户端之间的某处注入了伪造的证书。

如果中间人正在冒充您的服务器到客户端,他们当然能够用您的证书的“正确”答案硬编码的东西替换您的 javascript ......
2021-04-25 15:51:22
同时,您有按钮/菜单选项可以打开带有该信息的弹出窗口,所以我不明白为什么它不能用于您的 JS 环境。不过,对于防止 MITM 攻击可能没有用。
2021-04-30 15:51:22
我看到了,Web页面Web应用程序,JS 代码。(我以为是独立应用程序。抱歉。)
2021-05-08 15:51:22
@curiousguy 我的理解:应用程序数据是使用 HTTP 通过应用程序层在 Web 应用程序和客户端浏览器之间发送的。证书信息使用 TLS 通过传输层在 Web 服务器和客户端浏览器之间发送。
2021-05-11 15:51:22

不。您显然可以使用 AJAX/ActiveX/Java/Flash/Silverlight 和自定义服务器端脚本来实现,但我不明白您为什么需要它。


编辑:上面的想法是您将向服务器发出网络请求(使用上述技术之一)并询问该网络请求使用了什么证书。然后服务器可以检查自己的配置并回答问题。

如果浏览器以某种方式信任无效证书并连接到错误的服务器(例如 MITM 服务器),则该服务器可能会撒谎。一旦浏览器的信任机制遭到破坏,我不知道如何避免。

据我所知,没有办法(纯粹使用客户端 API)直接询问浏览器“用于浏览器当前 SSL 连接”的证书。即使 Forge 也不会这样做。它创建了一个完全并行的SSL 会话,但它不允许您询问浏览器的本机 SSL 会话。

@MaxRied,答案是“不,但是”,我说“不……”。问题是关于如何“确定哪个 CA 证书用于对浏览器当前 SSL 连接的远程主机进行身份验证” IE 浏览器具有正常的 SSL 堆栈(当前正在使用),您能否向浏览器询问什么证书和此类正在用于当前的 SSL 连接。基本上,没有你不能,无论你写了多少 JS。(Forge 创建一个并行 SSL 会话,它不检查标准会话)。但是,您可以询问您自己的服务器,但要遵守 SSL 信任的标准问题。
2021-04-18 15:51:22
@MaxRied,不,不是。不可能按照实际问题提出的要求去做,这就是为什么我的回答以“否”开头。所问的问题是,您是否知道客户端“正在使用哪个 CA 证书来验证浏览器当前 SSL 连接的远程主机”。我相信答案是“不,该信息在客户端不可用,但是......”。其他答案都没有解释如何做到这一点(Forge 是关于设置单独的 SSL 堆栈,而不是检查浏览器的 SSL 堆栈或证书)。
2021-04-27 15:51:22
@MaxRied,还请注意,说不可能的事情完全没问题我之所以不只是说的是,我希望额外的背景下是有用的,阐述我的观点。
2021-05-05 15:51:22
我会咬...这将如何在 AJAX 中完成?之所以需要这样做,是为了检查客户端是否使用了伪造的 CA 证书,从而允许中间人攻击。
2021-05-07 15:51:22
它更像是“嘿,不要那样做。”。OP 没有询问您是否认为这是一个好主意(这将是题外话,因为“主要基于意见”,这也使您的回答题外话,但这是另一点......)。他问如何做到这一点。这不是质疑问题的平台,而是解决问题的平台。你应该知道。
2021-05-07 15:51:22

AFAIK 不是单独使用 Javascript。但是有些网络服务器允许您访问线程或进程的连接参数。然后,服务器端脚本可以将这些值与请求一起发送,您可以使用它。

我为 nginx 网络服务器找到了这个:http : //wiki.nginx.org/NginxHttpSslModule (查看页面底部的变量)。应该可以将它们设置为环境变量并将它们传递给您的 FastCGI 进程或任何您使用的进程。

AOLServer/Naviserver 允许使用 nsssl module进行类似的访问。

感谢您的搜索。nginx 网络服务器信息适用于客户端证书,用于通过网络应用程序对用户进行身份验证。我有兴趣获取有关客户端浏览器上使用的 CA 证书的信息 - 对浏览器正在访问的网站进行身份验证的 CA 证书。
2021-04-19 15:51:22