Preventing fake accounts - security

I'm working on a simple web service that allows users to sign up for free and upload a small amount of data. I can easily establish a quota for each user, but malicious users could create fake accounts to upload as much data as they like in a denial-of-service attack.
Obviously, there's no perfect defense against this type of attack, but what can we do to mitigate this problem?

Tie it to a more-or-less unique identifier (phone number, bank account number, facebook/google/etc account) or to a finite resource (such as time, by using a captcha).

use a captcha on account creation to ensure that it's a
human and not an automated process.
require a valid email address and require that they click a link in their email to validate that that's their email address and continue the registration process. This cuts down on their ability to create many throwaway accounts because you can limit them to only having one account per email address and they have to then create a new email address for each account they want to create.

When the user signs up, the user supplies a valid email. Most accounts are not enabled until a response has been received, usually by clicking a link in the body of that email. When that click-through is received, you should be able to grab an IP address. That should help you curtail an abundance of casual DOS attacks.

Consider Phone Number Verification
Requiring phone number for account creation is the best approach I've come across; Creating a new email or cycling an IP address is pretty trivial, but genuine sms phone numbers cost money to activate & grant your service the ability to restrict access by country-code.
An important caveat: Virtual phone numbers (like google-voice), temporary-phone number services, & burner phones can make sms-verification ineffective at preventing duplicate user accounts. Depending on your use case, it might be worthwhile to use a service, like Vonage's Number Insight api, that lets you identify those types of numbers.
Authillo is a passwordless authentication provider that prevents duplicate/fake accounts by leveraging sms verification, liveness detection, & facial recognition. Depending on how critical it is that you prevent fake accounts on your service, their base plan might be what you're looking for.

Just log the IPs and assume the same user if the IP does not change within a time interval. This is bad, because it would prevent multiple users in the same house (same IP) but it is a good start.

Related

How to handle incomplete stripe connected account onboarding?

I am after the best practice for handling incomplete stripe connected account onboarding.
When onboarding goes smoothly, everything is simple. But there are fiddly edgecases everywhere, which results in a lot of permutations of values for account requirements
These include
current_deadline
currently_due
disabled_reason
errors
eventually_due
past_due
pending_verification
This creates a lot of complexity.
I need a simple way to:
figure out if the connected user needs to be notified of something (i.e. that they need to give more info), and
what to tell them.
My current strategy is to check if errors is empty, and if not, simply display them along with a link to manage the user's stripe account so they can address the errors.
But I'm worried this strategy will miss things (perhaps minor things that could be addressed before they become errors).
TL;DR I suspect most users will onboard without any problem, but for the few who do have issues, I want to ensure the app notifies them that they need to address them. What is the best way to do this? (using the information in requirements or other info)
When handling identity verification manually using the API, a simple way to check whether your connected user might need to be notified to provide more info is to look at the charges_enabled and payouts_enabled properties on the user's account object. If either of these two properties are false then you might need to reach out to the connected user for more information.
In cases where the connected user's charges and payouts are disabled, you would use the disabled_reason property on the requirements hash to learn the reason why charges and/or payouts are disabled. The possible disabled reasons are all documented here, but I'll list them out nonetheless:
action_required.requested_capabilities You need to request
capabilities for the connected account. For details, see Request and
unrequest capabilities.
requirements.past_due Additional verification
information is required to enable payout or charge capabilities on
this account.
requirements.pending_verification Stripe is currently
verifying information on the connected account.
rejected.fraud Account is rejected due to suspected fraud or illegal activity.
rejected.terms_of_service Account is rejected due to suspected terms
of service violations.
rejected.listed Account is rejected because
it's on a third-party prohibited persons or companies list (such as
financial services provider or government).
rejected.other Account is rejected for another reason.
listed Account might be on a prohibited persons or companies list (Stripe will investigate and either reject or reinstate the account appropriately).
under_review Account is under review by Stripe.
other Account isn't rejected but is disabled for another reason while being reviewed.
Using the disabled_reason, you can assess whether the user needs to be notified with a request for more information (i.e., requirements.past_due), whether they need to be notified for another reason (e.g., rejected.listed), or whether you need to make programmatic changes to the user's Stripe account (e.g., action_required.requested_capabilities).

SMS verification : what if user phone number changed?

I’m building an application and I’m thinking about asking user phone number to send a verification SMS. Though, imagine if the phone number is cancelled and attributed later to someone else. Then, the new person would be able to connect to my app in the name of the old one...
So is there any way to prevent this behavior ?
I want to make it like tinder : sign up possible by 2 different ways : (facebook connection and phone number) or (phone number and mail)
I have another question : I see that many sms sending services are not free (all of them actually). If I make an api with these services, anyone can send a lot of http request to it and make me pay 0,05€ times 100000000 ? And I can’t rely on IP adresses because with 3G an ip is not associated with a particular person...
To your first question:
You are describing Two Step Authentication (aka Two Step Verification) which you can read about in the Wikipedia page: Multi-Factor Authentication (MFA):
a method of confirming a user's claimed identity by utilizing something they know (password) and a second factor other than something they have or something they are. An example of a second step is the user repeating back something that was sent to them through an out-of-band mechanism.
You are correct that a phone number can change owners (as can an email address though over a longer time period on average). You are using their phone number as that out-of-band mechanism described above.
If the user has recently authenticated with their password, when you send the user an out-of-band code and they re-type that into an input box you have some degree of confidence that the end user both knows the password and has access to the SMS message and are choosing to trust that association.
You will need to consider if, and for how long, you can trust that association within the security context of the use case.
For example, adding two step verification when detecting the end-user has just authenticated on a device you have never seen before is a nice additional protection. However, using the out-of-band SMS verification in account recover could open up a big security hole. You do not want to bypass the authentication with something they know (password) in a password reset flow by simply having access to that SMS number. SMS is also not an appropriate mechanism for one-time-password (OTP).
If you want to offer you users more protections on their accounts look into implementing true MFA with software tokens (eg. Google Authenticator, Authy, etc.) and hard tokens (eg. FIDO U2F devices such as Yubikey, Google Titan, etc.).
To your second question:
You are correct, IP-based limiting is insufficient. With SMS services you are likely going to be making a server-side API call to the SMS provider. First check to see what security features your provider has out of the box. Next, protect your endpoint that is triggering the API calls to the SMS provider.
Rate limit the number of SMS messages to any one given recipient (eg. no more than X SMS messages to a single number per Y minute window)
Rate limit the number of SMS messages one person can make to different numbers (eg. no more than X different phone numbers per user per day).
Do not allow unauthenticated requests. The user should have already completed the first authentication step (something they know eg. username/password) before performing the out-of-band SMS step.
Protect the SMS form from Cross Site Forgery Requests (CSFR). Your back-end should only make the API call to the SMS provider if it knows the request came from your front-end and not another host.
Protect the SMS form from bot attacks. There are many approaches with Google ReCaptcha being one of the more common.

