I am currently designing a native app which will have a simple username / password login. On a valid authentication, the backend server is issuing a JWT access token and refresh token which are eventually used throughout subsequent API calls.
My concern is that using such an approach, my app can be prone to phishing whereby a hacker can decompile and recompile my app with malicious interceptors.
In order to overcome this, I was thinking of designing my Login API, so that rather than having an accessToken and a refreshToken in the payload response of the API, the Login API will issue a 301 Redirect on myapp://some-path?accessToken=X&refreshToken=Y. This will ensure that if a phishing app is calling my APIs, the accessToken and the refreshToken are sent to the original APP.
Is this a correct approach? If not, which design would be suggested?
How would that help? If I'm going into your app to hack and recompile, I'll be taking over the entire app. I won't leave a copy of the old version, I'm just going to replace the urls. So when you redirect to myapp://somepath, it'll be redirecting to the same hacked app.
Secondly, how would a redirect do anything? Making an HTTP request doesn't cause an app to be launched on the client. It causes the HTTP request to return a HTTPResponse object with a response code of 301. So your redirect URL wouldn't be launched anyway.
Third, that's already too late. By the time you have an access and refresh token, you've logged in. That means the hacked app has your password and credentials. 2FA may help here a bit to make it harder to attack, but only if its time based, and even then it just reduces the window.
If a user is installing a hacked version of your app and is willing to sign into it, you've already lost.
YOUR PROBLEM
I am currently designing a native app which will have a simple username / password login. On a valid authentication, the backend server is issuing a JWT access token and refresh token which are eventually used throughout subsequent API calls.
You need to bear in mind that any secret that leaves the backend or is stored inside a mobile app is no longer a secret, instead it's a public thing, even if you are using TLS (can be intercepted in some scenarios) and Certificate pinning (can be bypassed in some circunstances), because an attacker can reverse engineer your mobile app via a plethora of open source tools and techniques, one of them being static decompilation as you mention:
My concern is that using such an approach, my app can be prone to phishing whereby a hacker can decompile and recompile my app with malicious interceptors.
Once it's decompiled the attacker can do whatever he wants with your code, not just adding interceptors. It's well known problem that the Google Play store is full of cloned and repackaged apps that will use the same backend as the genuine app. You even have a repo RePack: A repository of repackaged Android apps, that illustrates the problem:
RePack is a repository of over 15,000 repackaged Android app pairs collected from AndroZoo. The SHA256 of the apps are available in the repackaging_pairs.txt file. The actual APKs are available in the AndroZoo dataset, which can be downloaded by giving a SHA256 as input. Please following this page to learn how to download apps from AndroZoo.
When repackaged the apps can be used to simply add ads to it and act as a fake app to your service where the profits will go to the attacker, or can be used to distribute malware and/or spy on users as seen in the article 700,000 malicious Android apps found in Google Play store last year:
Google has confirmed that it had to remove nearly 700,000 potentially malicious apps from the Google Play store in 2017 – an increase of 70% from the previous year.
Reverse Engineering
The truth is that anything running in the client side can be reverse engineered
easily by an attacker on a device he controls.
When reverse engineering a mobile app an attacker first step may be to perform a static binary analysis to extract all static secrets and to identify attack vectors, and you can see how 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.
Another alternative to extract secrets is to perfome a Man in the Middle (MitM) attack to intercept the TLS connection and extract all secrets and learn how the mobile app interacts with the backend and any other third party APIs, and you can see how I done it in the article
Steal that Api Key with a Man in the Middle Attack:
In order to help to demonstrate how to steal an API key, I have built and released in Github the Currency Converter Demo app for Android, which uses the same JNI/NDK technique we used in the earlier Android Hide Secrets app to hide the API key.
So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.
Wait, I imagine you now thinking, but I will use certificate pinning to protect my TLS channel, no problem just see how certificate pinning can be easily bypassed in a device the attacker controls in the article Bypassing Certificate Pinning
In this article you will learn how to repackage a mobile app in order to disable certificate pinning and in the process you will also learn how to create an Android emulator with a writable system to allow for adding the custom certificate authority for the proxy server into the Android operating system trust store. This will allow us to bypass certificate pinning and intercept the requests between the mobile and its backend with a MitM attack.
While repackaging a mobile app to bypass pinning is a good solution my preference goes to do it dynamically at runtime as I show in the article How to Bypass Certificate Pinning with Frida on an Android App:
Today I will show how to use the Frida instrumentation framework to hook into the mobile app at runtime and instrument the code in order to perform a successful MitM attack even when the mobile app has implemented certificate pinning.
Bypassing certificate pinning is not too hard, just a little laborious, and allows an attacker to understand in detail how a mobile app communicates with its API, and then use that same knowledge to automate attacks or build other services around it.
Now you may be thinking that you have lost the battle and shouldn't care about adding protections because they will end-up to be bypassed. Well, I have to tell you that software security shares the same traits as the defences in the medieval castles, where they used it in layers, in order to make the assault to the castle as hard as possible, and hopefully impossible. So, you need to adopt the same posture as them and put as many security layers as you can afford, and required by law, in order to make the attackers efforts time consuming and to require more expertise then most of them may have.
YOUR QUESTIONS
In order to overcome this, I was thinking of designing my Login API, so that rather than having an accessToken and a refreshToken in the payload response of the API, the Login API will issue a 301 Redirect on myapp://some-path?accessToken=X&refreshToken=Y. This will ensure that if a phishing app is calling my APIs, the accessToken and the refreshToken are sent to the original APP.
Is this a correct approach?
So, I think that by now is obvious that your solution will not be effective and will be easily defeated with repackaging the mobile app, MitM attack it or simply by instrumenting the code at runtime.
If not, which design would be suggested?
You should use a security approach where the API backend is able to recognize that what is making the request is indeed a genuine and untampered/repacked/cloned version of your mobile app, not just who is making the request, as when user authentication is solely used to protect unauthorised access to an API.
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.
POSSIBLE SOLUTION
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.
You will see that you can use a plethora of defence layers, like in medieval castles, and that the solution you may want to employ, to guarantee with an high degree of confidence that what is doing the request to the backend is indeed your genuine mobile app, is the Mobile App Attestation.
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.
Related
Looking for a way to see how I can make sure that requests that originate from my mobile apps are only served by my server API.
This is to enable guest users to get to see the app but not get data exposed out for use by BOTs.
Is there an Android or iOS app property that helps with creating requests that help with this?
Looking for a way to see how I can make sure that requests that originate from my mobile apps are only served by my server API.
As it is phrased now I read it more like that you want to ensure that you mobile app only sends and receives requests from your API server, not from an attackers API server pretending to be yours, or from an MitM attack. If this is the case then the solution is to add certificate pinning to your mobile app, but this should be always added to any mobile app.
I think what you mean here is that you want to ensure that your API server only replies to requests coming from a genuine instance of your mobile app. If this is the case then you are looking to lock down your API server to your mobile app and you have here a great challenge and several approaches to take.
Certificate Pinning
To implement certificate pinning in your mobile app I recommend you to read the article Securing HTTPS with Certificate Pinning:
In order to demonstrate how to use certificate pinning for protecting the https traffic between your mobile app and your API server, we will use the same Currency Converter Demo mobile app that I used in the previous article.
In this article we will learn what certificate pinning is, when to use it, how to implement it in an Android app, and how it can prevent a MitM attack.
So the article will guide you through an actual implementation of certificate pinning in an example app that you can find in this repo.
Lockdown the API server to the Mobile APP
I recommend you to read this answer I gave to the question How to secure an API REST for mobile app?, especially the sections Securing the API Server and A Possible Better Solution.
Encrypted Key Generation in the Mobile Aapp
I saw this in one of your comments to another answer(you should also add it to your question):
I am looking at a secure way of creating an encrypted key in the app that can only be decrypted on the server.
You can indeed create one securely with the help of the Android Security Library:
The Security library provides an implementation of the security best practices related to reading and writing data at rest, as well as key creation and verification.
I go in more detail about in this answer for the question Store Client Certificate and key (.pem) in Android securely, that contains some code samples.
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.
You can pass the package name (Android)/Bundle identifier(iOS app) of the application in req. params to validate the request from your app only.
In this way you can check the bundle identifier/package name on your server and based on that you can restrict the user to allow/disallow api usage.
Another way is the user of api key/token.
you can create the unique token/key on your server and given to the mobile app developer and ask then to send that in every api request.
So when you get the request on server you can validate that api key/token on server. If key/token is not valid then disallow the user to access your api.
I have backend api in Laravel and using Laravel Passport(OAuth2). I see OAuth2 is super cool and secures my auth request (with api middleware in laravel) and allow access only to authorized users.
But i can access the backend api for unauthorised usage for example
Routes: (/register) or (/login) without any api key. Most attackers will see this api call in network tab and can send DDOS attack. Since Laravel Passport has rate-limiting inbuilt, still i don't want people to access my backend api, unless i allow it manually.
What i want:
I have two frontend apps.
Android Native Mobile app.
Nuxt SPA frontend app
My API should work only from these frontends. No other postman or browser request should pass and probably should display unsupported platforms json msg.
OAUTH TOKENS ARE THEY REALLY ENOUGH TO PROTECT YOUR BACKEND?
I see OAuth2 is super cool and secures my auth request (with api middleware in laravel) and allow access only to authorized users.
It allows access to any request that presents a valid OAuth token, not only for authorized users. This is an usual misconception among developers, because the OAuth token only represents who is in the request, not what is making the request, and I discussed this in more detail in this article, where you can read:
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.
The article is in the context of a mobile app, but the concept is the same for both the mobile app and web app in terms of knowing the difference between who and what is making the request to the backend server.
UNAUTHORIZED USAGE OF THE BACKEND
But i can access the backend api for unauthorised usage for example
I hope that by now you have realized that is not only your routes to /register and /login that are at danger of being abused, because at the moment you only know who is making the request, not what is making it.
Routes: (/register) or (/login) without any api key.
Even if you have an API key on this routes, it would not prevent it from being abused for credential stuffing attacks.
Why you may ask?
Well in a web app all it's needed to extract an API key is to hit F12 to open the developer tools tab and search for it, or view the page source.
You may now think, oh but in my mobile app it would not be possible, because it's a binary, and I even use obfuscation. Despite being a little more difficult is not hard, because a lot of open source tools exist to help with the task.
Reverse Engineering
You can use a tool like MobSF to reverse engineer any mobile app binary, and extract the API key or any secret from it. I wrote the article How to Extract an API Key from a Mobile App by Static Binary Analysis that you can follow for a practical example of doing it so, and also shows you several techniques to hide the API key in a mobile app with the Android Hide Secrets repo from Github.
MobSF:
Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis.
If you cannot extract the API key via static analysis, then you can resort to dynamic analysis with open source tools to, 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.
Frida will allow at runtime to steal your OAuth tokens and sent them to the attackers control servers, from where they can then reuse it to launch automated attacks to your backend, that will trust they are legit, because the who in the request is valid.
Another approach to steal an API key or even OAuth tokens is to perform a Man in the Middle(MitM) Attack wit another open source tools, like mitmproxy:
An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.
So when attacker uses mitmproxy to intercept the request being made to the backend, he will see something like this:
Image sourced from article: Steal that API key with a Man in the Middle Attack
Did you noticed that the url is in https and contains an API Key?
So until now you though that https was enough to secure the communication between clients and server?
WHAT YOU WANT
What i want:
I have two frontend apps.
Android Native Mobile app.
Nuxt SPA frontend app
My API should work only from these frontends. No other postman or browser request should pass and probably should display unsupported platforms json msg.
The web apps
Due to the nature of how the web was built it's not possible for the backend to identify, with an high degree of confidence, what is making the request for any type of web app, be it a SPA or the traditional ones.
The best you can do is to apply User Behavior Analytics(UBA) in a best effort basis to tell appart who and what is accessing your backend:
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.[1] Instead of tracking devices or security events, UBA tracks a system's users.
A good example of using a UBA solution is to use
Google Recaptcha V3:
reCAPTCHA is a free service that protects your site from spam and abuse. It uses advanced risk analysis techniques to tell humans and bots apart.
This is prone to false positives, therefore you need to be careful when deciding to accept or not the request based on the score returned by reCPATCHA V3 for each request:
reCAPTCHA v3 returns a score for each request without user friction. The score is based on interactions with your site and enables you to take an appropriate action for your site.
For mobile apps
By now you are already aware that the OAuth token to identify your user is not that "safe" as you had though initially, because it only identifies the who in the request, not what is doing it, and as you also saw by the plethora of tools available to reverse engineer mobile apps, the OAuth token is always at danger of being stolen and abused by unauthorized clients.
The solution that can let your backend to be sure that the request is indeed from the same exact mobile app that was uploaded to the Google Play store is a Mobile App Attestation solution, and this is a concept that introduces a new approach of dealing with security for your mobile app and backend in an unified manner.
The usual solutions focus to much on the mobile app itself, but in first place the data you want to protect is in your backend server, and it's here that you want to have a mechanism to know that what is making the request is really the thing you expect, your genuine mobile app.
The Mobile App Attestation concept is described in this section of another article I wrote, from where I will quote the following text:
The role of a Mobile App Attestation service is to authenticate what is sending the requests, thus only responding to requests coming from genuine mobile app instances and rejecting all other requests from unauthorized sources.
In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework (Frida, xPosed, Cydia, etc.) and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.
On a 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 know. In the case that attestation fails the JWT token is signed with an incorrect secret. Since the secret used by the Mobile App Attestation service is not known by the mobile app, it is not possible to reverse engineer it at run-time even when the app has been tampered with, is running in a rooted device or communicating over a connection that is the target of a MitM attack.
The mobile app must send the JWT token in the header of every API request. This allows the API server to only serve requests when it can verify that the JWT token was signed with the shared secret and that it has not expired. All other requests will be refused. In other words a valid JWT token tells the API server that what is making the request is the genuine mobile app uploaded to the Google or Apple store, while an invalid or missing JWT token means that what is making the request is not authorized to do so, because it may be a bot, a repackaged app or an attacker making a MitM attack.
Taking this approach will let your backend server to know with a very high degree of confidence what is making the request, the same exact mobile app you uploaded to the Google Play, provided the JWT token has a valid signature and expire time, and discard all other requests as untrustworthy ones.
SUMMARY
For web apps your protection is more limited, and in my opinion User Behavior analytics in the backend may be the best option for you.
For mobile apps a huge plethora of solutions exist, but they focus on the mobile app itself, leaving the backend vulnerable to trust in requests that mimic the mobile app, but with a Mobile App Attestation solution the backend is able to tell apart requests from genuine mobile and from fake ones.
GOING THE EXTRA MILE
Now I would like to recommend you the excellent work of the OWASP foundation:
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
The Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
I am implementing SSL pinning in our android app. I have pinned 2 certificates (current and backup) at the client by embedding them in the app.
Now, I want to have a mechanism in place to update these certificates without requiring to roll out an app upgrade in case certificates are expired or private key is compromised. How can I implement that?
One possible solution I am seeing is through app notification. I can broadcast a notification with new certificates and store them in the client. Is there any problem in this approach or is there any better approach?
PUBLIC KEY PINNING
I am implementing SSL pinning in our android app. I have pinned 2 certificates (current and backup) at the client by embedding them in the app.
If you pin against the public key you do not need to update your mobile app each time a certificate is rotated in the server, once you will sign it with the same public key, and you can read the article Hands On Mobile APi Security: Pinning Client Connections for more details in how this can be done:
For networking, the Android client uses the OKHttp library. If our digital certificate is signed by a CA recognized by Android, the default trust manager can be used to validate the certificate. To pin the connection it is enough to add the host name and a hash of the certificate’s public key to the client builder(). See this OKHttp recipe for an example. All certificates with the same host name and public key will match the hash, so techniques such as certificate rotation can be employed without requiring client updates. Multiple host name - public key tuples can also be added to the client builder().
For a situation where the private key used to sign the certificate gets compromised you will end-up in the same situation that you are trying to solve now, that is the need to release a new mobile app to update what you trust to pin against. By other words, the public key cannot be trusted anymore, thus the server must rotate the certificate with one signed with the backup public key you have released with your mobile app. This approach will give you time for a new release, that removes the public key used to sign the compromised certificate, without locking out all your users.
You should always store the backup private keys in separated places, so that if one is compromised you don't get all compromised at once, because then having a backup pin being release with the mobile app is useless.
DON'T DO THIS
Now, I want to have a mechanism in place to update these certificates without requiring to roll out an app upgrade in case certificates are expired or private key is compromised. How can I implement that?
Unfortunately the safer method to deal with a compromised private key is to release a new mobile app that doesn't trust on it anymore. Any remote solution you may devise to update the certificates will open the mobile app doors for attackers to replace the certificates you are pinning against.
So my advice is to not go down this road, because you will shoot yourself on the foot more easily than you can think off.
One possible solution I am seeing is through app notification. I can broadcast a notification with new certificates and store them in the client. Is there any problem in this approach or is there any better approach?
While the mobile app have the connection pinned it can be bypassed, thus a MitM attack can be performed and the new certificates retrieved from the attackers server, instead from your server. Please read the article The Problem with Pinning for more insights on bypassing it:
Unpinning works by hooking, or intercepting, function calls in the app as it runs. Once intercepted the hooking framework can alter the values passed to or from the function. When you use an HTTP library to implement pinning, the functions called by the library are well known so people have written modules which specifically hook these checking functions so they always pass regardless of the actual certificates used in the TLS handshake. Similar approaches exist for iOS too.
While certificate pinning can be bypassed is still strongly advised to use it, because security is all about layers of defense, the more you have the more hard it will be to overcome all them... This is nothing new, if you think of medieval castles, they where built with this approach.
A POSSIBLE BETTER APPROACH
But you also asked for a better approach:
Is there any problem in this approach or is there any better approach?
As already mentioned you should pin against the public key of the certificate to avoid lockouts of the client when you rotate the server certificates.
While I cannot point you a better approach to deal with compromised private keys, I can point out to protect the certificate pinning from being bypassed with introspection frameworks, like xPosed or Frida, we can employ the Mobile App Attestation technique, that will attest the authenticity of the mobile app.
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.
Before we dive into the Mobile App Attestation technique, I would like to clear first a usual misconception among developers, regarding the WHO and the WHAT is calling 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.
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 or is not running in a rooted device 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.
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.
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
So I recommend you to switch to pin the certificates by the public key, and if you want to protect against certificate pinning being bypassed, and other threats, then you should devise your own Mobile App Attestation solution or use one that is ready for plug and play.
So In the end, the solution to use in order to protect your Mobile APP and 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.
I'm a bit disappointed about ProGuard.
I am using Gradle to hide my Google MAP API KEYS. I also read this question here Manage Google Maps API Key with Gradle in Android Studio
and did the same. If you follow the accepted answer in this question, your api key won't get obfuscated by ProGuard. The question is why?
There are two good answers. One with ManifestPlaceHolder, one with using #string
Still, if I decompile my app, there is still my weather api key to seen.
I am using private String myweatherapikey = BuildConfig.MY_API_WEATHER_KEY; and it is amazing (in a bad way) how ProGuard DOES NOT obfuscate this, even when using Gradle.
When you do reverse engineering it looks like private String myweatherapikey ="MY KEY IN PLAIN TEXT";
I am trying to obfuscate my keys since days but nothing worked, even using Gradle.
How do you hide your keys ? It really annoys me that all my keys are public, when you decompile my app.
Second question: I think it is impossible to hide your google maps api key. There are 2 keys, one for release-version and one for debug-version. Both of them are stored in src/debug and src/release. You can't hide this, right?
OBFUSCATION
your api key won't get obfuscated by ProGuard
If Proguard or any other tool obfuscates the API key, then it also needs to be de-obfuscated at run-time, otherwise you cannot use it.
No matter if you have an obfuscation mechanism or even an encryption mechanism, an attacker just needs to hook during run-time an instrumentation framework, like Frida, to the code that returns the API after it have been de-obfuscated or decrypted.
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.
Another approach for the attacker is to perform a MitM attack in a device he controls or was able to compromise, and intercept all requests between the mobile app and the backend in order to extract the API key from the header, and you can read my article Steal that API Key with a Man in the Midlle Attack to learn how it can be done:
So, in this article you will learn how to setup and run a MitM attack to intercept https traffic in a mobile device under your control, so that you can steal the API key. Finally, you will see at a high level how MitM attacks can be mitigated.
YES, IT'S PUBLIC
I am trying to obfuscate my keys since days but nothing worked, even using Gradle. How do you hide your keys ? It really annoys me that all my keys are public, when you decompile my app.
From the moment you publish a mobile app into the Google, Apple store or any other store, the binaries can be downloaded and reverse engineered, therefore anything inside of them must be considered to be in the public domain, be it secrets or just code.
Techniques to Hide API Keys and to Reverse Engineer them
My favorite tool to reverse engineer a binary of a mobile app is the MobSF:
Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis.
You can read my article How to Extract an API key from a Mobile App with Static Binary Analysis to understand how this is done and at same time to learn the several techniques used to try to hide an API key, and see how they are easily bypassed:
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.
It's time to look for a more advanced technique to hide the API key in a way that will be very hard to reverse engineer from the APK, and for this we will make use of native C++ code to store the API key, by leveraging the JNI interface which uses NDK under the hood.
GOOGLE MAPS API KEY
Second question: I think it is impossible to hide your google maps api key. There are 2 keys, one for release-version and one for debug-version. Both of them are stored in src/debug and src/release. You can't hide this, right?
If you have read all the links I posted above, then by now you may already have realized that is indeed a Mission Impossible to hide any secret in the binary of your mobile app.
The bottom line is that if is in the binary it can be extracted by static analysis or during run-time.
I am not really familiar with the Google Maps usage in a mobile app, therefore I don't know if its possible to move the calls for it to the backend, because this is what it must be done with any usage of Third Party APIs in a mobile app, otherwise the API key is vulnerable to be extracted and abused, and if you are billed or rate limited based on it, then you may be in trouble when an attacker get hands on your API key.
THIRD PARTY APIS
Currently you are usage of Third Party APIs puts your mobile app in this position:
But preferentially your mobile app should be in this position:
While in the graphics I mention a Reverse Proxy, it could be the backend for your mobile app.
NOTE: The graphics belong to an article that I am currently writing about the use of a Reverse Proxy to access Third Party APIs.
Securing the API keys to access Third Party APIs is much easier when delegating access to them to a reverse proxy or backend we are in control of, and an immediate advantage of this approach is that the API keys for the Thrid Party services are not anymore in the public domain, aka the binary of your mobile app.
So from the graphics we are left with only one API key to secure, the one to access your reverse proxy or backend, where you can employ as many security measures as you can afford to prevent unauthorized access to it.
POSSIBLE SOLUTION
How do you hide your keys ?
Would not be better to not have any keys at all to hide in your mobile app, because that would be the ideal solution. So the above graphic would look more like:
To be in a position where you don't need to ship any secrets in your mobile app you need to resort to the Mobile App Attestation concept, and from this article section I will extract the relevant bits, that explain it's role:
Before we dive into the role of a Mobile App Attestation service, we first need to understand the difference between what and who is accessing the API server. This is discussed in more detail in this article, where we can read:
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.
The role of a Mobile App Attestation service is to authenticate what is sending the requests, thus only responding to requests coming from genuine mobile app instances and rejecting all other requests from unauthorized sources.
In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework(Frida, xPosed, Cydia, etc.), and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.
On a 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 know. In the case that attestation fails the JWT token is signed with an incorrect secret. Since the secret used by the Mobile App Attestation service is not known by the mobile app, it is not possible to reverse engineer it at run-time even when the app has been tampered with, is running in a rooted device or communicating over a connection that is the target of a MitM attack.
The mobile app must send the JWT token in the header of every API request. This allows the API server to only serve requests when it can verify that the JWT token was signed with the shared secret and that it has not expired. All other requests will be refused. In other words a valid JWT token tells the API server that what is making the request is the genuine mobile app uploaded to the Google or Apple store, while an invalid or missing JWT token means that what is making the request is not authorized to do so, because it may be a bot, a repackaged app or an attacker making a MitM attack.
A great benefit of using a Mobile App Attestation service is its proactive and positive authentication model, which does not create false positives, and thus does not block legitimate users while it keeps the bad guys at bay.
The Mobile App Attestation liberates your mobile app to have an embedded secret in its code, instead now it only needs to pass to the reverse proxy or backend the JWT token it receives from the Attestation. Now the reverse proxy or backend can verify the JWT token, and on successful validation they can fulfill requests with a very high confidence that they are originated from what they expect, a genuine instance of the mobile app, with the added benefit of not exposing the API keys to access your Third Party services.
GOING THE EXTRA MILE
I cannot resist to recommend the excellent work done in the OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
I am going to create a Social media Application similar to facebook for both Android and IOS.I have login form where user need to give their uname and password.My server Team is handling webservices.
how to protect uname and password in Android and IOS App.
how to protect uname and pwd on remote ie while transferring from mobile to webservice.(I have an idea of using AES encryption Algorithm)
how to keep webservice url safe inside app(both android and ios)
what are the flaws could happen while creating these kind of app and how to restrict our app from Hackers?
what are the security steps server Team need to implement (they gonna write server in php).
thanks in advance?
Keep the password in the keychain (iOS).
Use SSL to communicate with the server, use POST for the username/password, Pin the certificate.
The webservice URL is public, anyone with a network sniffer will be able to see it.
The major hack will be against the server. Jailbreaking can compromise the app. The keychain is rather immune to jailbreaking.
The main thing for the server is how they handle the user personal information and password. Do not save the password, just a well salted SHA hash of it.
Define the value of the data you are securing from several perspectives: The user's perspective, the value to you,, your reputation, the value to an attacker. Then design the security to the highest level of all perspectives. Keep in mind that high security can be painful to the user. Find a balance.
If you care about security there is only one answer: Have the security designed and vetted by a security domain expert. I always have my designs and code vetted. Such a domain expert will have several years of full-time security experience in this area and possibly a certification such as CISSP. Anything short of this is just a "nice try".
Security bugs are different than normal code bugs. A normal app can have quite a few bugs that are just annoying but still be usable and even a good app. One security bug and there is no security, one security bug is all the attacker needs.