2

We have an Android app that sends some data to a web service, and then the web service saves it on a MySQL database. We want to avoid people using the web service if it is not from within the app itself. I mean, we want to make sure that no one can perform a MITM attack on our app and then send requests from somewhere else to our web service.

We came up with the next idea:

We include a passphrase both on the Android app and on the web service, then with each request to the web service a token using such passphrase and current timestamp is generated in this way:

// Pseudo
String token = md5(private_passphrase + (timestamp / 60));

The generated token is then sent to the web service, which generates another token the same way and compares them. If both are the same, it allows the request.

The idea is that, even if someone sniffs packets sent from our app, they will not be able to use the same request later from some other source.

How good and secure is this solution? Our concern is more about not letting others use our service from outside the app, not about securing the data we send.

Pablo PHG
  • 27
  • 5
  • What happens if the clocks on the two devices aren't in synch, or if there's any network latency? – Mark Baker Apr 14 '15 at 08:55
  • @MarkBaker server checks multiple possible tokens in a given time offset (right now it is on 5 minutes). And if it still fails for any reason, the server sends back it's current timestamp so the client can build up the request again, using server's timestamp. – Pablo PHG Apr 14 '15 at 10:57

2 Answers2

2

The question I would ask you is what specific attack vectors you're trying to protect against:

  1. Network-based exploit

    This will not protect against an attacker making fake requests. They just need to intercept 1 request, and then they'll have 60 seconds (well, on average 30) to make their requests using the same token.

  2. Long term network-based exploit

    This is will sort-of protect against an attacker making fake requests in the long term. Since the generated token is invalidated quickly, an attacker needs to get a token for each time period of requests they want to send.

  3. Generic protection

    This will not protect against generic attacks. If you store the private passphrase in the APK of the app, then an attacker can just reverse engineer the APK to get the passphrase, and hence generate any valid token they want. Game over.

The Better Way

Since you explicitly say "MITM", I would recommend you use TLS (HTTPS) for all of your communication. In fact, you could use certificate pinning in the app to ensure that you're connecting to the server appropriately.

You can never fully be sure that a request comes from your app. So instead, you just need to be able to flag abusive users. This answer suggests a great way of doing that.

However, be sure to use HTTPS for all traffic as a baseline, otherwise any "protection" you try to layer on top is simply not going to work.

Community
  • 1
  • 1
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
0

Well, depending on how you generate your timestamp, a division by 60 will not necessarily give you what you want. I guess you want to get some kind of "minute window". Timestamps are usually in milliseconds, which means you need to divide by by 60000.

If an attacker finds this out, which is actually not so hard as you might hope for, this is easily spoofable.

Furthermore, if the clocks on both sides are off by more than a minute, your system will see this as an invalid access attempt, and deny access. This also is valid for timezone changes, when one of your clients suddenly switches timezones, for whatever reason, may be business trip.

There are a number of one-time pad algorithms and libraries out there, which deal with this problem without involving timestamps, just search for "one-time pad" using google.

Mjoellnir
  • 486
  • 5
  • 11
  • I know, about milliseconds, that was just for the example. On the server I generate multiple tokens with 5 minutes offset and compare all of them. Timestamp is always obtained for the same timezone, and if match fails, server sends back it's timestamp, so the client can build the request again using server's timestamp. I am interested on how would this be spoofable. Right now tokens are getting validated OK. I just want to know if I can rely on this or not. – Pablo PHG Apr 14 '15 at 10:49
  • Which is basically an invitation to spoofing with the recipe how to do it already included. So I just send garbage to your server the first time, get the response right and bang I'm in on the second attempt. Whoops. – Mjoellnir Apr 14 '15 at 10:52
  • You are still not in because you wouldnt know the private passphrase, am I wrong? Server would just return you a timestamp in the first attempt. – Pablo PHG Apr 14 '15 at 10:58
  • Right, but md5 isn't that hard to break nowadays. It is prone to collisions so I can brute force my way through it. You should consider the otp approach. Your use case is one of the reasons it was created :) a 2nd option could be using https. Using that would push all the trouble to the transport layer. The web server. The app will have almost no additional trouble. – Mjoellnir Apr 14 '15 at 11:03
  • A 2nd option would be to move this into the transport layer by using https. The app wouldn't require so many changes. And on server side...you can configure it to to accept connections only when they properly encrypted. Then you have your password...or better you should use a user specific one...and due https it is armored and not replayable. MITM is also difficult. Impossible...well that term is always a bit too absolute when it comes to security :) – Mjoellnir Apr 14 '15 at 11:27