3

I read a lot that you can't restrict your Public REST API to only your mobile application, but I have an idea and I want opinions on it:

Variable App Key Method

Mobile App

  1. Get IP address of current connection
  2. Use a secret algorithm to generate a hashed AppKey from IP address.
  3. Send the AppKey with each API request

Server Side

  1. Check the IP address of incoming request
  2. Generate AuthKey from that IP address using same secret algorithm.
  3. Compare AuthKey with AppKey, if they match then you know that your Application is talking to you, because only the application knows the secret algorithm.

When IP address changes:

  • On mobile App regenerate the AppKey using the new IP address
  • Server side will always generate same key because it depends on IP address of the request

The main advantage of this is that the AppKey will always change, which is better than hardcoding 1 application key inside the code, which can be easily stolen by reading request headers. And even if you stole the AppKey from a user you must be using the same IP address where that key was generated.

Any thoughts?


Conclusion:

Relying on the IP address is problematic because you will need to call an external API to return back your correct IP address, and you will have to do that before every request because IP addresses change all the time.

Second problem is that internet connection on mobile switches a lot from WiFi to 3G to 4G, which will lead to unstable application behavior.

3
  • 2
    "Use a secret algorithm to generate a hashed AppKey from IP address." How do you propose to keep it secret if the app is installed on someone else's device?
    – John Wu
    Commented Apr 25, 2018 at 0:08
  • By obfuscating JAVA code to make it harder to decompile. Or using a compiled C++ code and integrate it with Java somehow.
    – DeepBlue
    Commented Apr 25, 2018 at 0:39
  • Auth based on Push.
    – Sentinel
    Commented Apr 28, 2018 at 0:57

3 Answers 3

4

Although it is certainly the case that generating a dynamic access key based on the IP address will improve protection, there are a number of problems with this approach:

  1. You can't actually assume that the IP address of a mobile device is very stable. This would mean that the IP address could change and then cause the requests to be rejected. Moreover, you need to query another service via an API to even find out the public facing IP address of the device is (it doesn't know because it might be behind NAT). Certain modern mobile networks can load balance requests address multiple IP addresses, which may mean you get a different external IP for each request.

  2. The algorithm to calculate the key can be reverse engineered from your app and then abused. So you still need to worry about how well protected it is.

  3. Probably the most important of all, this doesn't actually protect abuse from the same IP address (e.g. devices on the same network behind NAT). An attacker simply needs to capture the good AppKey by a Man-in-the-Middle attack and then they could use it any script or other apps they wanted successfully from the same IP address.

In my opinion, the better approach is to embed a secret in the app which can then be used in an HMAC calculation along with the API request parameters to show that the request is coming from your app. Of course, you are still subject to the possibility of this secret being reverse engineered from your app. There are then a whole series of different protections you could use to try and prevent that.

I work for a company that specialises in exactly this area - protecting backend APIs that are used by mobile apps so that they can only be used by the official app. You would be surprised the types of business attacks that can be mounted by spoofing requests and the lengths that some attackers will go to in order to mount such attacks. We have a very detailed blog series here that walks you through all the different levels of protection that you can apply in your app that I think you will find useful: https://www.approov.io/blog/practical-api-protection-walkthrough-part-1.html

6
  • "the better approach is to embed app secret in the app", but that is exactly what I am doing the "app secret" is the dynamic app key I am generating.
    – DeepBlue
    Commented Apr 25, 2018 at 19:35
  • @DeepBlue, the difference is that I am proposing that the secret is used to sign the whole request message, not the IP address that can change. By using HMAC and a secret this means that only your app can generate validly signed requests (unless the secret is compromised from the app, which is the next problem). All this is covered in our API protection walkthrough referenced above and also in approov.io/blog/simple-app-authentication.html Commented Apr 26, 2018 at 8:35
  • U said the algorithm can be reverse engineered, so the secret inside the App is even easier to get by reverse engineering. So the problem is the same, at least in an algorithm it is harder.
    – DeepBlue
    Commented Apr 26, 2018 at 10:12
  • 1
    @DeepBlue I agree that a secret algorithm is better than just a secret value, as it will be harder to reverse engineer. My main point is that you don't want to just lock down to the IP address. both because it may change and because multiple devices can share the same IP address. You can have a secret algorithm that takes the whole request and then generates a signature derived from it to be sent with the request, that locks it down to that particular request and not just the IP address. See this that discusses these types of issues/approaches youtube.com/watch?v=lgAEJwgxe0Y Commented Apr 27, 2018 at 11:26
  • + for the idea of signature derived from request.. I really liked it.
    – DeepBlue
    Commented Apr 27, 2018 at 21:55
6

Some comments

  1. Your mechanism relies upon the secrecy of an algorithm, a technique known as security through obscurity, which is almost universally deemed a bad idea.

  2. It is not likely you will be able to obfuscate your code enough to prevent reverse engineering, especially in light of the wide variety of deobfuscators available on the internet.

  3. Even if a hacker couldn't deobfuscate your code, he could run the app in a mocked network environment (where he can set the IP address to anything he wants), use your app to generate key hashes, and use those in a replay attack.

  4. Your app is not likely to know its visible IP address, and your service is not likely to know the app's local IP address, so it would be hard to get things to match up. The app could potentially pass through its local IP address as part of the request, but of course that voids the whole security mechanism, as it would be trivial to change it.

  5. Even if you got your mechanism to a point where it is secure, nothing prevents a hacker from using your app and modifying part of it in order to execute his own code.

  6. In general it is a very bad idea to roll your own security.

Edit:

  1. Maybe your mechanism would slow down the first hacker to try to hack it. But all it would take is for one guy to figure it out and upload the crack to a hacker page. Then it's game over and your mitigation is worthless.

  2. Because you are not issuing keys per user, there is no way to black list or block any key that is compromised. You can only block everyone or nobody. This makes your mechanism significantly worse than the standard pattern of issuing keys per user.

2
  • Nothing is 100% secure, there is no security method that we can call it totally secure, but we can call it secure enough. My method will raise the bar and make it need a lot of time and effort to crack the key.
    – DeepBlue
    Commented Apr 25, 2018 at 11:48
  • Regarding IP address it will be tricky, the only way to get correct IP in all situations is to use some sort of service or a separate API that have one task which is to return your correct IP address.
    – DeepBlue
    Commented Apr 25, 2018 at 11:50
2

In short, you cannot tell one unknown device from another unknown device, especially if the latter tries hard to impersonate as the former.

The standard method is to generate a per-device key. Make the user register the app as a part of an initial workflow, and link it to the user's or device's identity somehow.

Now each API connection has an unique key. You can throttle its usage (to share API access more evenly between customers), you can crawl haxx0r forums and ban keys found there, etc.

You cannot make a really good distinction between "mobile" and "desktop", though. Is a phone working via a wifi connection to a wired network "mobile"? If so, how is it different from a tablet / laptop / desktop / server doing the same? If not, how do you explain it to a user of the mobile app that (s)he's "not using mobile access"?

2
  • The standard method is to generate a per-device key, I agree, but it is same method I am proposing but in my case it is a dynamic key,
    – DeepBlue
    Commented Apr 25, 2018 at 19:33
  • 1
    The problem is that your key is generated on device, that is, you trust the device. So the device can cheat. In the above workflow, your server issues the key and links it to a harder-to-forge identity, like a Google / Apple account, a phone number, or an email. OTOH if you don't need that level of accountability, you can just generate an UUID on a mobile device, no need for crypto stuff. Can help throttling / banning, including throttling multiple keys from the same API; won't help against a distributed attack.
    – 9000
    Commented Apr 25, 2018 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.