I'm looking to implement a gRPC service in .net core, the client would also be in .net core running as a service. The client service will only be installed by my team and the installer package will not be available publicly (and wouldn't be much use to anyone else). I would like advice on whether call credentials (JWT bearer tokens) and/or channel credentials (client certs) would improve security, and if so how/why.
I know this question isn't about specific code, however it may well help determine how the service is coded, so if this is posted in the wrong place then please advise on the correct place.
The purpose of this service is only to receive information from clients, none of which is sensitive, mostly just health info of the endpoint. The server service will be using TLS with a LetsEncrypt certificate. As the connection will be encrypted the identity of the server should be ensured and no nefarious players should have visibility of the data transferred. The clients will only be sending data (to identify the endpoint) that contains a serial number generated by my team at the time of install, and if this somehow got duplicated the wrong data wouldn't really cause any issues or data breaches only that there would be some remediation work by a team member to correct the issue.
Because of these reasons, I can't see what benefit call or channel credentials would offer, especially channel credentials with the added overhead of maintaining client certificates for each client.
Can you offer any thoughts on this, or if there are any other security concerns I should consider?
Also, with this sort of set up, is there anyway a 3rd party could access the server service if they don't have the proto files?
Thanks
Related
Thanks for your help in advance.
I'm using React Native and Node.js to deliver a product for my company.
I've setup the steps on the backend to retrieve a password, validate it and respond with a token. The only problem is - the password I use on the front end (mobile app) to be validated by the back end is hardcoded.
My question is:
How should I securely store this password on the mobile app so that it can not be sniffed out by a hacker and used to compromise the backend?
My research so far.
Embedded in strings.xml
Hidden in Source Code
Hidden in BuildConfigs
Using Proguard
Disguised/Encrypted Strings
Hidden in Native Libraries
http://rammic.github.io/2015/07/28/hiding-secrets-in-android-apps/
These methods are basically useless because hackers can easily circumnavigate these methods of protection.
https://github.com/oblador/react-native-keychain
Although this may obfuscate keys, these still have to be hardcoded. Making these kind of useless, unless I'm missing something.
I could use a .env file
https://github.com/luggit/react-native-config
Again, I feel like the hacker can still view secret keys, even if they are saved in a .env
I want to be able to store keys in the app so that I can validate the user an allow them to access resources on the backend. However, I don't know what the best plan of action is to ensure user/business security.
What suggestions do you have to protect the world (react- native apps) from pesky hackers, when they're stealing keys and using them inappropriately?
Your Question
I've setup the steps on the backend to retrieve a password, validate it and respond with a token. The only problem is - the password I use on the front end (mobile app) to be validated by the back end is hardcoded.
My question is:
How should I securely store this password on the mobile app so that it can not be sniffed out by a hacker and used to compromise the backend?
The cruel truth is... you can't!!!
It seems that you already have done some extensive research on the subject, and in my opinion you mentioned one effective way of shipping your App with an embedded secret:
Hidden in Native Libraries
But as you also say:
These methods are basically useless because hackers can easily circumnavigate these methods of protection.
Some are useless and others make reverse engineer the secret from the mobile app a lot harder. As I wrote here, the approach of using the native interfaces to hide the secret will require expertise to reverse engineer it, but then if is hard to reverse engineer the binary you can always resort to a man in the middle (MitM) attack to steel the secret, as I show here for retrieving a secret that is hidden in the mobile app binary with the use of the native interfaces, JNI/NDK.
To protect your mobile app from a MitM you can employ Certificate Pinning:
Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host. If more than one certificate or public key is acceptable, then the program holds a pinset (taking from Jon Larimer and Kenny Root Google I/O talk). In this case, the advertised identity must match one of the elements in the pinset.
You can read this series of react native articles that show you how to apply certificate pinning to protect the communication channel between your mobile app and the API server.
If you don't know yet certificcate pinning can also be bypassed by using tools like Frida or xPosed.
Frida
Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.
xPosed
Xposed is a framework for modules that can change the behavior of the system and apps without touching any APKs. That's great because it means that modules can work for different versions and even ROMs without any changes (as long as the original code was not changed too much). It's also easy to undo.
So now you may be wondering how can I protect from certificate pinning bypass?
Well is not easy, but is possible, by using a mobile app attestation solution.
Before we go further on it, I would like to clarify first a common misconception among developers, regarding WHO and WHAT is accessing the API server.
The Difference Between WHO and WHAT is Accessing the API Server
To better understand the differences between the WHO and the WHAT are accessing an API server, let’s use this picture:
The Intended Communication Channel represents the mobile app being used as you expected, by a legit user without any malicious intentions, using an untampered version of the mobile app, and communicating directly with the API server without being man in the middle attacked.
The actual channel may represent several different scenarios, like a legit user with malicious intentions that may be using a repackaged version of the mobile app, a hacker using the genuine version of the mobile app, while man in the middle attacking it, to understand how the communication between the mobile app and the API server is being done in order to be able to automate attacks against your API. Many other scenarios are possible, but we will not enumerate each one here.
I hope that by now you may already have a clue why the WHO and the WHAT are not the same, but if not it will become clear in a moment.
The WHO is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
OAUTH
Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.
OpenID Connect
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
While user authentication may let the API server know WHO is using the API, it cannot guarantee that the requests have originated from WHAT you expect, the original version of the mobile app.
Now we need a way to identify WHAT is calling the API server, and here things become more tricky than most developers may think. The WHAT is the thing making the request to the API server. Is it really a genuine instance of the mobile app, or is a bot, an automated script or an attacker manually poking around with the API server, using a tool like Postman?
For your surprise you may end up discovering that It can be one of the legit users using a repackaged version of the mobile app or an automated script that is trying to gamify and take advantage of the service provided by the application.
Well, to identify the WHAT, developers tend to resort to an API key that usually they hard-code in the code of their mobile app. Some developers go the extra mile and compute the key at run-time in the mobile app, thus it becomes a runtime secret as opposed to the former approach when a static secret is embedded in the code.
The above write-up was extracted from an article I wrote, entitled WHY DOES YOUR MOBILE APP NEED AN API KEY?, and that you can read in full here, that is the first article in a series of articles about API keys.
Mobile App Attestation
The use of a Mobile App Attestation solution will enable the API server to know WHAT is sending the requests, thus allowing to respond only to requests from a genuine mobile app while rejecting all other requests from unsafe sources.
The role of a Mobile App Attestation service is to guarantee at run-time that your mobile app was not tampered, is not running in a rooted device and is not being the target of a MitM attack. This is done by running a SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device is running on. The cloud service also verifies that the TLS certificate provided to the mobile app on the handshake with the API server is indeed the same in use by the original and genuine API server for the mobile app, not one from a MitM attack.
On successful attestation of the mobile app integrity a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud are aware. In the case of failure on the mobile app attestation the JWT token is signed with a secret that the API server does not know.
Now the App must sent with every API call the JWT token in the headers of the request. This will allow the API server to only serve requests when it can verify the signature and expiration time in the JWT token and refuse them when it fails the verification.
Once the secret used by the Mobile App Attestation service is not known by the mobile app, is not possible to reverse engineer it at run-time even when the App is tampered, running in a rooted device or communicating over a connection that is being the target of a Man in the Middle Attack.
So this solution works in a positive detection model without false positives, thus not blocking legit users while keeping the bad guys at bays.
What suggestions do you have to protect the world (react- native apps) from pesky hackers, when they're stealing keys and using them inappropriately?
I think you should relaly go with a mobile app attestation solution, that you can roll in your own if you have the expertise for it, or you can use a solution that already exists as a SAAS solution at Approov(I work here), that provides SDKs for several platforms, including iOS, Android, React Native and others. The integration will also need a small check in the API server code to verify the JWT token issued by the cloud service. This check is necessary for the API server to be able to decide what requests to serve and what ones to deny.
Summary
I want to be able to store keys in the app so that I can validate the user an allow them to access resources on the backend. However, I don't know what the best plan of action is to ensure user/business security.
Don't go down this route of storing keys in the mobile app, because as you already know, by your extensive research, they can be bypassed.
Instead use a mobile attestation solution in conjunction with OAUTH2 or OpenID connect, that you can bind with the mobile app attestation token. An example of this token binding can be found in this article for the check of the custom payload claim in the endpoint /forms.
Going the Extra Mile
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
I have a .net WEB API publicly exposed and also a Xamarin Forms App which uses the API, the app needs to be extremely secure due to the data it manages.
I will create an HTTP Certificate for the WEB API.
The Xamarin Forms app will have a login/password to validate against a local Active Directory. via a /token endpoint, and using an Authorize attribute on all endpoints to assure that every HTTP call has the bearer token in it, I implemented that using this:
I based my implementation on this one:
http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
Additionally the customer has asked us for Client Certificate Authentication, I dont understand how this totally works.
1. I need to add a certificate to the Xamarin Project, right? How do I Add it? How do I generate it?
2. In the Web API I need to validate each http call has the certificate attached.
I found this but not sure if it will work:
http://www.razibinrais.com/secure-web-api-with-client-certificate/
However when investigating this, I also found something about certificate pinning, which is basically security but the other way around, it means the Xamarin APP will validate if the server certificate is associated with the right server (or something like that), so there is no way of a MAN IN THE MIDDLE Attack.
I found how to implement it here:
https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin
Question is:
1. Do I need both ?
Something else that I should research for on this journey?
Certificate pinning and Client Certificate Authentication are 2 very different things. Certificate pinning makes sure your app is talking to the server it expects to talk to. It also prevents eavesdropping, which is known as a 'Man in the middle' attack. I just recently wrote an article about this on my blog.
Client Certificate Authentication works the other way around. It adds an extra layer of security so your server can be sure only clients that have the certificate can communicate successfully with it. However, since apps can be decompiled without a lot of effort, this client certificate can 'easily' be obtained by a malicious user. So this isn't a silver bullet.
From my experience, Client Certificate Authentication is often used in enterprise apps, when there is an Enterprise Mobility Management solution in place (eg. Mobile Iron or Microsoft Intune or others), where the EMM solution can push the certificates to the users device out of band.
Should you use both? That really depends on the requirements of your customer, since they mitigate 2 very different problems.
The Web API link you included looks like it should do the server job properly at first sight. This article also includes how to generate a client certificate with a Powershell command.
Generating a client side certificate:
Use the Powershell command in the article that you referenced in your question.
Otherwise, this gist might help you on your way.
Installation:
Add the certificate file to each platform specific project as a resource. This is usually done in the form of a .p12 file.
Usage:
That all depends on which HttpClient you are using.
If you use the provided Web API solution, you should add the certificate contents as a X-ARR-ClientCert header with each request.
I have a middleware server (A), under an Azure Web App role.
I'm using some SOAP service from a private server (B), a third party, that filters incoming IPs, so if my request IP is not registered in their firewall, I won't be able to access any information.
The middleware is not exclusive for (B) and a lot of other clients(C) request information from (A), including mobile devices (D).
I want to make sure that any request from (A) to (B) is accepted even if my current Request IP changes - and it will since the middleware is on the cloud and some changes are performed periodically -.
I had in mind a CSR certificate so that server (B) knows it's my Middleware (A), without caring for my request IP.
Is that idea a good choice?, am I missing something? are there any better solutions, recommendations?, I want to be able to connect (A) & (B) without affecting a lot (C) & (D).
Note: If the original idea works, where should I start to implement it, given the azure Web App constraints and private server ones?.
You seem to be asking how to authenticate to this private server (B). There are many ways to handle this. There is one big question...Do you have control over this private server?
If so, you have a slew of options; basic auth, cert auth, flavors of OAuth, etc. pick one. Make sure the transport is secure via SSL though.
You make it sounds like you don't have access, at which point you are at the mercy of this 3rd party. IP restrictions can be put in place to try to limit exposure when a authentication mechanism can't be added. I guess sometimes even both for those uber least-privilege types. If they have IP filters in place, it is likely those will be difficult to remove, especially if they have other consumers of this SOAP service.
Also, a CSR is only the start of a certificate creation. You can create on if you are going to use the Client Certificate auth option. Or if you need to purchase a cert to secure the transport your middleware services. However, it has nothing to do with authentication directly.
I'm trying to design a green-field project that will have several services (serving data) and web-applications (serving HTML). I've read about microservices and they look like good fit.
The problem I still have is how to implement SSO. I want the user to authenticate once and have access to all the different services and applications.
I can think of several approaches:
Add Identity service and application. Any service that has protected resources will talk to the Identity service to make sure the credentials it has are valid. If they are not it will redirect the user for authentication.
Use a web-standard such as OpenID and have each service handle it own identities. This means the user will have to authorize individually each service/application but after that it will be SSO.
I'll be happy to hear other ideas. If a specific PaaS (such as Heroku) has a proprietary solution that would also be acceptable.
While implementing a microservice architecture at my previous job we decided the best approach was in alignment with #1, Add identity service and authorize service access through it. In our case this was done with tokens. If a request came with an authorization token then we could verify that token with the identity service if it was the first call in the user's session with the service. Once the token had been validated then it was saved in the session so subsequent calls in the user's session did not have to make the additional call. You can also create a scheduled job if tokens need to be refreshed in that session.
In this situation we were authenticating with an OAuth 2.0 endpoint and the token was added to the HTTP header for calls to our domain. All of the services were routed from that domain so we could get the token from the HTTP header. Since we were all part of the same application ecosystem, the initial OAuth 2.0 authorization would list the application services that the user would be giving permission to for their account.
An addition to this approach was that the identity service would provide the proxy client library which would be added to the HTTP request filter chain and handle the authorization process to the service. The service would be configured to consume the proxy client library from the identity service. Since we were using Dropwizard this proxy would become a Dropwizard Module bootstrapping the filter into the running service process. This allowed for updates to the identity service that also had a complimentary client side update to be easily consumed by dependent services as long as the interface did not change significantly.
Our deployment architecture was spread across AWS Virtual Private Cloud (VPC) and our own company's data centers. The OAuth 2.0 authentication service was located in the company's data center while all of our application services were deployed to AWS VPC.
I hope the approach we took is helpful to your decision. Let me know if you have any other questions.
Chris Sterling explained standard authentication practice above and it makes absolute sense. I just want to put another thought here for some practical reasons.
We implemented authentication services and multiple other micro services relying on auth server in order to authorize resources. At some point we ran in to performance issues due to too many round trips to authentication server, we also had scalability issues for auth server as number of micro services increased. We changed the architecture little bit to avoid too many round trips.
Auth server will be contacted only once with credentials and it will generate the token based on a private key. Corresponding public key will be installed in each client (micro service server) which will be able to validate the authentication key with out contacting auth server. Key contain time generated and a client utility installed in micro service will validity as well. Even though it was not standard implementation we have pretty good success with this model especially when all the micro services are internally hosted.
As part of strengthening session authentication security for a site that I am building, I am trying to compile a list of the best ways to register a user's computer as a second tier of validation - that is in addition to the standard username/password login, of course. Typical ways of registering a user's computer are by setting a cookie and or IP address validation. As prevalent as mobile computing is, IP mapping is less and less a reliable identifier. Security settings and internet security & system optimization software can make it difficult to keep a cookie in place for very long.
Are there any other methods that can be used for establishing a more reliable computer registration that doesn't require the user to add exceptions to the various cookie deleting software?
If you're looking to do device authentication, you may want to consider mutually authenticated SSL. Here, you'd deploy a client identity certificate to each endpoint you'd want to authenticate. Then, you set the server up to require client authentication, so that a client would need to present a valid identity certificate in order to form the SSL tunnel.
This, of course, is not a perfect solution. In reality, this presents much of the same weaknesses as other solutions (to various degrees) Once your client identity certificates go to your clients, they are out of your control; should a client give their certificate to anyone else, you lost the device authentication that you have based on it. SSL identity certificates are generally stored in a keystore on the client which is encrypted with a password or other credential needed to unlock them. While a client certificate could still be compromised, it's somewhat stronger that just a cookie or something like that (assuming you don't have a client that is trying to give away its credential). In addition, you'd want to come up with some validation routine that a client would need to go though in order to get a credential in the first place (how do I know that this is a client device that I want to remember/register?).
Remember, these types of approaches only do device authentication, not users. There are more in-depth schemes already developed for device authentication than what I've mentioned; for example, 802.1x is a network protocol where an endpoint needs to present a client-side certificate to the network switch to get on a LAN. This is out-of-scope for a web application scenario, like what you've described, but the idea is the same (put a cryptographic credential on the client and validate it to establish the connection).
This, like all other security matters really, is a risk decision. What are you trying to accomplish with such a countermeasure? What are the threats you're trying to prevent and what are the consequences if someone does log in on an unregistered device? Only your situation can answer those questions and let you see the real risk, if you need/should mitigate it, and, if so, how strong of a solution do you need to get the risk level down to an acceptable level?
the best ways to register a user's computer as a second tier of
validation
From my point of view this approach does not offer much in the aspect of authentication.
You are not authenticating a user and have no idea who is using the PC that you would accept as being registered.
The way you describe it, this step should be a configuration rule in the firewall to accept connections from specific IPs only.
IMO the filtering of the PCs is the responsibility of a firewall and it would be much better handled by the firewall than any application level filtering.
Just think that you would have the overhead in your application to examine each request and decide whether to accept it or not.
Better leave this preprocessing overhead to the firewall. That's why it is there.