Make secure connection with a nodejs server providing API on Android - android

I have a website that store private information that can be accessed by request with a secret api key.
My Android application have to access that private information, and to do that it use a proxy server that store and use the secret api key to communicate with the website
The problem is that just using Wireshark, or finding the string in the app resources file, someone can see the proxy server url and use it to get the private data from the website
How can i make this system secure? how can i be sure that none else can use the proxy except the Android app?
Thank you!

I have a website that store private information that can be accessed by request with a secret api key.
From the moment you put a secret on the client is not anymore a secret, because now is public and anyone can see it by reverse engineer the app or by intercepting the traffic with a proxy or by just watching the traffic with the tool you mention, Wireshark.
My Android application have to access that private information, and to do that it use a proxy server that store and use the secret api key to communicate with the website
Using a proxy server doesn't solve the problem, because the proxy server doesn't know WHAT is calling it. As it stands the proxy server is open to the public that knows how to call it, as you already know and pointed out:
The problem is that just using Wireshark, or finding the string in the app resources file, someone can see the proxy server url and use it to get the private data from the website.
Another approach is to use a proxy tool like the MiTM Proxy that in my opinion will allow to extract more easily the API key, as you can see in the article Steal that API Key with a Man in the Middle Attack:
While we can use advanced techniques, like JNI/NDK, to hide the API key in the mobile app code, it will not impede someone from performing a MitM attack in order to steal the API key. In fact a MitM attack is easy to the point that it can even be achieved by non developers.
ADDRESSING YOUR QUESTIONS
How can i make this system secure? how can i be sure that none else can use the proxy except the Android app?
Well you bought yourself a very hard problem to solve, that a lot will say that is only possible to make it harder to be solved by the attacker, and this is true until some degree, because a lot of developers are not aware of the Mobile App Attestation concept, that allows a back-end server to only server requests comming from a original app.
Before I can explain you the concept I would like to clarify a common misconception among developers regarding the WHO vs WHAT is accessing your back-end 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.
First question
How can i make this system secure?
Depending on your budget and resources you may employ an array of different approaches and techniques to defend your API server, and I will start to enumerate some of the most usual ones, but before I do it so I would like to leave this note:
As a best practice a mobile app or a web app should only communicate with an API server that is under your control and any access to third party APIs services must be done by this same API server you control. This way you limit the attack surface to only one place, where you will employ as many layers of defense as what you are protecting is worth.
You can start with reCaptcha V3, followed by Web Application Firewall(WAF) and finally if you can afford it a User Behavior Analytics(UBA) solution.
Google reCAPTCHA V3:
reCAPTCHA is a free service that protects your website from spam and abuse. reCAPTCHA uses an advanced risk analysis engine and adaptive challenges to keep automated software from engaging in abusive activities on your site. It does this while letting your valid users pass through with ease.
...helps you detect abusive traffic on your website without any user friction. It returns a score based on the interactions with your website and provides you more flexibility to take appropriate actions.
WAF - Web Application Firewall:
A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to and from a web application. A WAF is differentiated from a regular firewall in that a WAF is able to filter the content of specific web applications while regular firewalls serve as a safety gate between servers. By inspecting HTTP traffic, it can prevent attacks stemming from web application security flaws, such as SQL injection, cross-site scripting (XSS), file inclusion, and security misconfigurations.
UBA - User Behavior Analytics:
User behavior analytics (UBA) as defined by Gartner is a cybersecurity process about detection of insider threats, targeted attacks, and financial fraud. UBA solutions look at patterns of human behavior, and then apply algorithms and statistical analysis to detect meaningful anomalies from those patterns—anomalies that indicate potential threats. Instead of tracking devices or security events, UBA tracks a system's users. Big data platforms like Apache Hadoop are increasing UBA functionality by allowing them to analyze petabytes worth of data to detect insider threats and advanced persistent threats.
All this solutions work based on a negative identification model, by other words they try their best to differentiate the bad from the good by identifying what is bad, not what is good, thus they are prone to false positives, despite of the advanced technology used by some of them, like machine learning and artificial intelligence.
So you may find yourself more often than not in having to relax how you block the access to the API server in order to not affect the good users. This also means that this solutions require constant monitoring to validate that the false positives are not blocking your legit users and that at same time they are properly keeping at bay the unauthorized ones.
Regarding APIs serving mobile apps a positive identification model can be used by using a Mobile App Attestation solution that guarantees to the API server that the requests can be trusted without the possibility of false positives, and I will explain it as a reply to your second question.
Second question
how can i be sure that none else can use the proxy except the Android app?
As I mentioned in the begin of my answer, the Mobile App Attestation concept may be your best option to tackle your problem.
The role of a Mobile App Attestation solution is to guarantee at run-time that your mobile app was not tampered with, is not running in a rooted device, not being instrumented by a framework like xPosed or Frida, not being MitM attacked, and this is achieved by running an SDK in the background. The service running in the cloud will challenge the app, and based on the responses it will attest the integrity of the mobile app and device is running on, thus the SDK will never be responsible for any decisions.
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.
MiTM Proxy
An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.
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.
The Mobile App Attestation service 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.
CONCLUSION
In the end, the solution to use in order to protect your API server must be chosen in accordance with the value of what you are trying to protect and the legal requirements for that type of data, like the GDPR regulations in Europe.
DO YOU WANT TO GO 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.