How do I identify two requests from the same source in NodeJS?

my case is simple:
I need an application layer solution to identify and then apply some sort of rule to requests coming from the same origin.
If a guy will request my server from Postman, or from a browser or from a cURL I want to identify this guy and then do something with this information.
In my particular case I want to blacklist a guy who would be attacking my server for sometime.
Is it possible in Node/Express?
There is no uber identifier that comes with a web request that tells you who the user is behind the request, no matter how the request was initiated (browser, cURL, Postman, node.js app, PHP app, etc...).
This question comes up pretty regularly among new web developers. In the end it boils down to two things:
Requiring users to have an account, login to that account in order to use your service, requiring login credentials with every use of the service and then tracking their usage to see if it meets your usage guidelines. If it does not, you can ban that account.
Rate limiting users either by account or by IP address or some combination of both. If they exceed a certain rate limit, you can slow them down or deny access.
A browser provides a cookie so you can attempt to identify repeat users via browser cookies. But, this can be defeated by clearing cookies. Cookies are per-browser though so you can't correlate the same user across multiple devices or across multiple browsers with a plain cookie.
cURL and Postman don't provide any identifying information by default other than the originating IP address. You can attempt to track IP address, but there are some issues with relying only on IP address because corporate users may be going through a proxy which makes them all appear to come from the same IP address. If you ban one user for misbehavior, that may affect lots of other innocent users.
If you look how Google, Facebook, etc... do this, they all require you to create some sort of account and then provide credentials for that account with every request. This allows them to track your usage and manage your traffic if needed. And, for free usage, they generally all have rate limits that limit how frequently you can make API calls. This prevents any single user from using more than an appropriate share of the load of the service. And, it allows them to detect and regulate accounts that are abusing the system.
One step further than this concerns how an account is created because you don't want an abuser to just be able to run a script every 10 minutes to automatically create a new account. There are a variety of schemes for protecting this too. The most common is just requiring some proof that a human is involved in creating the new account (captcha, question/answer, etc...) which prevent automated account creation. Other checks can require a valid credit card, unique email address verification, etc...

Best practises to verify card owner when adding credit card to user account

in our application we allow users to link card to their profile and use it later for payments inside our system. Recently we had a couple fraud attempts when users added stolen credit cards (so they knew all information about card, including CVV).
The only thing that we came up with is to make temporary payment of some small random amount so user can check bank transactions report and verify ownership by providing exact authorized amount.
Is there any other common proven ways to verify card ownership?
Yes, there are a couple of things you can do at the very least:
Validating the house number and postcode/zipcode provided to you with the result returned to your from your payment processor on the pre-auth (AVS - Address Verification Service).
3D secure verification (Mastercard SecureCode or Verified by Visa) - the user is redirected to their issuer's site (or one ran for them by e.g. Arcot) and has to enter a secret only known to them.
Validating a small random amount is also a good check to make, however this takes a few days whereas the above can be validated instantly.

Safe to assume Email addresses are unique?

Building an app for schools. Teachers will have classrooms assigned to them. Teachers login via email/password.
We also have district supervisors/administrators who need to easily distribute these classrooms to teachers. Currently I have a feature where they can assign a classroom to an email address, and when a user with that email signs up, it is automatically granted to them.
Is this safe? Or is it possible for two individuals to have the same email address?
Two email accounts cannot have the same email address, but whether multiple individuals are using the same address will depend on the policy of the owner of the domain, or it might be up to individual users for public systems such as Gmail or Hotmail if they want to share their address with others.
Is the app (or a particular deployment of it) restricted to only allow sign-ups from the domain of the school? (e.g. at Example College only alow emails that end in #example.edu?)
If so, you should check with the school as it is upto them how emails are distributed and used. If anyone can sign up you should be aware that people may share email addresses at certain institutions or that email addresses may be recycled for new teachers if no longer in use.
To make this approach more secure you should:
Verify the email address of each person that signs up. This can be a confirmation email containing a link with an ID generated by a cryptographically secure RNG. When the user clicks the link http://www.example.com/confirm.aspx?id=123456qwerty this will verify that they have access to the email address and grant them access to the classroom.
Expire the pre-granted rooms after a set number of days. This will reduce the chances of a classroom being granted to any recycled email address.
A couple things jump out to me.
1) You seem to be assigning resources to an account (an email address) before it has been created. How do you know that the person registering with that email address is the person that you expect?
2) You can only assume that an email address is unique if you control the domain of the email addresses and you enforce uniqueness. Otherwise it is possible that email addresses will be recycled over time (quite common with corporate email addresses like jsmith#company.com).

Resources