Why does an Insecure gRPC server still allow connections from secured clients - node.js

I can't seem to understand what's happening behind the scene, but any guidance will really be appreciated.
I have the following grpc server that is hosted on Google Cloud Run:
server.js
server.bindAsync(`0.0.0.0:${process.env.PORT}`, grpc.ServerCredentials.createInsecure(), () => { //Notice, this is insecure
server.start();
console.log('GRPC Service Started');
});
Then I was given a service url of the form:
https://test-service-abcdefghij-ue.a.run.app
Then below is a client that connects to the above server using the following code:
client.js
... new test_proto.TestAccount("test-service-abcdefghij-ue.a.run.app", grpc.credentials.createSsl()); //Notice I used createSsl instead of createInsecure()
As you can see from my client code, I used createSsl without passing a self signed certificate, yet the connection to the createInsecure server worked.
I always thought both server and client must provide same self-signed certificates.
So, why does this still work even though the server is configured to be insecure? Does it mean data will still be transmitted in plain text regardless?

Based on comments from #John Hanley posting the answer, Cloud Run does not support client SSL certificates. The client verifies the server's SSL certificate. If a client connects to a Cloud Run service using HTTP (insecure), Cloud Run will redirect the client to an HTTPS endpoint. That means the final connection is encrypted with symmetric encryption. However, encryption alone does not mean a connection is secure. Google Cloud Run also supports IAP to authorize a user's access. In other words, a secure connection requires encryption and authorization.
You can have a look at documentation.

Related

Is it safe to host a client certificate and a key on a node server with heroku

I am tying to connect to a secure api that requires a client ssl certificate and a key. The remote api gave me both of them and I'm able to connect to this api with postman without any issues.
Now, I have a node.js server hosted on Heroku and I need to send the client certificate and key with each request.
My question is how do I host this client certificate and key safely? In some kind of a folder (doesn't sound safe)? do I need heroku to host them for me for security reasons?
For the sake of the question I already host them in a regular folder and can perform my requests easily.
I'm new to SSl but do implementing this suggested solution is what I need?
https://devcenter.heroku.com/articles/ssl#manually-upload-certificates.
This Heroku docs talk about making the server a secure endpoint for users so it isn't relevant for me as my understanding goes- https://devcenter.heroku.com/articles/ssl-endpoint#ssl-file-types.
I got my answer by getting help from the Heroku support and by understanding better how to work with client certificate.
Eventually I have used environment variables to store the key and the certificate as a string.
Heroku support environment variables through their CLI and server setting.
Most answers online talking about receiving the certificate, my issue was where to store them to be sent to a remote secure API.
I hope somebody, will be able to use this answer.

How to stop handshaking and data sharing, if the server does not REQUEST for client certificate in two way SSL authentication in python3?

I am using pyhthon3 requests library and want to request some resources from the server using HTTPS. So I use two way SSL authentication, and I have configured the server in a way which do not REQUEST for client certificate in response of 'client Hello' request.
As You can see IP xxx.xx.xxx.100 is the client and IP xxx.xx.xxx.207 is the server. So when the client sends 'Client Hello' to the sever, in response the server does not REQUEST for the client certificate, even though its two way SSL authentication.
So as per my requirements, how can I stop the process of handshaking and data sharing immediately in such case? Or how to force the server to REQUEST for client certificate?
... even though its two way SSL authentication.
It's not. Just because the client has the certificate to do mutual authentication, does not mean that this certificate is actually used. It is only mutual authentication if the server actually requests it using a CertificateRequest (which is clearly not done) and the client then providing the requested certificate.
... how can I stop the process of handshaking and data sharing immediately in such case?
You can't. There is no API for this.
And I'm not sure what kind of sense such a requirement would make. The client has successfully authenticated the server which should be all needed by the client to exchange data with the server. The server instead might want to know who the client is before sending specific data. So authenticating the client before providing such data makes sense from a server perspective, but not from a client one. This would be like you refusing to drive a car if nobody is checking your drivers license.
Or how to force the server to REQUEST for client certificate?
This fully depends on the kind of server. Different servers need different configuration. For example with nginx see ssl_verify_client.

Axios Returning "net::ERR_CERT_AUTHORITY_INVALID"

Currently I have two systems:
A Vultr Server running An Express.js Backend and a Discord Bot (Self Certified SSL)
A Firebase App Running my React App.
The current way the app is set up is the react app is sending a request to the backend (The Express App) using Axios. When I use axios to try to hit an API endpoint on my express app, it returns in the console:
Failed to load resource: net::ERR_CERT_AUTHORITY_INVALID
How do I go about fixing this so I can be able to get the information from my Vultr app using Firebase without getting the Cert Invalid error? Is it Possible? Can I do it using HTTP on my VPS' IP Address while having HTTPS on Firebase? I saw the following circulating but it has not worked:
const instance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false
})
});
The error message is just telling you that your certificate is untrusted.
You've got two choices: trust or ignore
Blindly ignoring ssl errors is very very bad, makes you succetible to man in the middle attacks. The way certificates work is that they delegate their 'trust' to a parent until you reach a CA (Certificate Authority). Let's say you buy a certificate from godaddy, they sign your certificate, so when someone is trying to see if your certificate is valid, they go to godaddy's CA, get the public key and check if your is valid.
If you self sign a certificate there's no CA, hence, no way of trusting it. Unless you explicitly add it to the ca bundle file in your operating system.
Self signed certificates beat no certificates at all, and manually trusting it beats ignoring ssl errors. But, it's a bit of work to catch on with the concepts but it becomes easier with time. If your app is meant for a hobby, ignore away.
Trusting
To trust globally, you would have to get your certificate and add it to the ca trust bundle, which requires you to have access to the OS and admin privileges, which is the casa for your vultr app but not for firebase.
In firebase's case you'd have to fetch the certificates public key and pass it as an argument to axios
here's how
Ignoring
here's how