Related

Restrict face recognition API call to Flutter app only

I have an use case where in my flutter app makes an API call to a backend API which in turn makes a call to a 3rd party service to verify whether both the images are similar. My concern is, any user can use the api access token to call the backend API directly with spoofed data to get a verified profile. How can i make sure that the image data is coming from the mobile camera itself ?
The Difference Between WHO and WHAT is Accessing the API Server
I have an use case where in my flutter app makes an API call to a backend API which in turn makes a call to a 3rd party service to verify whether both the images are similar. My concern is, any user can use the api access token to call the backend API directly with spoofed data to get a verified profile.
You need to empower your backend API with a mechanism to distinguish between who is in the request vs what is making the request. I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read this:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
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.
So think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
After you understand this idea and it's ingrained in your mindset, you will look into mobile API security with another perspective, and you will be able to see attack surfaces that you never though they could exist.
Possible Solution
How can i make sure that the image data is coming from the mobile camera itself ?
I will reply to this question more in the context of how you can be sure that the request sent to the backend with the image is originated from your genuine and unmodified mobile app, and not from a tampered one or from a bot or manual request.
I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, especially the sections Hardening and Shielding the Mobile App, Securing the API Server and A Possible Better Solution to understand the several options you have to tackle your problem.
From the several solutions provided in the answer the best fit for your problem will be the Mobile App Attestation, that will allow your backend to have a very high degree of confidence that what is making the request is indeed your genuine and unmodified mobile app, therefore preventing attacker from getting a valid profile, as per your main concern:
My concern is, any user can use the api access token to call the backend API directly with spoofed data to get a verified profile.
Do You Want To Go The Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
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.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

Client Service Authentication to Backend

