HTTPS React app inside intranet still shows as untrusted - node.js

We have a Node.js application with React frontend for warehouse management. One of the features of the app is a real-time QR code reader (Which requires webcam access that is only available if the website is running under a secured connection).
This application is accessible only inside the intranet network (eg.: 192.168.157.12:80) and has no domain. I know after some research that the way is to obtain a self-signed certificate and I already did that successfully.
The problem is that it shows on the client-side as an "untrusted" certificate and require the user to confirm/bypass a bunch of warning to access the app - this is a no-go for us because a lot of the users are not tech-savvy and it presents a significant issue.
Is there any way to show the self-signed certificate as fully valid inside the local network on Windows PC and Android tablet with chrome browser and not bother the user with any warnings and alerts?
If not, can you please suggest any other method how to handle this?
Thank You.

Related

What is the most secure way store keys in React Native

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.

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.

app authentication [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
securing connection to php server
I'm writing an mobile application to access an online database (I'm more interested in the high-level algorithm/protocol than the platform-specific implementation).
Since keeping the DB updated require a lot of work I want to restrict the access to my sponsored application only (I don't want other apps to take advantage of my DB for free). To do this I need to authenticate the application itself, but how can I do it?
If I store some sort of credentials within the app somebody could try to disassemble the program, retrieve the data and write his own application bypassing mine (even if I encrypt the credentials I still need to store somewhere the decryption key...)
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. You can use the keytool included with the Android SDK (if you're using Android; there are similar tools out there for other platforms) for this purpose. 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, both server and client side. There is also a complete walk-through for Android applications in my book, Application Security for the Android Platform, published by O'Reilly.
Now...you are right in that someone with access to the mobile app could recover the private key associated with the client-side certificate. It would be in a BKS keystore that would be encrypted but your app would need to supply a password to open that keystore. So, someone could reverse engineer your app (fairly easy on the Android platform), grab the password, grab the keystore, and decrypt it to recover the client-side private key. You can mitigate this someway by obfuscating the app to make reversing the keystore password more difficult, or asking the user to log in to the app and using that password to derive the password the the keystore, etc...it really depends on the level of risk you're willing to take on for your application.

providing SSL for Web Service that runs on IIS

I need to provide SSL to my Web Service that runs on IIS (ASMX web service).
As I understand there are 3 ways to do that:
1) create my own certificate using IIS
2) buy it
3) get some open source certificate
For instance my Web Service has constant IP and communicates with only one web site on client side (client is in PHP).
Can someone give an advice, what is the best way for me to provide it and what are advantages and disadvantages of 3 ways to do that, or just point to some article for complete beginners in SSL issue.
Thanx for assistance!
Creating your own cert is useful only if your end users are either completely uncaring about security or they have some other way of verifying the validity of your server - generally an internal network or something similar.
The free cert issuers tend to be unrecognized. This has the same effect as self-signing.... i.e. pointless since the end user will get the same warning messages.
There are very inexpensive options though. I've used GoDaddy before # USD $13 a year.
Here's a link to all the trusted certificate authorities that Mozilla adds to FireFox:
http://www.mozilla.org/projects/security/certs/included/
IE and Chrome have similar lists.

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