Can I use Client Certificates on Azure App Services without a custom domain?

For testing purposes I would like to enable the 'Incoming Client Certificates' option in my Azure App Service (running a WCF webservice), and see if my Client application can still connect to the webservice. Since I am still in a testing phase, my app service still has the .azurewebsites.net domain name.
However, I can't seem to figure out how to get a proper client certificate that the server will accept (without switching to a custom domain name, which I know will work).
Currently, I see 2 possible routes to a solution:
Somehow get my hands on .cer that is signed by a CA trusted by the App Service server.
Generate a self-signed .pfx and .cer with my own self-signed CA. Import the pfx on the App Service and install the .cer on the client.
Both directions have not yielded any success so far. Does anyone have any experience with this?
Per my understanding, the client certificate is used by client systems to make authenticated requests to a remote server. In this case, your webservice is the remote server in a C/S mode. As you point out, "validating this certificate is the responsibility of the web app. So this means that any certificate will be valid as long as you don't validate anything". It does not effect on whether you have a custom domain or not in your web app service.
If you want to use client cert authentication with Azure app, you can refer to How To Configure TLS Mutual Authentication for Web App.
If the server has requested client certificate in its server hello and the client cert has signing capability, then it is expected to send the CertificateVerify message to the server. It contains signed hash of all messages from Client Hello till that point which are buffered on the server side. The server TLS layer will decrypt this using the client public key (which is in the Client certificate received earlier) and compare with its calculated hash. It will call back to application layer if this fails.
The application needs to handle it at that point and return its own error or continue with the session. https://www.rfc-editor.org/rfc/rfc5246#section-7.4.8
One example of this with Wolfssl library is https://github.com/wolfSSL/wolfssl/blob/14ef517b6113033c5fc7506a9da100e5e341bfd4/wrapper/CSharp/wolfSSL-Example-IOCallbacks/wolfSSL-Example-IOCallbacks.cs#L145

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