I am developing an Android background service that will communicate with a backend API. Also, the app will be distributed through a mobile device management system and there is no client interaction, such as inputting user info. How can I securely authorize each instance of the background service so they may access the backend service? One idea I had was to distribute one-time invitation codes with the app that were preconfigured on the server so each instance of the app may register with the service by generating a username and password, and then it could use OAuth to retrieve access tokens.
I found a similar question, however, I do not want to allow any arbitrary instance of the service to have access to the API and it references a deprecated feature
Authorizing Client Acces to App Engine Backend
The Challenge
I am developing an Android background service that will communicate with a backend API. Also, the app will be distributed through a mobile device management system and there is no client interaction, such as inputting user info.
You have got yourself a huge challenge here :)
Locking down the API server to genuine and unmodified instances of a mobile app is already a very hard task when user authentication(who) is involved, but when this is missing then things become really difficult, but not impossible.
Before we continue further I would like to first clear a misconception that I usually find among developers of any seniority, that is about the difference between who and what is accessing an API server.
The Difference Between WHO and WHAT is Accessing the API Server
I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
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.
So think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
In your case you don't have a user, therefore you will need to put your efforts on creating a solution that allows for the API server to have a very high degree of confidence that it can be sure that the request is from what it expects, a genuine and unmodified version of the mobile app where your Android background service is running.
Your Solution to the Challenge
One idea I had was to distribute one-time invitation codes with the app that were preconfigured on the server so each instance of the app may register with the service by generating a username and password, and then it could use OAuth to retrieve access tokens.
As you may be aware by now your solution will only provide the who in the request, not what is doing the request. The what in the request is already referenced by you when you say I do not want to allow any arbitrary instance of the service to have access to the API. This can be mobile apps instrumented at runtime, repackaged mobile apps, cloned mobile apps, bots running automated scritps to make request like the real mobile app or even manually replayed requests by an attacker.
Also, the one-time invitation codes can be easily extracted from the APK binary with reverse engineer techniques, like I show in my article How to Extract an API key from a Mobile App with Static Binary Analysis:
The range of open source tools available for reverse engineering is huge, and we really can't scratch the surface of this topic in this article, but instead we will focus in using the Mobile Security Framework(MobSF) to demonstrate how to reverse engineer the APK of our mobile app. MobSF is a collection of open source tools that present their results in an attractive dashboard, but the same tools used under the hood within MobSF and elsewhere can be used individually to achieve the same results.
During this article we will use the Android Hide Secrets research repository that is a dummy mobile app with API keys hidden using several different techniques.
A Possible Better Solution
How can I securely authorize each instance of the background service so they may access the backend service?
I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, especially the sections Hardening and Shielding the Mobile App, Securing the API Server and A Possible Better Solution.
The linked answer will allow you to understand the several options you may want to consider, and also highlight the Mobile App Attestation concept as the one that will allow the API server to have a very high degree of confidence to only accept requests from genuine and unmodified instances of the mobile app running the Android background service.
Do You Want To Go The Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
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.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

How to restrict usage of an API key with Hash comparison

