I'm working on a site where, ideally, anyone will be able to email a specified address and attach a photo to their message (e.g. from an iPhone). This address will be set to pipe the email to a PHP script, which will then process this photo store it on our server.
I can see this system being pretty easy to abuse: someone sets up a page on their own server to repeatedly spam the address with photos, clogging up our storage space and server resources. Anyone have a suggestion on how to minimize this risk?
Thanks!
A few options, off of the top of my head. I'd use a combination, though:
Use a registration system (guarded with a CAPTCHA) so that only registered users can use the service; give each user their own secret email address, and only accept emails from their registered address. (Yes, their address can be spoofed, but it's at least some protection against casual abusers)
Require the user put a secret code in the subject line so that even if their from address is spoofed by an attacker, they'd also need to know the code or else the message is rejected
Set up per-account limiting
Limit the photo size so someone doesn't try to upload a 100 MB photo repeatedly
I don't see a fool proof method here. However you can treat this process like a user registration process. Once someone sends an email to you, you store the email in a temp storage, send an auto generated message back to the originating email address, asking them to click on a unique link to confirm or replying to that email with some special text.
Related
I am making a registration wherein users inputs email as their username and I have to send a random code to their email after a successful registration.
So far, what I got is:
Step 1: User registers with their email.
Step 2: API Generates a random code and inserts it to my database table (tbl_temp_otp).
Step 3: After inserting to the database, the code will be sent to the email provided in the registration.
Step 4: User gets the code, and input it into the registration form then API checks if that code exists and is still in unused
state.
So far, it works.
My issue is that, how can I send the OTP code through POST request without anybody seeing it in the network tab in google chrome?
EDIT based on the comments
I think I explained the issue in a wrong way...
What I really meant was not without anybody seeing it but without the registrant seeing it.
Since, the registrant is able to see the code inserted in the database, I'm concerned that they'll register with a non-existing email address and verify it by looking into the network tab and input the inserted OTP code and still able to completely register with the provided non-existing email address.
There is no way to hide the OTP that is sent through a POST request. The best thing to do, is to make the OTP time-based, and limit the duration that it is valid for.
Anyways, the request that is visible in the network tab is only visible for the respective user, so there is no actual security risk. Hope this clarifies your question. You can continue with the same process.
You can't.
You are sending it by email where the email client needs to read it, then it needs to be transferred to the user's browser so the browser can send it back over the network.
The user's browser and email client belong to the user. They are under the user's control. They can't be used to conceal information from the user.
But that shouldn't matter. It is a one time code designed to prove that the user is who they claim to be. It doesn't matter if the user gets their hands on it.
There's a risk that it might be intercepted between the browser and your server, but you can mitigate that by using HTTPS.
There's a risk that it might be intercepted between the email client and the browser, but there isn't anything you can do about the possibility of the user having malware on their system which is designed to share your one time password. It's a pretty remote possibility in the first place though.
There's a risk that the email will be intercepted, but nothing you can do about that unless you want to force the user to invest in setting up and learning how to use GPG or similar. (Again, it is a small risk).
Re edit:
I'm concerned that they'll register with a non-existing email address and verify it by looking into the network tab
Your one-time code should be associated with the email address that it was emailed to.
It won't show up in the network tab until the user clicks the link in that email. So there is no way for them to get the code without the email address being real.
You've already associated the code with a particular email address in your database, so they can't change their mind and use that code with a different email address.
I'm writing a web application and security is very important to me. When writing the 'forgot password' function I have taken the following advises into account:
Generate secure random auth token
Send user an email with this token
Send user an SMS with a pin code to enter in combination with the email link
Do not leak account info, the site will not mention an unknown email address when the user enters an unknown address. This way accounts cannot be linked to the webapp.
But this made me thinking. The website requires the user email address to be unique. Therefore the register form notices the user when the email already exists.
This means my attempts to not leak account existence information to an attacker in the 'password recovery' part are useless because I leak the same information in the register part of the site.
I have been looking at ways to prevent this and best practices around this, but not much information is written about it.
I have also noticed the same issue in the stackoverflow account system. Stackoverflow does not leak this information in the 'forgot password' function but it does leak account existance information in the registration process.
Can anyone point me in the right direction on this one?
Kind regards,
Daan
Update
A few minutes after typing this I had the following idea on how not to leak information to an attacker:
Do not present the new user with the message 'email address is in use', but accept the registration as if it would be a new one.
When the email address already exists, just send an email with the message there is already an account for that email address.
What do you think?
if you do password recovery, always send an alert that the email has been send when the email is legit, but only send when he is in your database.
In the registration part it's required to say if the e-mail exists in the database, so leakage is possible but for people to guess e-mail addresses without knowing them they need to bruteforce it which can be avoided by limiting the amount of posts the users can do to prevent spamming
There is always the possibility to move towards Login Names for logging in. You don't quite need your email address to be unique unless that is the sole method of logging in.
The answer her would just be more obfuscation if you realistically want to be more secure. What you could have:
Login name (the actual unique identifier to login to your web application, has to be unique)
Display name (the name visible to other users, does not have to be unique)
This could make guessing login names more difficult, and it would be slightly more secure. Email addresses would not need to be unique necessarily. But then the user must always keep track of what login name they signed up with. This process could ostensibly hide this information from attackers. Since both login and password recovery would ask for the username only.
I don't think this problem has a great answer. Like Joachim pointed out, you are always prone to leaking when you require the email to be unique. Since checking has to be done upon registration. Password recovery can be managed simply by always giving the message "Instructions have been sent to the email you provided" whether or not the email exists in your database. And failure or success would be handled internally but never be shown. Best way to make timing attacks impossible is defer the whole sending process to be asynchronous from your HTTP response.
So options are either, move to a login name system (with the same security holes ostensibly) or just accept that with unique email addresses you will leak during the registration process.
There might not be a best answer here. Part of security is getting users to be clever. And signing up with just an email address that is not really public, tends to help. But if an attacker has access to their sign up email, things are out of your control. And there is not much you can do (unless you have two step auth with SMS or something)
I am struggling these days to prevent spam from my signup form. I do not want just to prevent it from bots (with honeypots etc) but when a real human writes a script designed for my website to fill my database with dummy registrations(i do not want to use captcha). I have the following things in my mind to implement about it:
Check if email addresses exist (not only valid).I have read that you may be banned if there are lots of requests.Moreover it is possible that the script can contain valid email addresses (for instance when a university provides students email that are slightly different).
The other solution is to make a comparison between IP/Time_of_request and in case the same IP gives lots of requests for signup, consider user as spammer. For this you can set a threshold that you can consider signup request as spam. The problem here is that the script may find the threshold (e.g. 1 second ) and send request every 1.1 seconds. Moreover someone may use onion routing(?) and i will not be able to ban him.
3.What do you think about random input names ?
So what practices here are considered to be good enough to come through this situation?
Thanks!
UPDATE
I send email with confirmation link for activation,but i give users the feature to use the site for about 4 days without activating their accounts! I do not want in first step my database to have spam accounts!
SOLUTION
For everyone interested in, i used honeypots combined with a temporary database ! It seems to work fine!Thanks!
One more thing you can create a temporary registration database, and if someone verify email in 24 hours of registration, his/her data will moved to main registration database. and every entry will be deleted in 24 hours if email is not verified by user.
To validate the email address you could send a confirmation email with a validation link and the user should click on that link to confirm that is his email address and is not a boot.
In Response to OP Update: If you need to give users the option of using the site without clicking the activation link for X days, perhaps you could also send a set of two 4-digit (or just 6, but not secure) PIN numbers in the email (or separately) and have them use that as their temporary password until the account is activated via the original email link. In your database you'd notice if the PIN was used or not, indicating if it was a spam account. It could even be a one-time-use PIN.
From this question I really like #woliveirajr's answer because it solves:
how to protect against releasing e-mail addresses used on a website
verifies the owner of the e-mail address
To avoid this kind of leak, you could also begin the registration
process by asking for the e-mail. After entering it, you would send an
e-mail with a link so that the user could continue with the
registration process. If the e-mail was already registered, you would
send an e-mail saying that.
That way, only the owner of the e-mail could register.
Drawbacks:
probably the real, common users will get bored by having so much steps to register.
in very few cases simple revealing that an e-mail is already registered in a site is a problem, specially because it's easy to
register at any site providing any e-mail that you want. You'll just
won't receive the e-mail to activate your account, but in general the
site will link the account / username to that e-mail.
Where I'm uncertain is how to implement a system where a user can only access the registration page when they click on a link from an e-mail. Would the registration page retrieve data passed to it using GET and verify "a code" to know whether or not the user can register, and this code changes every 30 minutes? For example, the e-mailed registration link could be mysite.com/register.php?secretcode=as18d and register.php checks "the code" as18d but this code would change every 30 minutes. Is this the idea? Would the code be generated by a salted hash based on the system time?
Or, instead of e-mail a link with a few letters could be e-mailed which the user enters into the registration page to authenticate, kind of like how captures work but not really.
The general approach to this is to use an unguessable token, such as a GUID that is embedded in the link so that it gets submitted with the GET. This should be secure since it is highly statistically unlikely that someone will randomly guess a GUID for any user regardless of the time they spend trying to guess, thus expiration isn't even really necessary.
It is worth noting this should be done over an SSL link to avoid the possibility of a man in the middle compromising the verification process.
There's no way on the server side to guarantee that an HTTP request came from an link in an email message. You can't trust anything from the client side; it can all be spoofed and manipulated.
What you need is a hard to guess token. Long and random are good starting points.
Disagree with AJ on expiration for several reasons.
If your user db gets large, you don't want to track un-used tokens for years and years.
If someone requests an activation token and doesn't use it after a few days, it's unlikely they will. Might as well remove it.
I designed a registration form that users can use for registration.
When the user registers an account, he/she has to provide an email and then I will use ajax call to a server php script called checkavailableemail.php.
If the provided email exists in the DB, then I will transfer back FALSE and the user can see the red warning message and form cannot pass the validation procedure.
Here is the question,
Is there a way that I can prevent spam from getting all available emails in my DB?
For example, the bad guy can design an auto-script that uses some methods to continuously send email validation request. In the end, the guy can get a full list of all my current customer email account.
Thank you
There are gazillions of email IDs possible.
The bad guy need to send gazillion requests to get your current customer email accounts list. So, if you get a lot of requests from a single IP, you can temporarily block that.
So, no need to worry.
[EDIT]: OP Clarification:
You can get the IP of the user by this code:
$IP = $_SERVER['REMOTE_ADDR'];
Keep a list of number of requests made by an IP in last 24 hours, log them into a database table. if number of requests go beyond a certain limit, say 500, you can deny requests from this IP by checking the IP of the user with same code.
You could use a session and increment it with every failed register attempt. Once they hit 10, disable the form for a set amount of time. Sorry I can't post examples, my PHP is not strong.
Brian and shamittomar pretty much said everything.
Your concern is almost fictitious since the spam "dudes" are much better off sending emails to random addresses rather than flooding your website validation, to then send spam to those addresses.
Simply establish a limit.