What key do browsers use to encrypt HTTPS requests to preloaded HSTS sites? - https

As far as I know, HTTPS requests are regular HTTP requests encrypted with the public key provided by the server during the initial handshake.
I have been reading about HSTS but have not been able to find anything related to the public key of sites that are in preloaded HSTS lists. Are the public keys of these sites also preloaded? Or is this key sent by the server on initial handshake like in any HTTPS request?

is this key sent by the server on initial handshake like in any HTTPS request?
Yes. HSTS just says “always use HTTPS for this domain so automatically correct any http:// calls to https:// before it is sent”.
It says nothing about how that HTTPS connection is set up, which is done through the usual manner.

Related

CORS with client https certificates

I have a site with two https servers. One (frontend) serves up a UI made of static pages. The other (backend) serves up a microservice. Both of them happen to be using the same (test) X509 certificate to identify themselves. Individually, I can connect to them both over https requiring the client certificate "tester".
We were hiding CORS issues until now by going through an nginx setup that makes the frontend and backend appear that they are same Origin. I have implemented the headers 'Access-Control-Allow-Origin', 'Access-Control-Allow-Credentials' for all requests; with methods, headers for preflight check requests (OPTIONS).
In Chrome, cross-site like this works just fine. I can see that front-end URLs and backend URLs are different sites. I see the OPTIONS requests being made before backend requests are made.
Even though Chrome doesn't seem to need it, I did find the xmlhttprequest object that will be used to perform the request and did a xhr.withCredentials = true on it, because that seems to be what fetch.js does under the hood when it gets "credentials":"include". I noticed that there is an xhr.setRequestHeader function available that I might need to use to make Firefox happy.
Firefox behaves identically for the UI calls. But for all backend calls, I get a 405. When it does this, there is no network connection being made to the server. The browser just decided that this is a 405 without executing any https request. Even though this is different behavior from Chrome, it kind of makes sense. Both the front-end UI and backend service need a client certificate to be chosen. I chose the certificate "tester" when I connected to the UI. When it goes to make a backend request, it could assume that the same client certificate should be used to reach the back-end. But maybe it assumes that it could be different, and there is something else I need to tell Firefox.
Is anybody here using CORS in combination with 2 way SSL certificates like this, and had this Firefox problem and fixed it somewhere. I suspect that it's not a server-side fix, but something that the client needs to do.
Edit: see the answer here: https://stackoverflow.com/a/74744206/537554
I haven't actually tested this using client certificates, but I seem to recall that Firefox will not send credentials if Access-Control-Allow-Origin is set to the * wildcard instead of an actual domain. See this page on MDN.
Also there's an issue with Firefox sending a CORS request to a server that expects the client certificate to be presented in the TLS handshake. Basically, Firefox will not send the certificate during the preflight, creating a chicken and the egg problem. See this bug on bugzilla.
When using CORS with credentials (basic auth, cookies, client certificate, etc.):
Access-Control-Allow-Credentials must be true
Access-Control-Allow-Origin must not be *
Access-Control-Allow-Origin must not be multi-value (neither duplicated nor comma-delimited)
Access-Control-Allow-Origin must be set to exactly the value from the request's Origin header in order for the request to work (either hard-coded that way or if it passes a whitelist of allowed values)
The preflight OPTIONS request must not require credentials (including the client certificate). Part of the purpose of the preflight is to ask what is allowed in a CORS request, and therefore sending credentials before knowing if they are allowed is incorrect.
The preflight OPTIONS request must return a 200-level response, generally 204
Note: For Access-Control-Allow-Origin, you may want to consider allowing the value null since redirect chains (like the ones typically used for OAuth) can cause that Origin value in a request from a browser.

HTTPS and HTTP CORS

My questions is simple, but I cannot find an answer and I haven't got any resources to test it myself.
Can I make HTTPS CORS request from one domain to another HTTPS domain?
Can I make HTTP CORS request from one domain to another HTTPS domain?
I know that I can do HTTP CORS request from one domain to another HTTP domain, but I don't know if there is any difference when I use HTTPS.
Yes you can do a CORS request from a HTTPS domain to another HTTPS domain.
The only difference is because HTTPS is a secure origin, you can only make call to secure origin, so not to HTTP, the browser will block it with a message like:
Mixed Content: The page at 'https://example.com/index.html' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example2.com/endpoint'. This request has been blocked; the content must be served over HTTPS.
Warning: If you allow http requests to call your https webpage, it will be insecure because it means an attacker can force requests to your https webpage with the cookies of a victim and read the answer
Beware if you still need to support IE8/IE9 and are using XDomainRequest as it does not support cross-protocol requests. As per MDN:
The origin's security protocol must match that of the requested URL. (http to http, https to https). If these do not match, the request will error "Access is Denied".