I'm currently using Spotify in my Android app, but I am required to use a Secret in order to refresh tokens and such. I would like to transmit the secret from my Backend to the app, so the secret does not reside in the APK and cannot be found when decompiling. I've read a lot only about securing secrets in your app, via various ways like proxies, just using your own backend, putting the code into native C++ code (NDK) in the app or using the Hash of the app to determine whether the app is calling the backend, and not some guy behind his computer trying to steal the secrets.
Found options:
Proxy: It means routing it through my own server, don't want that
Own backend: Same as proxy, don't want all request to got trough my own service
Native code: Using this seems to slow down decompilers, but doesn't stop them
Hash: From what I could find, this post suggests some things that I consider weird. It is retrieving the SHA-1 and passing it into the network header to verify that the app is calling. The weird part about this is, that when you just unzip the APK file, running a printcert (keytool -printcert -file CERT.RSA) command will display all SHA and MD5 hashes of the APK. From what I can tell, this is not foolproof as someone can just get the hashes of the APK file and submit that to the server.
Is there any other way I can solve this issue?
YOUR PROBLEM
I'm currently using Spotify in my Android app, but I am required to use a Secret in order to refresh tokens and such. I would like to transmit the secret from my Backend to the app, so the secret does not reside in the APK and cannot be found when decompiling. I've read a lot only about securing secrets in your app, via various ways like proxies, just using your own backend, putting the code into native C++ code (NDK) in the app or using the Hash of the app to determine whether the app is calling the backend, and not some guy behind his computer trying to steal the secrets.
Congratulations in your efforts to understand the problem, it seems that you went to a great extent to understand that secrets in a mobile app can always be extracted by static binary analysis, but I don't see any mention to instrumentation frameworks like:
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.
or
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.
but many others more exist, and all of them will hook into your code at runtime and extract any secret you store in your mobile app, no matter how securely you store it, even if you use hardware backed keystores, that run in a trusted execution environment:
Android Hardware-backed Keystore
The availability of a trusted execution environment in a system on a chip (SoC) offers an opportunity for Android devices to provide hardware-backed, strong security services to the Android OS, to platform services, and even to third-party apps.
At some point the secret retrieved from this keystore will need to be used to make the request to your third party service, and at this point all an attacker needs to do is to hook on the call to that function and extract the secret when passed to it.
So no matter what you do in the end a secret in a mobile app can always be extracted, it just depends on the skill set of the attacker and the time and effort he is willing to put in.
This being said, it leads me to the point I am always advising developers to not do, that is calling Third Party services from within their mobile app.
THIRD PARTY SERVICES ACCESS FROM A MOBILE APP
Found options:
Proxy: It means routing it through my own server, don't want that
Own backend: Same as proxy, don't want all request to got trough my own service
Yes I read you don't want to use a proxy or your backend, but that is the best chance you have to secure the access to your third party service, in this case Shopify.
I wrote this article that explains why you should not do it from your mobile app, from where I quote:
Generally, all Third Party APIs require a secret in the form of an API key, Access Token or some other mechanism for a remote client to identify itself to the backend server with which it wishes to communicate. Herein lies the crux of the problem of accessing it from within your mobile app, because you will need to ship the required secret(s) within the code (the coloured keys in the above graphic).
Now you may say that you have obfuscated the secret within your code, hidden it in the native C code, assembled it dynamically at runtime, or even encrypted it. However, in the end all an attacker needs to do in order to extract this secret is to reverse engineer the binary with static binary analysis, or hook an instrumentation framework like Frida into the function at runtime which will return the secret. Alternatively an attacker can inspect the traffic between the mobile app and the Third Party API it is connecting to by executing a MitM (man-in-the-middle).
With the secret in their possession, the attacker can cause a lot of damage to an organization. The damage can be monetary, reputational and/or regulatory. Financially, the attacker can use the extracted secret to access your cloud provider and your pay-per-call Third Party APIs in your name, thus causing you additional costs. Further, you may be financially hurt by the exfiltration of data which may be sold to your competitors or used to commit fraud. Reputationally you can be impacted when the attacker uses the extracted secret to post on your behalf on social networks, creating a public relations nightmare. Another reputational damage can occur when an attacker uses the Third Party API and violates its terms & conditions (for example where frequent usage of the API triggers rate limits) such that you get blocked from using the service, creating pain for your end users. Last but not least are regulatory troubles caused when the extracted secret is the only mechanism of protecting access to confidential information from your Third Party API. If the attacker can retrieve confidential information such as Personal Identifiable Information (PII), regulatory fines connected to violations of GDPR in Europe, or the new CCPA Data Privacy Law in the California, may be enforced against your business.
So the take home message is that any secret you ship in your code must be considered public from the moment you release your app or push the code to a public repository. By now it should be clear that the best approach is to completely avoid accessing Third Party APIs from within a mobile app; instead you should always delegate this access to a backend you can trust and control, such as a Reverse Proxy.
You now may say that the problem have just shifted from the mobile app into the reverse proxy or backend server, and that's a positive thing, because the backend or reverse proxy is under your control, but a mobile app is out of your control, because it's in the client side, therefore the attacker can do whatever he wants with it.
In the backend or reverse proxy you are not exposing the secrets to access the third party services to the public, and any abuse an attacker wants to do in your behalf against that third party service will need to pass through a place you control, therefore you can apply as many defense mechanisms as you can afford and is required by law for your use case.
SECURITY IN DEPTH
putting the code into native C++ code (NDK)
When hiding the secret in native C code it's not easy to find it with static binary analysis, at least for script kids and seasonal hackers, it needs a better skill set that the majority may not have, thus I really recommend you to use it as an extra layer of security, but to protect a secret to access your own services, not third party ones as I already mentioned before.
If you really decide to follow my advice and shift your efforts to defend the third party secret in place you have control off, like your own backend, then I recommend you to read my answer to the question How to secure an API REST for mobile app? for the sections on Securing the API Server and A Possible Better Solution.
If you read the above answer then you have realized that if you keep the access to third party services in your backend, you can lock down your API server to your mobile app with a very high degree of confidence by using the Mobile App Attestation concept.
DO YOU WANT TO GO THE EXTRA MILE?
I saw that you are well informed, thus you already know what I am about to share, but in any response I gave to a security question I always like to reference the excellent work from the OWASP foundation, thus If you allow I will do it here to :)
For Mobile Apps
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.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
Everything that was created by a human can be broken down by a human - there is no completely secure option.
There are few things you can try though.
Use end-to-end encryption to establish a secure connection with you server and then send your secret to your app from your backend. Store secret secured via KeyStore in SharedPrefs or file or database.
Also you can leverage one-time pad cipher based on Vernam algorithm. It has absolute cryptographic strength thus cannot be cracked. In conjunction with Diffie-Hellman it may give a nice security boost.
It can still be cracked though - via memory scan on rooted devices while the app is active and has secret decrypted, via man-in-the-middle attack etc. As I've said - everything can be broken(for now except of Vernam algorithm maybe).
Don't bother too much with it though - it will be hard for criminals to significantly misuse your secrets. Generally they even don't bother with such stuff that much.
Hope this answer will help you somehow.

