Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

also validate certificates for embedded content that goes to a different domain #14

Open
danwent opened this issue Nov 7, 2010 · 7 comments

Comments

@danwent
Copy link
Owner

danwent commented Nov 7, 2010

reported by: tz [email protected]

I have a problem since I've disabled most CAs - perspectives will work
for actual web pages, but not other content, e.g. on the page
www.xyz.com, if there is a different "images.xyz.com" which has images
or javascript or whatever but is NOT a page, I get a certificate error
which perspectives cannot bypass (unless I manually type in the URL to
go to the top - I might get a 404, but the SSL will go through and get
perspectives to verify things).

@danwent
Copy link
Owner Author

danwent commented Nov 7, 2010

The current code hooks into the nsIWebProgressListener interface,
which seems to only be called on actions related to contacting the
site shown in the URL bar. You can find this code in
plugin/chrome/content/notaries.js . Look for the notaryListener
attribute of the class. At this level, we get some idea that the page
includes insecure content (because the browser.securityUI.state flags
have Perspectives.state.STATE_IS_BROKEN set), but I do not believe you
have the ability to validate and trust any such connections. Note:
STATE_IS_BROKEN seems to be what Firefox uses to set the 'mixed
content' error icon in the UI.

It seems we need to be able to find a lower-level interface that is
called for each embedded item on the page. An ancient link
(https://developer.mozilla.org/en/Firefox_1.5_for_developers) mentions
the following:

Certificate prompts can now be overridden on a per-channel basis. This
works by setting an interface requestor as an nsIChannel's
notificationCallbacks and giving out an interface for
nsIBadCertListener.

Other extensions (e.g., firebug) must already do something along these
lines. For example, I suspect we'd be able to catch bad certificate by
listening on a per-channel basis similar to how firebug listens on a
per-channel basis for each embedded request:
http://code.google.com/p/fbug/source/browse/branches/firebug1.7/modules/firebug-channel-listener.js
.

Sometimes poking through the mozilla source using mxr.mozilla.org is
useful here.

In addition to figuring out how to hook into these requests, we would
likely have to change certain things about the perspectives UI, since
a single page could have multiple certificates, each of which would
require a separate key graph, etc. Those changes probably wouldn't be
too tough.

@tz1
Copy link

tz1 commented Nov 7, 2010

It is actually worse than that - here at github. They insist on using a dozen subsites - gist.github.com, assetsN.github.com (N=1,2,3 so far), etc. I type https://assets1.github.com and get the error page but perspectives won't automatically bypass it (though clicking on the perspectives icon says it has seen the cert for the last few days). login redirects to gist.github.com, also not automatically overridden. I've manually inserted exceptions for these.

@Tie-fighter
Copy link

up :)

@Tie-fighter
Copy link

Certificate Patrol works with embedded content. http://patrol.psyced.org/
Maybe their source code gives a good hint at how to do this properly.

@ghost
Copy link

ghost commented Jun 14, 2014

I implemented a first draft for embedded content support. You can find the fork here: https://github.com/lambdor/Perspectives/tree/embedded_content

Most important question:
_How do you restart a single request for embedded content or just delay it long enough until the Perspectives servers have been queried?_
see MDN Setting_HTTP_request_headers, MDN nsIHttpChannel and MDN nsIChannel.

Usage:
In about:config you have to set security.ssl.enable_ocsp_stapling to false, otherwise embedded content may silently fail with "sec_error_ocsp_invalid_signing_cert" (see https://bugzilla.mozilla.org/show_bug.cgi?id=971750). The embedded contents are checked on page load and their security exceptions are overriden but not yet restarted again. Therefore you may have to reload the page to see the successful overrides. To actually see some effect delete all your CA certs: go to Perspectives -> View Certificate Store and delete all Authorities (tedious). Then try https://www.github.com for example which embeds stylesheets from https://assets-cdn.github.com. You should either see an unstyled page (=embedded content is not supported or not yet overriden) or a fully styled page (=success). If the page is unstyled try to reload the page once more.

How it works:
To retrieve all embedded content URIs we have to register a httpRequestObserver. This is done in initNotaries(). The observe() code is similar to updateStatus() except that "security_state" is always assumed STATE_IS_SECURE(!). I don't know how to retrieve the actual security_state for embedded content. Calling "subject.QueryInterface(Ci.nsIChannel).securityInfo" always returns null for me? But security_state can only take the values SECURE, BROKEN ("some content was received over an insecure channel") and INSECURE (see https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIWebProgressListener). Thus if we probe for HTTPS it should be save to exclude STATE_IS_INSECURE? And if "mixed content" is handled in this very procedure then STATE_IS_BROKEN can also be excluded? Which only leaves STATE_IS_SECURE.

After all the notary queries in observe() are completed process_results_embedded() is called. The embedded-procedure is a very simplified version of process_notary_results() (now named process_results_main()), because we can ignore all the different cases which handle notification updates. Whereas process_results_main() reloads the current tab, process_results_embedded() just silently overrides the security exception for now, but doesn't do any reloading, so you don't see any effect until you reload the page.

Querying for embedded content requires the main page fully loaded which again may depend on the users configuration (existing CA certs, existing security overrides). I outlined those conditions in the following decision table:

condition
certificate exists 0 0 0 0 0 0 1 1 1 1 1 1
is_whitelisted_by_user (main page) 0 0 0 1 1 1 0 0 0 1 1 1
ask before contacting notaries 0 1 1 0 1 1 0 1 1 0 1 1
has_user_permission (main page) - 0 1 - 0 1 - 0 1 - 0 1
result
query main 1 0 1 - - - 1 0 1 - - -
loads page and requests embedded 0 0 0 1 1 1 1 1 1 1 1 1
query embedded - - 1' 1 1" 1'" 1 1" 1'" 1 1" 1'"

') This should happen once the main page has been reloaded again triggered by Perspectives.
") Set to "true" for now until we know how to restart a request. Embedded content should actually respect the user's probing permission of course. Setting this to "false" right now would require two page reloads however.
'") Set to "true" for now until we know how to restart a request. Querying has to be held back until the user is giving permission for the main page. Setting this to "false" would require a manual page reload right now.

Doing a full page reload once all embedded content requests are finished doesn't work for pages with dynamic requests (AJAX, adding new header nodes etc.).

Tell me what you think!

@ghost
Copy link

ghost commented Jun 14, 2014

Related to #20

@daveschaefer
Copy link
Collaborator

Hi @lambdor , thank you very much for sending the patch! I have some important real life deadlines coming up but I will review this as soon as I can.

I may have to fix #123 before looking at this so the existing extension will continue to function when Firefox releases their next update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants