3

I have a login page, where user logs in via his mobile number, He gets an OTP send via backend server, once he enters a One-Time Passcode (OTP), we hit an API like this:

https://backend.com/api/login?mobile=9123123123&otp=1234

My question is this good enough from security point of view or should I encrypt both mobile number and OTP via some algorithm and send those like following:

https://backend.com/api/login?authToken=jshfkasfasfbmsabvj&authKey=amsfgjkashfkashjfjasgfkjahsfkj

where authToken is encrypted mobile number and authKey is encrypted OTP.

What are good practices regarding this, what are good encryption algo, which can be used here?


Few suggestions came to use https, which indeed I am using but missed to have in the question somehow. What my concern is someone can figure out the API, and start hitting with different combination of OTPs for mobile number and gain the access of a account.

  • 5
    Step 1: use HTTPS. That way, any query params in the URL are already encrypted, without you having to do any extra steps. Please don't try to invent your own encryption scheme. – amon May 19 '17 at 13:38
  • @amon Thanks for the reply, I am already using https, Please see my edit. – Saurabh May 19 '17 at 15:34
  • I agree with @amon. You don't need more than HTTPS. – BlueWizard May 20 '17 at 17:14
10

What my concern is someone can figure out the API, and start hitting with different combination of OTPs for mobile number and gain the access to an account

This is a frequent question related to the security of web applications. Once our APIs are public, they are exposed to all sort of malice.

Besides the https, which should be mandatory, here some measures you should consider too.

Thresholds

Setting a max number of request per second and source (remote address). Let's say X Req/s per IP address.

Thresholds are commonly implemented in the API Gateway or in the Authentication server. Many API Managers provide control of thresholds out of the box.

The point is, the number of possible combinations of phone/otp and their respective permutations will be usually greater than the threshold, what reduce the possibilities of hitting a valid tuple or at least, it make it harder.

We can set endpoints with different thresholds. Usually, endpoints related to the security will have lower values than those related to the business.

Hitting the threshold causes ban. The ban last as long as you want (1, 5, 10 min, ...). If you like blacklists this is the right place to add one.

Study cases:

Opacity

We often think that we should provide as many info as possible to the user when errors happen. That's ok when we speak about business rules, but it's not when we speak about security.

If the login process fails, a simple Invalid credentials should be enough. Don't tell to whoever is on the other side of the wire the causes of the error.

Making your security opaque to the externals reduces the attack surface.

Authentication tokens

I would encourage you to don't reinvent the wheel, overall with security. JWT.

It's a plus if you can force the expiration at will from the backend.

Study cases:

Traceability

Https connections are encrypted. However, the query strings can be traced in log files once the message has been decrypted. So, doesn't matter if the query string values were encrypted twice. I would suggest sending POST request for authentication processes. Do it for any other request that may transport sensitive data.

Certificate validation

As prevention to MITM, checking if the server certificate matches the server's domain is a plus.

Awareness

Security is serious business. Keep yourself up-to-date and well documented. Here a good place to start working. OWASP - Categories.

Here some interesting projects:

  • JWT deserves a well earned +1 – Christophe May 19 '17 at 18:53
  • Well, not reinventing the wheel in general worth it. Overall in security. – Laiv May 19 '17 at 18:56
  • I overall agree with your answer. But "Make your security opaque to the externals." is security throu obscurity. – BlueWizard May 20 '17 at 17:16
  • Well, I intendedly overstated the term. I think that giving back too much info about the failures produced at security layers is like giving a detailed map of the vulnarebilities to exploit. If I set a threshold, I would not tell to the user "You have reached 60req / s, wait 20min for the next try". I would not even care in returning a 429 http status. I would probably return a random 4xx. – Laiv May 20 '17 at 17:23
  • Ofcourse the policy around this subject is different if I sell my API as a Service. Usually my APIs have only one or maybe 2 consumers: the apps and the web portal and both are implentated with the security constraints in mind. Everyone else is an "external" I don't trust in. – Laiv May 20 '17 at 17:27
1

There are two main points of attack against your system:

1) the transport channel, which could leak access details (number + password)

2) your API which could allow an unknown node to repetitively guess the credentials, for a given phone number

