问题
It's probable a newbie question but I'll try to create an interesting debate.
I know there's some authentication methods for API Basic Authentication, API Keys, OAuth 2.0 ... all of those methods add a header or a formData param in the request.
Although you use SSL, it's "usually easy" to hack mobile apps (I'm thinking in Android right now: decompiling the app, changing manifest to allow custom SSL, compiling again and sniffinf through a SSL proxy all the requests).
In those request I've found a lot of auth keys that I can use in other calls from a console, simulating the app with no problems.
So, now I've hacked some API's in mobile apps, my question is: is there any way to secure an API in a mobile app?
I wonder one securization layer would be to limit the number of request per "key".
Am I wrong ? Am I missing something ? Is this a stupid question ?
回答1:
Am I wrong ? Is this a stupid question ?
No you are not wrong, and it's not a stupid question at all, because it's indeed easy to attack an API server of a mobile app, and you will be surprised to know how many senior developers are not aware how easy it can be done, and I have noticed that more often then not, this is due to their misconception about what vs who is accessing the API server.
The difference between what and who is accessing the API server.
This is discussed in more detail in this article I wrote, 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.
So if the quoted text is not enough to clarify you, then please go ahead and read the entire section of the article.
Impersonating the Mobile APP
In those request I've found a lot of auth keys that I can use in other calls from a console, simulating the app with no problems.
If by auth keys
you mean the ones provide via user sign-in, with his username and password, then they just identify the who in the request.
For other keys, like api-keys
, acess-tokens
or any other convention used to name them, they have the purpose of providing to the API server a mechanism to only authorize requests from the genuine mobile app, they are indeed trying to allow the API server to identify what is doing the request, and has you already discovered it's easy to extract them with a proxy:
Although you use SSL, it's "usually easy" to hack mobile apps (I'm thinking in Android right now: decompiling the app, changing manifest to allow custom SSL, compiling again and sniffinf through a SSL proxy all the requests).
So in the end of the day all an attacker needs it's to use a proxy to learn how the API server works, and what is needed to simulate an API call as if it was done from the mobile app itself.
Securing the API Server
So, now I've hacked some API's in mobile apps, my question is: is there any way to secure an API in a mobile app?
You can use Mobile Hardening and Shielding solutions, that will try to prevent the mobile app to work in compromised/rooted devices, with modified/tampered apps and/or when some instrumentation framework is being used during runtime, but all of them have the draw-back of performing all that decisions in the mobile app, therefore subject to be manipulated or totally bypassed by the alreay dito instrumentation frameworks, and a good example of one it's 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.
While is better to use an in app solution, than not using anything, it's still not the ideal solution, because the control of deciding what to do is in the client side, not in the server side.
A Possible Better Solution
The current implementations of a mobile app and API server may look like this:
This approach is what leaves the API keys vulnerable to be extracted by attackers via proxy interception(red line), just like you already noticed by using a proxy to intercept them.
A better approach would be something like this:
Wait, but I don't see any API key in the mobile app anymore:
Am I missing something ?
Yes, a Mobile App Attestation solution.
To be in a position where you don't need to ship any secrets with your mobile app, then you need to resort to the Mobile App Attestation concept, and from this article section I will quote the relevant parts to explain it's role:
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 releases your mobile app from having 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 mobile app attestation service. Now the reverse proxy or backend can verify the JWT token, and on successful validation they can accept requests with a very high confidence that they are originated from what they expect, a true and genuine instance of the mobile app, with the added benefit of not exposing the API keys to access your API server or any Third Party services.
GOING THE EXTRA MILE
I cannot finish without recommending you 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.
来源:https://stackoverflow.com/questions/60559419/how-to-secure-an-api-rest-for-mobile-app-if-sniffing-requests-gives-you-the-k