GSA - enable optional HTTPS?

Is there a way on a Google Search Appliance to enable optional https?
Under settings, under the heading Force secure connections when serving the options are:
No.
Use HTTPS when serving secure results, but not when serving public results.
Use HTTPS when serving both public and secure results.
I don't want to Force secure connections though, I want them to be optional.
ie, if someone requests the site as HTTP it serves as HTTP and if they request it as HTTPS it serves as HTTPS.
If I choose the 1st or 2nd options it accepts connections on HTTPS but immediately redirects to HTTP (ie, it forces HTTP). And the 3rd option forces HTTPS.
Is there any other settings that would enable it to accept HTTPS optionally?
You must install a valid ssl certificate or create a self-signed certificate. (Administration->SSL Settings)
In SSL Settings->Other Settings->"Force secure connections when serving?" you must select either: 'a' or 'b'
a. "Use HTTPS when serving secure results, but not when serving public
results."
b. "Use HTTPS when serving both public and secure results."
Unless all requests are coming from https, chances are you will select 'a'.
If 'b' is selected, you will receive an "unknown error" if sending query over standard http.
Now here's the major caveat:
Your observation that https still redirects to http, even with 'a' selected, is correct. The only method that I am aware of to force SSL when serving results with option 'a' is to send the additional 'access' query parameter '&access=a'
'a'=all
'p'=public (default)
https://www.google.com/support/enterprise/static/gsa/docs/admin/72/gsa_doc_set/xml_reference/request_format.html#1087053
BEWARNED: Depending on how your GSA is configured, there may be privacy implications if your organization maintains public collections containing private urls requiring authentication. URLS that require auth will be served right along with the rest of your results.
Changing the settings you mention to "No" will cause the GSA to use whatever protocol you started the experience with to be used.
Choosing the other options will cause the GSA to switch protocols.
Edit - It looks like this not possible. It doesn't matter what you request, the GSA will redirect based on the config.
If you create an SSL certificate for your GSA's host name and install the valid SSL certificate then it should serve results on port 443 (HTTPS) correctly.
i.e. if your GSA is "search.mydomain.com" then create a properly signed SSL certificate in that name and install to the GSA.
Typically this works without a certificate but the browser will show a warning message due to no SSL certificate / invalid SSL certificate.

Ensure WebSockets only connecting from known domain

How can I make sure only a script hosted on a specific list of domains is allowed to connect to my WebSocket application?
Or to prevent opinion based closevotes, is there a state-of-the-art or native way?
I do not intend to implement user authentication.
The mechanism for this with WebSocket is the origin header.
This HTTP header is set by browsers to the domain of the host that served the HTML that contained the JavaScript which opened the WebSocket connection.
A WebSocket server can inspect the origin header during the initial opening handshake of the WebSocket protocol. The server can then only allow proceeding of the connection if the origin matches a known whitelist.
The header cannot be modified from JavaScript, and all browsers are required by the RFC6455 specification to include it.
Caution: a non-browser WebSocket client can of course fake the origin header to any value it likes.
#oberstet gave you the right answer.
If you are worried about bots or programmatic HTTP agents, then you are going to have a bad time. Everything in a HTTP request can be spoofed. Your only option is to use cookies to attach a token with limited time validity that certify the user went through an allowed website to get that script. Get that cookie in the WebSocket handshake and decide if you allow it or not.
E.g.: When a user visit your site, or one of your sites, return a cookie with a symmetrically encrypted token based on the user IP address, User-Agent header, and Origin header; when the user initiates a WebSocket connection, if it is in the same 2nd domain, it will send the cookie, then if the data adds up allow the connection, otherwise, reject it. If the WS is in another domain, then you will have to forget about cookies and rely on a web socket message once the connection is established to check the validity of the connection.

Etags and last-modified over https SSL?

Is it possible to use HTTP caching for conditional GET requests over a secure HTTPS connection? I've got caching working over non-secure HTTP, but when I switch to HTTPS the browser stops sending if-none-match and if-modified-since headers, so the caching breaks. I've tried various Cache-Control settings like public, max-age=3600 and whatnot, no dice.
This happens in both Safari and Chrome, so I'm assuming the SSL is breaking it somehow. Is caching not allowed over SSL?
And just to be clear, the server is indeed properly setting the etag and last-modified headers, but the browser is not sending if-none-match and if-modified-since in the request, according to the Chrome developer tools.
Thanks for your help.
Figured it out! Turns out you have to have a trusted certificate. I was using my self-signed test certificate for SSL HTTPS. Adding it to my keychain and turning it green made the caching work.

Resources