Within a web browser, is it possible for JavaScript to obtain information about the HTTPS Certificate being used for the current page?

StackOverflow https://stackoverflow.com/questions/2402121

Question

Is there a method for JavaScript running in a browser to determine which CA certificate is being used to authenticate the remote host for the browser's current HTTPS connection, and also obtain properties of that certificate, such as the name of the CA?

If not, are there any other options for programatically obtaining this information, such as ActiveX, Java, CGI on the server side, ...?

Was it helpful?

Solution

You can use the opensource Forge project to do this. It implements SSL/TLS in JavaScript. You can make an ajax call to the server and use a callback to inspect the certificate. Keep in mind that the server is the one sending the JavaScript so this shouldn't be used to determine whether or not you trust the server the JavaScript is from. The Forge project does allow cross-domain requests, so if you are using this for trust, you can load the Forge JavaScript from a server you already trust and then contact the server you don't yet trust. However, unless that other server provides a cross-domain policy, you will not be able to perform the cross-domain request.

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

The blog links in the README provide more information on how Forge can be used and how it works.

OTHER TIPS

Copying my own answer from Is there any way to access certificate information from a Chrome Extension

2018 answer: yes, in Firefox 62

You'll need to make a WebExtension, which is also called a browser extension.

See accessing security information on MDN

You can also check out the docs for:

You'll need Firefox 62.

Here's a working 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>"
    ]
}

enter image description here

It also may be implemented in Chromium once this code is merged.

No. You could obviously do it with AJAX/ActiveX/Java/Flash/Silverlight and a custom server-side script, but I can't see why you would need this.


EDIT: The idea above is that you would make a network request (using one of the above technologies) to the server and ask what certificate was used for that network request. The server could then inspect its own configuration and answer the question.

If the browser is somehow trusting an invalid certificate and connecting to the wrong server (e.g. a MITM server), the server could lie. Once the browser's trust mechanism is compromised, I don't know how to avoid that.

As far as I know, there is no way (purely using client side APIs) to directly ask the browser what cert it's using "for the browser's current SSL connection". Even Forge doesn't do that. It creates an entirely parallel SSL session, but it doesn't let you ask about the browser's native SSL session.

JavaScript running in the web browser does not have access to the certificate information. The certificate information is also not passed through HTTP to the application. My research indicates that there is no way for the web application to determine if a man-in-the-middle attack has injected a bogus certificate somewhere between the host and client.

AFAIK not with Javascript alone. But some webservers allow you to access the connection parameters of the thread or process. A serverside script can then send those values along with the request and you use it.

I found this for nginx webserver: http://wiki.nginx.org/NginxHttpSslModule (Look at the bottom of the page for the variables). It should be possible to set them as environment variables and pass them to your FastCGI processes or whatever you use.

AOLServer/Naviserver allows similar access with the nsssl module.

In practical terms, this has little use -- why would you need to know certificate information from JavaScript on the individual page already rendered?

  • If it's not trusted, then obviously your code could have been altered, too, so, it cannot be trusted, either.

  • If the certificate is actually trusted, then how would you be able to distinguish the scenario from the one where the certificate is not trusted, but your code has been modified through a MitM attack to think otherwise?

So, checking certificates would only be useful from within Browser Extensions (which are presumed to be trusted code) as opposed to the scripts in the individual pages themselves. Such interface that extensions use is browser-specific, and not all browsers even provide it. For example, whereas Mozilla browsers do let you peek into the certificates (affording extensions like the EFF SSL Observatory), Chromium is still lacking.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top