secure websocket (wss) on localhost - web

My Qt-based application uses an insecure websocket on localhost (ws://localhost:50050) in order to connect to a web browser. This works fine on most platforms, however, some web browsers (e.g. Safari) and anything on iOS require a secure websocket (wss://localhost:50050) and this in turn requires the app to contain a valid certificate. Since certificates for localhost cannot be issued the general recommendation is to use a self-signed certificate and I followed the instructions according to:
https://letsencrypt.org/docs/certificates-for-localhost
and tested it with the standard Qt example app:
https://www.soundjack.eu/Downloads/sslechoserver.zip
However, this fails and now I wonder if current browser do not accept self-signed certificates anymore or if the the certificate must be created differently or if there is an alternative to this approach.

Related

Browser does not prompt for client certificate when deployed on port 443

I have run into a very strange situation.
I am developing a web application that requires client certificate authentication.
Whenever I deploy the application on the default HTTPS port 443 the browser does not prompt me for a client certificate, web application does not see any certificate being provided and thus flags the request as unauthorized.
Verified to work as expected
In the following situations the browser prompts for a client certificate to be attached and authentication works a expected.
Deployed at https://localhost:8443/
Local computer with a self-signed SSL certificate that has been manually entrusted.
Deployed at https://test.mydomain.com:8443/
Remote instance with valid SSL certificate provided from Let's encrypt.
The above scenario has also been verified to work as expected if I launch the web application with the sudo command to outrule that it causes the issue in the below scenario.
Situations when it does not work
Deployed at https://localhost/
Deployed at https://test.mydomain.com/
Verified the following
Everything is 100% intact in terms of configuration, the only change I apply is changing the port number from 8443 to 443.
Verified on multiple browsers, Chrome, Firefox and Safari. Behavior is consistent for all browsers and in all scenarios.
Cleared any caches, cookies, session variables and also inspected that no HTTP Authorization header is sent in the request.
Verified that the exact same truststore is loaded by the web application in all scenarios.
What could be triggering this behavior and what other tools/debug can I use to further understand what is going on?

Protecting mobile app from man-in-the-middle attack

We are working on a mobile app that communicates with the backend through REST API over SSL. Mobile device executes cert validation on the API call (using standard libraries in mobile frameworks).
If we try to connect the mobile device through proxy (such as Charles), we see all the traffic, but it is encrypted - as expected.
However, if I enable SSL proxy, generate root certificate and install that cert on my device, I will see all the data in clear text through Charles - again, as expected.
The question is, how to prevent this?
The main target, of course, is to expose data ONLY if device calls allowed server with a valid certificate for that server.
Off hand the only way to prevent such a thing if the attacker has that level of access to the device would be to use SSL thumb printing. You would initiate a connection to the server. Retrieve the SSL certificate and compare this to a hard coded value within the app code. If this does not match abort the connection and don't send the data.
The issue with this however is the overhead if the SSL updates. You would need to release an update to the app with a fresh thumbprint value. This would also stop people using the app until they updated to the latest version.
The only way to prevent this is through certificate pinning, but if the attacker is able to install a root certificate before you connect for the first time to your API, you can still be MiM'ed.

Secure websocket with custom domain to OpenShift app failed

I added a custom domain and custom certificate to my app.It seems that custom certificate is not provided when wss try to connect.
I tested http connection like https:// api.myapp.com, every thing is ok.
But if I try websocket like wss://api.myapp.com:8443, every thing is not ok.
chrome says:
failed: WebSocket opening handshake was canceled
a test tool github.com/wtmmac/websocket-tester says:
websocket.Dial wss://api.myapp.com:8443: x509: certificate is valid for *.rhcloud.com, rhcloud.com, not api.myapp.com
Is there some additional configs needed after alias-update-cert, if want to use secure websocket with custom domain?
OpenShift Online does not currently support the ability to use a Custom SSL Certificate with secure web sockets. If you would like to use wss I would suggest that you use the app-domain.rhcloud.com address that is provided for you by OpenShift.

Setting up secure web sockets (wss) service for my https web app

I have this web app that is served via https, and now it needs to use a websocket service that is served from another server. Chrome, Firefox and Internet Explorer complain right away that if the application is secure (https), then it is not allowed to connect to an insecure websocket service (ws:// URI). Strangely, Apple Safari doesn't complain so.
Well, fair enough, I assumed any globally trusted certificate would be fine to be installed at the websocket server side, to enable secure service (wss:// URI). However the company that maintains the socket server claims that they have to install there the very same certificate that secures my web application. I read in webs that the wss will not run with self-signed certificate, but nowhere that it must be the same certificate that the calling web site runs on.
Since we are talking sharing a certificate key file with 3rd party, I wanted to double check this. If my secure site runs at domain first.com, and the websocket server at IP address a.b.c.d, what kind of certificate should be installed on the websocket server to enable the communication? On one hand, that would be a kind of cross-site scripting, but perhaps the browser security model allows it, assuming the user knows what they want?
What I understand from above, the browser connects to your web application and is then redirected to the other server. If that be the case, then browser would complain about being redirected to unsecured site from a secured URL. The way forward actually depends on the domain of the server that the redirect is happening to, for example, if your main site has URL form www.mainsite.com and the target site has URL form abc.secondsite.com or an IP, the second server must have configured an SSL certificate that has been issued to either abc.secondsite.com of the IP i.e. the name of the host requested must match exactly with the SSL ceritficate that is provided by the secondsite.
The secondsite technically does not have to have the same certificate as your mainsite, it just have to be a certificate issued by a trusted source (like Verisign etc.).
On the other hand, if you have a wildcard subdomain certificate i.e. a certificate issues is valid for all the *.mainsite.com domains and the URL form of the secondsite is sub_domain.mainsite.com, then the same certificate can be used on both the servers.
Hope this helps.
thanks
Since we are talking sharing a certificate key file with 3rd party, I
wanted to double check this. If my secure site runs at domain
first.com, and the websocket server at IP address a.b.c.d, what kind
of certificate should be installed on the websocket server to enable
the communication? On one hand, that would be a kind of cross-site
scripting, but perhaps the browser security model allows it, assuming
the user knows what they want?
You cannot provide a certificate for an IP address. In order to use WSS:// you need to connect to a domain name, and have a valid certificate for that domain name. So you need a SSL certificate for the domain name of your WebSocket server.
As far as I know, it does not need to be the same than the one on the site. You can check by entering here: http://vtortola.github.io/ng-terminal-emulator/ and executing the command websocket wss://echo.websocket.org, you will connect to a WebSocket in websocket.org that echoes your inputs.
WebSockets are not constrained by the SOP (Same Origin Policy), you can connect anywhere, and the server is responsible of checking the HTTP request header "Origin" and accept or refuse the connection.

How would I protect a private API

I am working on a REST API to be used by a mobile application I am writing, mostly for the purpose of communicating with a database.
The mobile application makes calls to URLs like this:
example.com/mobileapi/getinfo
And carries certain POST payload along with each call.
I'm not worried about user authentication etc.
However, what I am worried about is, if someone were to use the mobile application along with a network monitoring tool like Fiddler or Wireshark, they could document all the URLs being called, along with all the POST parameters. That would be enough information to create their own app that uses my API.
How can I prevent this? I considered hardcoding a Key into my application and have that included as a POST parameter with each request, but that would be visible as well.
What you want to do is employ mutually-authenticated SSL, so that your server will only accept incoming connections from your app and your app will only communicate with your server.
Here's the high-level approach. Create a self-signed server SSL certificate and deploy on your web server. If you're using Android, you can use the keytool included with the Android SDK for this purpose; if you're using another app platform, similar tools exist for them as well. Then create a self-signed client and deploy that within your application in a custom keystore included in your application as a resource (keytool will generate this as well). Configure the server to require client-side SSL authentication and to only accept the client certificate you generated. Configure the client to use that client-side certificate to identify itself and only accept the one server-side certificate you installed on your server for that part of it.
If someone/something other than your app attempts to connect to your server, the SSL connection will not be created, as the server will reject incoming SSL connections that do not present the client certificate that you have included in your app.
A step-by-step for this is a much longer answer than is warranted here. I would suggest doing this in stages as there are resources on the web about how to deal with self-signed SSL certificate in Android (I'm not as familiar with how to do this on other mobile platforms), both server and client side. There is also a complete walk-through in my book, Application Security for the Android Platform, published by O'Reilly.

Resources