2

My mobile app is using an HTTP-based API with endpoints that aren't hard to figure out, such as https://<domain>/api/config or https://<domain>/api/login.

So someone could create an account in the app, then use the credentials in some request-making desktop app ("rogue client") to send requests to /api/login and then, after "logging in" with my bearer authentication scheme, go on to other endpoints to see what data is being sent from there.

Such attempts could potentially let people peep into some sensitive data about other users that should only be accessible internally by the app alone.

What would be an established approach to improve my app's security in guaranteeing that any data sent from my backend API is accessible by the app only?

Specifically for iOS apps, are there any frameworks to achieve this?

My backend is Nginx & Django.

Desmond Hume
  • 8,037
  • 14
  • 65
  • 112
  • It is not possible. Anything your client has is available to anybody else taking the time to look, so they can come up with another client. But apart from really special cases and interesting apps, nobody will. See my answers [here](https://stackoverflow.com/questions/51800405/protecting-rest-api-behind-spa-against-data-thiefs/51803335#51803335) or [here](https://stackoverflow.com/questions/49929136/verify-authenticity-of-an-client/49929649#49929649) for example. – Gabor Lengyel May 10 '20 at 11:09
  • @GaborLengyel Nope. – Desmond Hume May 10 '20 at 11:16
  • You can only make development of rogue clients harder but totally preventing this is not possible. The one way to do so is at the moment to use HTTPS with server certificate pinning, forced HTTPS client authentication (the cert+private key has to be very well protected within the app) and a highly obfuscated app with anti-debugging, anti-Frida and a lot of other anti-reverse-engineering stuff included. – Robert May 10 '20 at 11:27
  • @Robert Thanks. About `use HTTPS with server certificate pinning`, isn't SSL pinning aimed at making sure that the client is talking to the genuine server backend instead of an imposter server? My question is more about the opposite case: ensure that the backend is talking to the genuine app. About `forced HTTPS client authentication`, I'm not sure what you meant. – Desmond Hume May 10 '20 at 11:32
  • @DesmondHume To understand the communication there are two ways:Reverse the app (offline) and understand which APIs it uses or redirect the traffic between app and server through e.g. mitmproxy so that you directly see all communication. With certificate pinning the attacker first has to break this before he can get access to the transmitted data. `HTTPS cert based client auth`: This is an optional feature of HTTPS that can be enforced by the server. In that case no HTTPS connection can be established if the client does not posses the correct certificate+private key. – Robert May 10 '20 at 11:43
  • @Robert Thank you. As common to most APIs, my app's API uses path naming which happens to be quite unimaginative and easy to guess, one would not even need to reverse engineer the app in order to request the API. I'm not sure if HTTPS allows for sniffing traffic using a proxy, at least not in my attempt using Proxyman app with an iPhone, but gotta check it again. Client Certificate Auth method is interesting, but I suppose that one would need to include a client certificate into the app as a file into, which would be easy to extract on e.g. a jailbroken iPhone and use for a malicious purpose. – Desmond Hume May 10 '20 at 12:22
  • @DesmondHume Sniffing HTTPS on even on a non-jailbroken iPhone is pretty easy. I do this every day. Of course adding a cert+key as file would be a dumb solution. Therefore it should be included into the source code as constant may be obfuscated, split into several parts and encoded/encrypted. That is the way how obfuscation works. – Robert May 10 '20 at 14:18
  • @Robert What tools are you using to sniff network on a real iPhone device? – Desmond Hume May 10 '20 at 15:29
  • @DesmondHume mitmproxy. Just install the certificate and activate it and all traffic is accessible (unless pinned or client cert required). – Robert May 10 '20 at 16:31
  • @Robert Appreciate it. – Desmond Hume May 11 '20 at 08:37

3 Answers3

2

MAPPING AN API

My mobile app is using an HTTP-based API with endpoints that aren't hard to figure out, such as https:///api/config or https:///api/login.

All it's needed to map all the API endpoints being used by your mobile app is for someone to install your mobile app in a device they control and proxy the requests through a proxy, like the mitmproxy:

An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.

BEARER AUTHORIZATION TOKEN EXTRACTION

So someone could create an account in the app, then use the credentials in some request-making desktop app ("rogue client") to send requests to /api/login and then, after "logging in" with my bearer authentication scheme, go on to other endpoints to see what data is being sent from there.

Yes you can create the account in the app and extract the bearer authentication token, and for this you can continue to use the proxy approach I mentioned to map all the API endpoints. You can read this article to see how I use mitmproxy to extract an API key, therefore applicable for your bearer token scenario.

The mitmproxy allow us to intercept, manipulate and replay requests on the fly or at any point in time, therefore an excellent tool to poke around your aPI and extract all data while you use the mobile app as a normal user.

SENSITIVE DATA ACCESS

Such attempts could potentially let people peep into some sensitive data about other users that should only be accessible internally by the app alone.

Well here it seems more like a design problem of your mobile app and backend, because a logged user should never be able to access API endpoints as another user.

Also you need to ensure that each API endpoint strictly returns only the absolute necessary data for the mobile app do what it needs to do. Unfortunately more often then not developers have fat API endpoints that give away a lot of info, and then its up to the consumer to filter the data it needs. Don't do this, instead using roles to authorize what amount of data each logged user as access to in each API endpoint, therefore allowing for more or less data to be sent back in the response accordingly to his role.

Another thing to keep in mind is that developers tend to do too much business logic on the client side, and this approach also leads to fat APIs and to leak data that could be kept in server side if the API was the only one responsible to perform that business logic. Try to design your mobile apps to be as dumb as possible, and make them delegate to the backend all the hard work. This approach also as the advantage of making easy to fix bugs without needing to release a new mobile app.

IMPROVE API SECURITY

What would be an established approach to improve my app's security in guaranteeing that any data sent from my backend API is accessible by the app only?

Well you bought yourself a very hard challenge to overcome, but while hard is not impossible to achieve a solution that allows your API server to have a very high degree of confidence that the requests is receiving are indeed from a genuine instance of your mobile app.

So it seems that you want to lock your API server to only accept requests from your mobile app, and if that is the case then please read this reply I gave 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.

Specifically for iOS apps, are there any frameworks to achieve this?

If you have read the reply I linked above, then you know by now that you should employ security in depth, by using as many layers as you can afford, being the most effective of all the Mobile App Attestation concept.

Bear in mind that has you add more security layers, more time consuming will be for an attacker to overcome all of them. This also raises the bar for the skill set necessary for an attacker to have in order to bypass all of them, thus putting at bay scripts kids and seasonal attackers.

By the way don't forget to always apply strong code obfuscation techniques to your code base.

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 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.

Exadra37
  • 11,244
  • 3
  • 43
  • 57
1

For iOS apps, The correct way is to use App Attestation.

App Attest Flow

You can’t rely on your app’s logic to perform security checks on itself because a compromised app can falsify the results. Instead, you use the shared instance of the DCAppAttestService class in your app to create a hardware-based, cryptographic key that uses Apple servers to certify that the key belongs to a valid instance of your app. Then you use the service to cryptographically sign server requests using the certified key. Your app uses these measures to assert its legitimacy with any server requests for sensitive or premium content.

It is a cryptographically secure way to make sure your app is the thing which is accessing your API and not something else.

Apple has an App Attest service. Official documentations are here:

eastriver lee
  • 173
  • 2
  • 9
Matt
  • 873
  • 1
  • 9
  • 24
-1

Here is the best practice of using JWTs.

On the client-side, you create the token (there are many libraries for this), using the secret token to sign it. You pass it as part of the API request, and the server will know it’s that specific client because the request is signed with its unique identifier

Edit: Based on comments and discussions, reaching to full security is not possible, But you can make it harder using the above blog post practice.

Mahsa Yousefi
  • 206
  • 1
  • 7
  • The problem with using a JWT is that you need to keep the secret, well, secret. Since the secret needs to be in the app there is no way of doing this (You can make it hard, but not impossible to extract the secret) – Paulw11 May 10 '20 at 10:48
  • Of course, you're right. But I think generating token based on user credentials is too fragile. we can make it stronger by above solution. Kindly mention the alternatives you think are better to use. – Mahsa Yousefi May 10 '20 at 10:54