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.