Avoid disabling certificate pinning Android

I am developing an Android application that uses Certificate Pinning (in a similar fashion such this).
However, I've came across dynamic instrumentation libraries such as Frida, or worse yet, Objection, that can bypass this safeguard.
I understand that security must be implemented on server side, but, I'd like to keep prying eyes outside my API. Moreover I also understand that Java executables are easy to disassemble and analyze.
How can I make this process more difficult for an attacker, i.e. make basic commands such as objection's
android sslpinning disable
fail and harden my app? I've seen that depending on the namings of the assets this process also crashes.
Any ideas?
Several harding frameworks can make it more difficult for Frida and similar tools to attach and manipulate the app process. However with enough time, motivation and/or money you can even break those frameworks.
However usually it is not the question "using a hardening framework or not" but "how many money are you willing to pay to get this little extra protection?
From my knowledge there are no free or even cheap hardening frameworks (please correct me if I am wrong and provide links to those free/cheap solutions with good protection), therefore it is just a question how much protection you want and how much you are willing to pay.
Note: Proguard and R8 are not hardening frameworks! They only just obfuscate the code a bit, but especially when it comes to certificate pinning and disabling this via Frida they do not offer any protection!
Possible Solution
How can I make this process more difficult for an attacker
A possible solution for your problem is to use a Mobile App Attestation solution to guarantee at run-time that your mobile app is not being MitM attacked, is not tampered, is not running in a rooted device, is not attached to a debugger and no instrumentation frameworks is present. This is achieved 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 the device is running on. The SDK in the mobile app doesn't make any decisions about the integrity of the app or mobile device, that is done in the cloud service, based on measurements provided by the mobile app.
So on a successful attestation of the mobile app integrity, by the cloud service, 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.
Any ideas?
You can try to roll your own solution or you can look for an existing Mobile App Attestation SAAS solution, like 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
In the end, the solution to use in order to protect your API server and mobile app must be chosen in accordance with the value of what you are trying to protect and the legal requirements for that type of data, like the GDPR regulations in Europe.
Going the Extra Mile
You seem to be into mobile app security, does I would like to recommend you:
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.

Restrict API requests to only my own mobile app

