My sign up form was abused to send spam. Is yours safe?
mzrn.sh
mzrn.sh
> This is one of those articles where reading the title is enough. No need to read the rest
then why isn't the title on HN what the article says is all we need to know?
We apply a few strategies...
1. Require oauth-based sign up for gmail.com, hotmail.com, and live.com addresses. No emails sent until after authentication.
2. Drop obvious spam. If your name contains "http://" or "Whatsapp" or your User-Agent is "python-requests" than you get a 400.
3. Manual approval for suspicious sign ups. High Abuse IP DB scores, statistically unusual names, etc generate a help desk ticket that someone from our staff approves before an email is sent. Persistent bad actors are blocked by IP for 2 weeks.
4. Rate limiting by IP. This prevents bad actors from spamming our help desk.
All together this seems to have largely solved the problem... for now.
When I did this, the spammers got more creative trying other ways to get through.
Now I return a 200, and the response looks identical to a successful signup.
The only difference is nothing actually happened on the backend.
I only do it for things which are clearly not valid users.
I gave them an e-mail address that contained a "+". Apparently MondialRelay silently dropped their requests. They thought they had sent me multiple e-mails. I received none.
I hate that kind of silent failure mode.
If there was something of value (besides excellent software) behind the signup form maybe we would need different strategies.
The way it goes is that an attacker got hold of e.g. an Amazon account and starts ordering stuff to his address. In order to prevent the victim from becoming suspicious, the attacker buries the Amazon emails in an avalanche of spam emails. So a bot was submitting the victims email address to my sign up form, my app sends out a verification email to the victim and being part of the distraction.
I solved the problem by adding a Captcha (https://www.cloudflare.com/products/turnstile/) to the form.
In that case, I think a simple proof-of-work would be enough. I also like the oauth solution mentioned elsewhere if a domain is supported.
Here's a thought: why not create a "mailto:" link so that users send a mail with the verification token instead?
Any ideas on how a simple proof-of-work could look like, also from the backend side?
for(i=0; i<INT_MAX; i++) {
output = hash(concat(server_provided_data, i));
if(check_output(output))
break;
With check_output checkig that the leading n bits are all zero, for instance, with n the difficulty.
On the server-side, no loop is needed: only one check with the server-provided data and client-provided "i" is enough.
In practice, i is probably going to be much larger than 32 bits, and any cheap way of changing it shold be enough, it doesn't have to be linearly increasing.
I imagine countless proof-of-work libraries exist.The issue with that approach is that slower clients will take longer to solve the challenge, but it just needs to be prohibitely expensive (and slow) for the attacker to spam this, even if they have powerful machines. Botnets can sidestep the issue a bit by distributing computing, but this should still slow them down.
You could also ask for the client's best find after x seconds if it's low-powered, and check that it is reasonable (though that can be gamed). The difficulty can also be increased temporarily if there is a surge of requests.
Maybe we need some kind of "Internet weather forecast" to adjust captca difficulty across websites according to detected botnet activity?
You probably can't use a single website to send those 20 messages (if it's well-designed with a cool down), as the recipient address is the same. So you need 20 different websites to send these.
What outgoing spam rate is acceptable, assuming you can't reach zero? 1 per 10 sec?
On the other hand, it's a fascinating topic on a technical level and I wouldn't compare it to other system exploits that you may witness in real life of people taking advantage.
The spammer must have been quite determined -- for free accounts there is a limit of invited users, so their automation script had to send an invite, cancel the invite, send the next invite, cancel, and so on.
Fixed by adding more rate limits.
These are all spams. The last valid case was when someone wanted to report a bug on a page from my site and want to include the URL of that page. But this case is so rare now a days. People can't differentiate the URL of a page from the page itself.
Isn't it better to validate input data? If you don't do it you can have bigger problems then sending spam, regardless if you use user input data into welcome emails or not.
It amazes me to see the kind of code at some startups. Such code would never pass manual testing when working for a software company. But likely it won't reach testing phase because it won't pass code reviews.
I can't remember the details unfortunately, but it was something I never thought of.
They were sending weird/crazy unexpected strings.
Oh they were exploiting automated responses saw on Reddit webdev
https://www.reddit.com/r/webdev/comments/10ujhh4/why_do_i_ge...
The way it worked was that the "from" email address could contain CRLF and then a bunch of extra headers, even a message body, which would simply get injected.
And nobody has learned the lesson that “all user data is hostile” yet.
It is and isn't really a DDOS, it's a obscuration, see -
email: some@real.address
username: F*YOU
submit!
Now your sending "Hey F*YOU!" to real people.
I think you can't restrict usernames enough to not allow any spam. The only right way is to really just have the email and nothing else in the first confirmation mail.
There are low tech and effective ways to tell bots from real people but I don't want to share them in public with possible bot writers here, sorry. If they know they don't care because they are successful enough without complicating their code a little bit more. If they don't know, don't tell them.