Search code examples
androidiosrestsecurityapi-design

Preventing request replay attack


I have a simple REST API and to prevent the request replay attack. I have added a UTC timestamp with the request and allowing request if the difference in seconds in not more than 60 seconds.

This API is consumed by Android and iOS applications. After moving the app into production, we realized that most of users have inaccurate time and time zone and this prevents them to use the app.

How can I improve the mitigation?

Any chance I can get UTC time irrespective of phone's time and timezone?


Solution

  • You should not rely on the timestamp sent by the device, as it may be easily tampered with.

    If (and only if) you are able to identify requests coming from the same user or device, then you can use the timestamp on the server and do the same mitigation strategy, but this time you have a unified time measure. (You need to save the "last" access timestamp on per-user or per-device basis.)

    A way to identify an user or a device can be that of creating a hash of (e.g. time of first run + IP address + ...) the first time of use, and send that along the REST API request all the subsequent times. If the user is required to log-in, then you could save this value along with the user's info; otherwise you can "identify" the device similarly.

    EDIT: This edit is in light of your comment which adds information that was not clear before

    I want to check if the originating time of the request and the receiving time on server should not have large interval (say more than 1 minute).*

    Rephrasing, you want to invalidate requests based on their generation time (not older than 60 seconds). If now I interpret it correctly, the idea is that very likely client's requests would need much less than 60 seconds to be answered, so the assumption is that too-old a message was very likely already consumed properly - it might be a reply attack.

    Unfortunately, your solution would only (predictably) reduce the space of messages that the attacker can use to carry out reply attacks, that are therefore far from being prevented, even with synchronised timestamps. Additionally, if the message can be tampered with, i.e. the attacker can freshen old messages with newer timestamps, the the mitigation would be totally ineffective.

    Anyway, if your purpose was not that of preventing reply attacks, but to simply discard expired messages, then you can achieve your goal by offering two REST APIs:

    1. one for "preparation" (you do not even need to collect a reply)
    2. the other for the actual "request"

    and both with client's timestamps and with the same request identifier.

    So you will see server side the two pairs timestamp-requestID: (t,ID) and (t',ID). This will allow you to simply make the difference of timestamps, t' - t, which is independent on the time shift or time zone they set up. You can also time the requests server-side to discard the "request" arriving too late related to their corresponding "preparation".

    Additionally to improve security, you might let the client App sign the messages (including the timestamps and the request ID) to guarantee integrity - the messages cannot be tampered with without noticing, so that you can rely on timestamps sent to the APIs. One way is to use public-key cryptography, but be careful on how you distribute public keys. (This way you limit the attacker to reply only the most recent requests).