How to protect ?

  • As said in the comments, encryption of number and OTP is not sufficient to protect against 1: because if your API takes encrypted input, the attacker just has to intercept the encrypted version.

  • https completely avoids 1, except if someone spoofs your server address and manages to play the man in the middle (MITM). It would therefore be safe for your client application to not simply use https, but also check if the server certificate matches the server's domain

  • Encryption of OTP of phone or both, does not in principle protect you against 2: If your OTP 1234 is encrypted to xEHg, it's only a matter of time before the encrypted version gets guessed. The following will increase your defense:

    • use longer OTP (8 seems a minimum)
    • let the OTP live for a shorter time frame (If the OTP changes every minute, it'll be too short for guessing millions of combinations)
    • if an IP address makes more than N wrong guesses, block that IP for a certain amount of time
    • if there are more than K wrong OTP guesses for a given phone, either block the originating IP address a certain amount of time, or notify the user about the risk or both

These measures will defeat OTP guessing.

1

Beyond what Amon says: NEVER use http. Always use https. That way everything is encrypted and you know it goes to the right destination.

PS. What Burghardt says is wrong. He claims that the parameters in an https request are sent unencrypted and shows a Firefox history as evidence. But Firefox has sent the https request, so Firefox on your machine knows the parameters and can record them - but then they are encrypted before they are sent out.

  • 1
    Exactly ! No https means that Encrypted OTP can be hijacked for a replay (e.g. Simply sending the hijacked info without decrypting its content) – Christophe May 19 '17 at 14:59
  • @Christophe @gnasher729 I am using https only, I missed that when adding in question, I updated it. Also why only https seems not completely secure to me, as someone can find the API and start hitting it multiple time for a mobile number and different OTP combinations. – Saurabh May 19 '17 at 15:30
  • @gnasher729: Not everything is encrypted. See my answer, and the update I made with a screenshot of my Firefox browser history. – Greg Burghardt May 19 '17 at 18:12
  • but then they are encrypted before they are sent out. This should be easy to test, for instance doing a MITM. A way to do is with Webscarb or similars – Laiv May 23 '17 at 6:37
0

First off, I'm not a security person. So anything I say here may or may not be stupid.

My first thought was that if you don't encrypt the mobile number then any 3rd party can suck up the data stream and harvest information that directly links a publicly known identifier with a user of your system.

This may or may not impact the inpenatrability of your API, but it does has the potential to affect your users.

EDIT

See .. I knew that caveat should have come in handy. I didn't spot the http vs https issue!

  • Yes, I have similar concern, Please see my edit in question. – Saurabh May 19 '17 at 15:35
-2

The problem from a security standpoint is the One-Time Passcode and mobile number are being passed as query string parameters. If the information is deemed sensitive in any way, don't use a GET request with query string parameters. Use a POST request and pass the parameters as part of the request body, and encrypt it using HTTPS.

HTTP + GET = Security problem

HTTPS + GET = Same security problem

HTTPS + POST + Passing parameters in the request body means the data actually gets encrypted and isn't visible in someone's browser history, or the log files of the destination web server for the request.


amon commented:

Could you please explain why HTTPS + query params in the URL is a security problem? As far as I understand, HTTPS encrypts the complete payload incl. headers and the URL during transit. The only info that can't be encrypted is the server hostname.

Have a look at your browser history. Here is a screenshot from Firefox of my recent browser history:

Screenshot of Firefox browser history window showing HTTPS URLs with query strings, unencrypted

As you can see, I visited https://codereview.stackexchange.com/questions?sort=newest. The ?sort=newest part is the query string... on an HTTPS URL. Visible in my browser history, including access logs on the destination web server itself.

  • 2
    Could you please explain why HTTPS + query params in the URL is a security problem? As far as I understand, HTTPS encrypts the complete payload incl. headers and the URL during transit. The only info that can't be encrypted is the server hostname. And the browser history isn't a problem for a one-time password. – amon May 19 '17 at 17:45
  • @amon: I updated my answer to address your question. – Greg Burghardt May 19 '17 at 18:06
  • Well, that would require to the attacker to have access to your pc, but it's fair enough overall if we assume that the average user doesn't care too much about security. – Laiv May 19 '17 at 19:38
  • 1
    @Laiv: Or the attacker gains access to the destination web server. And it is because most users don't care about security that we do things like, never ever ever ever ever for any reason, no matter how good it sounds... pass ANYTHING sensitive in a query string. :) – Greg Burghardt May 19 '17 at 20:21
  • 1
    @GregBurghardt: The main premise of your answer is wrong, and that's it. The information is encrypted. https does what it promises: Encryption between sender and receiver. Your other arguments fail, since there is confidential information that needs to be transmitted, and if it isn't handled properly you have a problem - whether this happens in the URL or the body. – gnasher729 May 23 '17 at 4:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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