9

This may sound like an open ended question, but I would like to take my chances and understand if there is any way the rest of the community is handling this issue.

Let's say there is an app that allows users to sign up using their phone number.

App platform

  1. Android
  2. iOS

App flow

  1. user opens the app
  2. he is presented with a login/register button user
  3. now wants to sign up as he is a new user. So he clicks on the register button and he is asked for his phone number
  4. when he submits his phone number, he receives an OTP via SMS. Say the app actually calls the /register API which is the one that triggers the SMS.

Risk: Now for every outbound SMS, there is a financial cost involved.

Proactive/reactive mitigation measures

  1. The API is rate limited (based on the phone number)
  2. There is proper monitoring and alerting in place. So if at all there are abuse instances, extreme measures like IP blocking can happen.

Issues

  1. If an adversary (potentially a competitor) hits the API with different phone numbers, the rate limiting logic is easily bypassed.
  2. IP blocking may not be viable all the time. Say if the adversary is behind a NATed network, all genuine users behind the network also get blocked from doing any successful sign up.
  3. If the adversary changes IPs (maybe using Tor), mitigation step 2 mentioned above also gets bypassed.
  4. Captcha is not a solution as it destroys UX, especially when dealing with mobile apps.
  5. Having username password instead of OTP for registration verification is not an option because the app needs a verified phone number to function.
  6. Per device signature can also be used as a factor to rate limit on, but the fact is that too comes from the device over HTTP(s). Hence, easily changeable as well. So this option is also ruled out.

In such a situation, how to protect against the risk or maybe plan and be prepared for it, if at all it can not be sorted ?

  • Does your setup actually require the sms part? We currently use FreeOTP which is an app on your phone that will generate OTP's for certain accounts. (freeotp.github.io) – Nomad Mar 13 at 15:15
  • 1
    If the UX allows, you can do the phone number verification only after an account is created with standard email verification techniques. This creates a significant amount of extra effort for the attacker with almost no (per-transaction) cost to you. If you add rate-limits/blocking rules/etc. based on email domains as well as IPs. There are also captchas that don't require user input (I think they work on input timing/etc.) – Jens Ehrich Mar 15 at 15:22
  • 1
    CAPTCHA should be your solution, but only show the captcha when you're in a throttled state due to attack. – meagar Mar 15 at 15:34
2

Email Verification First

If your UX allows, you can require the user to first create an account based on their email address. Once the address is verified you can allow adding a phone number and then verify it your usual way.

A legitimate user likely has an email address already, and therefore the setup remains easy. However, an attacker would have to create a new functional mailbox (or alias) for each attempt. By rate/max limiting the phone verification by email domain, you ensure they can't automate this easily. Free mail services generally already prevent automated account creation, and you can blacklist ones that don't.

Use Invisible CAPTCHAs

There are CAPTCHAs that don't require any user interaction that you can use as well during your onboarding, for exmple: https://developers.google.com/recaptcha/docs/invisible

0
+100
  1. Then you need to rate-limit by IP (see 2)
  2. Then you need to choose a limit that makes sense (for example; how big is the chance that you get 10 registrations from the same IP within an hour? Or maybe 1000 per day?). Take a reasonable number per interval, add a little extra to be on the safe side (but also keeping things within budget(s))
  3. You can block TOR/Proxy/VPN IP's. If you don't want that, you can rate limit such IP's with different (more strict) limits (also see 4)
  4. There are non-intrusive (or less annoying) captcha's than the eye-watering blurry wavy texts. Also; you could only show captcha's on TOR/Proxy/VPN IP's
  5. -
  6. You can't trust client data. Never trust client data.

There are databases of known (open) Proxy's and TOR exit nodes available. Some more reliable than others, but they also come at a cost (though there are free databases available).

Also; depending on volume there's bound to be some false positives/negatives. Come to terms with the fact that you'll never get this 100% correct. So provide a way for legitimate users to get help / register in another way should they be identified as illegitimate or unjust ratelimited. Also provide an easy way for you / whoemever is managing the website/service to add (and remove) IP's (or phonenumbers) to (or from) a blacklist that DON'T get flagged but should be.

0

There's a couple things I'd do to increase risk mitigation.

  1. Don't think of the Captcha as always on, or always off. Turn it on based on the rate of attempts per IP address. Think of it as something like a greylist. Affecting the UX is likely better than blocking entirely. You can then consider further blocks (total IP blacklisting for instance) based on failed captcha/higher rates.

  2. Whatever mitigations you put in place are going to have workarounds or attack modes you didn't account for from dedicated attackers, so you need something in place to protect/alert against this possibility. You should consider placing a rate limit on the outgoing SMS to only allow a certain amount of cost per unit time, or potentially alert staff members to respond to such an attack when the costs reach a certain threshold.

    This would further protect you against bugs in the software itself that might generate loops, duplicates, etc that and send out large amounts of erroneous SMS messages, rather than just malicious, intentional attacks.

0

There is not a solid way of getting the phone number without OTP, unfortunately. However, you can get the deviceID() of the android phone. This will give you a valid IMEI number. First, check this number with a server of yours and see if there's something fishy about it.

You can also use other data anonymously. For example, if your application uses READ_CONTACTS or READ_PROFILE permissions, you can use the data there to identify fake users. (e.g. phone only has starter apps, same IMEI but keeps sending different sms numbers.)

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.