Is there any way to restrict post requests to my REST API only to requests coming from my own mobile app binary? This app will be distributed on Google Play and the Apple App Store so it should be implied that someone will have access to its binary and try to reverse engineer it.
I was thinking something involving the app signatures, since every published app must be signed somehow, but I can't figure out how to do it in a secure way. Maybe a combination of getting the app signature, plus time-based hashes, plus app-generated key pairs and the good old security though obscurity?
I'm looking for something as fail proof as possible. The reason why is because I need to deliver data to the app based on data gathered by the phone sensors, and if people can pose as my own app and send data to my api that wasn't processed by my own algorithms, it defeats its purpose.
I'm open to any effective solution, no matter how complicated. Tin foil hat solutions are greatly appreciated.
Any credentials that are stored in the app can be exposed by the user. In the case of Android, they can completely decompile your app and easily retrieve them.
If the connection to the server does not utilize SSL, they can be easily sniffed off the network.
Seriously, anybody who wants the credentials will get them, so don't worry about concealing them. In essence, you have a public API.
There are some pitfalls and it takes extra time to manage a public API.
Many public APIs still track by IP address and implement tarpits to simply slow down requests from any IP address that seems to be abusing the system. This way, legitimate users from the same IP address can still carry on, albeit slower.
You have to be willing to shut off an IP address or IP address range despite the fact that you may be blocking innocent and upstanding users at the same time as the abusers. If your application is free, it may give you more freedom since there is no expected level of service and no contract, but you may want to guard yourself with a legal agreement.
In general, if your service is popular enough that someone wants to attack it, that's usually a good sign, so don't worry about it too much early on, but do stay ahead of it. You don't want the reason for your app's failure to be because users got tired of waiting on a slow server.
Your other option is to have the users register, so you can block by credentials rather than IP address when you spot abuse.
Yes, It's public
This app will be distributed on Google Play and the Apple App Store so it should be implied that someone will have access to its binary and try to reverse engineer it.
From the moment its on the stores it's public, therefore anything sensitive on the app binary must be considered as potentially compromised.
The Difference Between WHO and WHAT is Accessing the API Server
Before I dive into your problem I would like to first clear a misconception about who and what is accessing an API server. I wrote a series of articles around API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in detail the difference between who and what is accessing your API server, but I will extract here the main takes from it:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
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.
Think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
So if you are not using user authentication in the app, then you are left with trying to attest what is doing the request.
Mobile Apps should be as much dumb as possible
The reason why is because I need to deliver data to the app based on data gathered by the phone sensors, and if people can pose as my own app and send data to my api that wasn't processed by my own algorithms, it defeats its purpose.
It sounds to me that you are saying that you have algorithms running on the phone to process data from the device sensors and then send them to the API server. If so then you should reconsider this approach and instead just collect the sensor values and send them to the API server and have it running the algorithm.
As I said anything inside your app binary is public, because as yourself said, it can be reverse engineered:
should be implied that someone will have access to its binary and try to reverse engineer it.
Keeping the algorithms in the backend will allow you to not reveal your business logic, and at same time you may reject requests with sensor readings that do not make sense(if is possible to do). This also brings you the benefit of not having to release a new version of the app each time you tweak the algorithm or fix a bug in it.
Runtime attacks
I was thinking something involving the app signatures, since every published app must be signed somehow, but I can't figure out how to do it in a secure way.
Anything you do at runtime to protect the request you are about to send to your API can be reverse engineered with tools like 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.
Your Suggested Solutions
Security is all about layers of defense, thus you should add as many as you can afford and required by law(e.g GDPR in Europe), therefore any of your purposed solutions are one more layer the attacker needs to bypass, and depending on is skill-set and time is willing to spent on your mobile app it may prevent them to go any further, but in the end all of them can be bypassed.
Maybe a combination of getting the app signature, plus time-based hashes, plus app-generated key pairs and the good old security though obscurity?
Even when you use key pairs stored in the hardware trusted execution environment, all an attacker needs to do is to use an instrumentation framework to hook in the function of your code that uses the keys in order to extract or manipulate the parameters and return values of the function.
Android Hardware-backed Keystore
The availability of a trusted execution environment in a system on a chip (SoC) offers an opportunity for Android devices to provide hardware-backed, strong security services to the Android OS, to platform services, and even to third-party apps.
While it can be defeated I still recommend you to use it, because not all hackers have the skill set or are willing to spend the time on it, and I would recommend you to read this series of articles about Mobile API Security Techniques to learn about some complementary/similar techniques to the ones you described. This articles will teach you how API Keys, User Access Tokens, HMAC and TLS Pinning can be used to protect the API and how they can be bypassed.
Possible Better Solutions
Nowadays I see developers using Android SafetyNet to attest what is doing the request to the API server, but they fail to understand it's not intended to attest that the mobile app is what is doing the request, instead it's intended to attest the integrity of the device, and I go in more detail on my answer to the question Android equivalent of ios devicecheck. So should I use it? Yes you should, because it is one more layer of defense, that in this case tells you that your mobile app is not installed in a rooted device, unless SafetyNet has been bypassed.
Is there any way to restrict post requests to my REST API only to requests coming from my own mobile app binary?
You can allow the API server to have an high degree of confidence that is indeed accepting requests only from your genuine app binary by implementing the Mobile App Attestation concept, and I describe it in more detail on this answer I gave to the question How to secure an API REST for mobile app?, specially the sections Securing the API Server and A Possible Better Solution.
Do you want to go the Extra Mile?
In any response to a security question I always like to reference the excellent work from the OWASP foundation.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
For Mobile Apps
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.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
No. You're publishing a service with a public interface and your app will presumably only communicate via this REST API. Anything that your app can send, anyone else can send also. This means that the only way to secure access would be to authenticate in some way, i.e. keep a secret. However, you are also publishing your apps. This means that any secret in your app is essentially being given out also. You can't have it both ways; you can't expect to both give out your secret and keep it secret.
Though this is an old post, I thought I should share the updates from Google in this regard.
You can actually ensure that your Android application is calling the API using the SafetyNet mobile attestation APIs. This adds a little overhead on the network calls and prevents your application from running in a rooted device.
I found nothing similar like SafetyNet for iOS. Hence in my case, I checked the device configuration first in my login API and took different measures for Android and iOS. In case of iOS, I decided to keep a shared secret key between the server and the application. As the iOS applications are a little bit difficult to reversed engineered, I think this extra key checking adds some protection.
Of course, in both cases, you need to communicate over HTTPS.
As the other answers and comments imply, you cant truly restrict API access to only your app but you can take different measures to reduce the attempts. I believe the best solution is to make requests to your API (from native code of course) with a custom header like "App-Version-Key" (this key will be decided at compile time) and make your server check for this key to decide if it should accept or reject. Also when using this method you SHOULD use HTTPS/SSL as this will reduce the risk of people seeing your key by viewing the request on the network.
Regarding Cordova/Phonegap apps, I will be creating a plugin to do the above mentioned method. I will update this comment when its complete.
there is nothing much you can do. cause when you let some one in they can call your APIs. the most you can do is as below:
since you want only and only your application (with a specific package name and signature) calls your APIs, you can get the signature key of your apk pragmatically and send is to sever in every API call and if thats ok you response to the request. (or you can have a token API that your app calls it every beginning of the app and then use that token for other APIs - though token must be invalidated after some hours of not working with)
then you need to proguard your code so no one sees what you are sending and how you encrypt them. if you do a good encrypt decompiling will be so hard to do.
even signature of apk can be mocked in some hard ways but its the best you can do.
Someone have looked at Firebase App Check ?
https://firebase.google.com/docs/app-check
Is there any way to restrict post requests to my REST API only to requests coming from my own mobile app binary?
I'm not sure if there is an absolute solution.
But, you can reduce unwanted requests.
Use an App Check:
The "Firebase App Check" can be used cross-platform (https://firebase.google.com/docs/app-check) - credit to #Xande-Rasta-Moura
iOS: https://developer.apple.com/documentation/devicecheck
Android: https://android-developers.googleblog.com/2013/01/verifying-back-end-calls-from-android.html
Use BasicAuth (for API requests)
Allow a user-agent header for mobile devices only (for API requests)
Use a robots.txt file to reduce bots
User-agent: *
Disallow: /

Categories

Resources