【问题标题】:Within a web browser, is it possible for JavaScript to obtain information about the HTTPS Certificate being used for the current page?在 Web 浏览器中,JavaScript 是否可以获取有关当前页面使用的 HTTPS 证书的信息?
【发布时间】:2011-01-25 00:27:05
【问题描述】:

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

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

【问题讨论】:

    标签: javascript browser ssl certificate ssl-certificate


    【解决方案1】:

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

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

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

    【讨论】:

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

    Is there any way to access certificate information from a Chrome Extension复制我自己的答案

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

    您需要制作一个 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

    【讨论】:

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

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

    【讨论】:

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

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


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

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

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

    【讨论】:

    • 我会咬...这将如何在 AJAX 中完成?需要这样做的原因是检查客户端是否使用了伪造的 CA 证书,从而允许中间人攻击。
    • @MaxRied,答案是“不,但是”,我说“不......”。问题是关于如何“确定哪个 CA 证书用于对浏览器当前 SSL 连接的远程主机进行身份验证”I.E.鉴于浏览器具有正常的 SSL 堆栈(当前正在使用),您能否向浏览器询问当前 SSL 连接使用的证书等。基本上,没有你不能,不管你写了多少 JS。 (Forge 创建一个并行 SSL 会话,它不检查标准会话)。但是,您可以询问自己的服务器,但要遵守 SSL 信任的标准问题。
    • 这更像是“嘿,不要那样做。”。 OP 没有问您是否认为这是一个好主意(这将与“主要基于意见”的主题无关,这也会使您的答案偏离主题,但这是另一点......)。他问如何做到这一点。这不是提问问题的平台,而是解决问题的平台。你应该知道的。
    • @MaxRied,不,不是。不可能按照实际问题的要求去做,这就是为什么我的回答以“不”开头。问的问题是,您能否知道客户端“正在使用哪个 CA 证书来验证浏览器当前 SSL 连接的远程主机”。我相信答案是“不,该信息在客户端不可用,但是......”。其他答案都没有解释如何做到这一点(Forge 是关于设置一个单独的 SSL 堆栈,而不是检查浏览器的 SSL 堆栈或证书)。
    • @MaxRied,还请注意perfectly fine 表示某事是不可能的。我没有这么说的原因是我希望额外的上下文有用并详细说明我的观点。
    【解决方案5】:

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

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

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

    【讨论】:

    • 感谢您的搜索。 nginx webserver 信息适用于客户端证书,用于通过 web 应用程序对用户进行身份验证。我有兴趣获取有关客户端浏览器上使用的 CA 证书的信息——用于验证浏览器正在访问的网站的 CA 证书。
    【解决方案6】:

    实际上,这几乎没有用——为什么您需要在已呈现的单个页面上从 JavaScript 中了解证书信息?

    • 如果它不受信任,那么显然您的代码也可能被更改过,因此它也不能被信任。

    • 如果证书实际上是受信任的,那么您如何能够将这种情况与证书不受信任的情况区分开来,但您的代码已通过中间人攻击被修改为不这样认为?

    因此,检查证书仅在 Browser Extensions(假定为受信任的代码)中而不是在单个页面中的脚本中有用 他们自己。扩展使用的这种接口是特定于浏览器的,并不是所有的浏览器都提供它。例如,虽然 Mozilla 浏览器确实允许您查看证书(提供像 EFF SSL Observatory 这样的扩展名),但 Chromium is still lacking

    【讨论】:

    • 这里有一个场景:公司中存在一个代理,用于捕获所有流量。代理使用自签名证书拦截 TLS 流量。自签名证书安装在公司的每台计算机上。浏览器不会报告任何问题。当被多个网站返回时,该公司可能只是捕获流量,并且可能没有资源来重写执行 MitM 检测的 JavaScript。
    • @MaxRied,仅仅因为没有解决方案而给出 -1,并且答案明确指出(并解释了为什么会这样)并不公平,尤其是当所有其他答案基本上都是无论如何“不”。
    • " 实际上,这没什么用——为什么您需要在已经呈现的单个页面上从 JavaScript 中知道证书信息?":这不是“否”,而是“否” ,而你的问题是错误的!为什么有人会问这种荒谬的事情?!”。
    • @MaxRied,理解这个问题意味着已经完成了一半。软件工程领域有很多荒谬之处。给一个坦率的答案打点 -1 点 i 并穿过 t 是不公平的。
    • 这是纵深防御。
    猜你喜欢
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多