When a customer signs up for a site, we want to let them know whether a username/email is available for use.
We have a httphandler that serves the purpose of feeding a jquery script that showsthe customer whether or not their desired username/email is available.
The question is:
The service can clearly be seen being called when you view the request in fiddler.
It shows /emlhandler.asmx?name=xxxxxxxxxxx#yyy.com
From the handler, a simple 0 or 1 is returned to indicate whether or not the name/address is available.
My concern is that this seems like a major security issue that would be very easy for an inexperienced person to exploit to discover all the users on the site.
So friends, how do you protect your site info and still allow the ajax callback to provide a great user experience?
Thanks.
Heath
You are being slightly paranoid here. Every site that allows user registration has to do something similar. One thing you can reasonably do is add a slight delay (maybe 2 or 3 seconds) to the handler's processing in order to reduce the likelihood or ease of a brute-force attack. Frankly, I don't think anyone would bother.
Another option is just to ignore repeated emails and send a verification email before a user's registration actually becomes active. If a new user attempts to use an existing email, the original email owner receives the verification and can cancel or ignore it. But I don't recommend this.
I'd say the vast majority of the sites I've used will just immediately say "this email address is already registered... did you forget your password?" Just knowing an email address is already in use on a given site does not in itself represent a security breach.
One possible solution would be to only enable POST requests for that method.
And since you cannot invoke services from JavaScript from another domain (XSS - Cross-site Scripting) without your authorization, then you would be protected.
However this technique would prevent malicious users from calling your web service to discover user names but this wouldn't prevent the user to automate a process to simulate user entering data in a text box to force a call to the service, in that case, perhaps you could allow just a number of requests per user in an X amount of time.
You could keep track of the number of attempts using the Session object from your web service
Another approac would be to add a re Captcha to your site, however this would decrease the level of responsiveness if you used to allow your users to capture a user name and as soon as they write you call your service. Implementing would require your users to write the auto-generated captcha in order to submit your data
Related
I am after some advice regarding use of GUIDs from the security perspective. I have developed an ASP.Net application. It provides the user with access to some material, such as documents and photos, that aren't on the web server. These are stored on a file server. I have a 'GetResource.aspx' page which takes the ID of the resource, opens it using System.IO.FileInfo writes it to the response stream and returns it.
So, GetResource.aspx?id=123 would return, say, a picture that the user has access to. Of course, the user could manually enter the URL as GetResource.aspx?id=456 in which case the picture / document etc with that ID would be returned and it may not be one they have permission to access.
So clearly using an integer ID is not adequate. Would using a GUID as the ID provide enough 'randomness' that I could reliably assume the user could never manually enter "GetResource.aspx?guid={A guessed guid}" and ever expect to access a valid resource, including if using a script that made many random guesses per second?
Or, is there no substitute to determining the ID of the user from a Session variable, determining he does actually have access to the requested resource and only then returning it (Which as I write this I'm more and more convinced is the case!).
Thanks
There is certainly no substitute to authenticating the user and seeing if they are authorized to access the resource. What you are proposing here is a method of making it harder for a user to hit on a valid id for a document they are not authorized to view (either by mistake or on purpose).
A GUID is certainly large enough that you would never get "accidental" valid ids in practice. That makes a GUID without authorization checks a system that works great as long as noone is actively trying to break it. On the other hand, authorization checking is a system that would work great even in the presence of active attackers (of course this depends on what the attackers can manage to do).
You should choose between the two approaches depending on the nature of your application (is it public? are the users known and accountable for their actions? how bad would a "security breach" be?).
You should be determining if the user is authorised before blindly serving it if it is protected content.
The GUID does help to some extent, it makes guessing URLs harder, so I'd still recommend using them. But URLs can still be shared (even accidentally). If you are just going to serve up the content anyway regardless of who makes the request then it is of little real protection.
If you think that content is restricted one and having some personal data then you should go with username and password thing.
Consider a hypothetical bank application, where we have accounts and some group of admins. Each admin has modification rights on some of accounts. To save modifications done for an account, application sends account id on edit page. A admin can change post request by using tools like fiddler. If he/she changes account id to some account id on which he/she is not authorized. Then what is the best way to detect it.
What strategy should I use to re-validate every piece of data for authorization on post-back? My concern is more towards design, not code.
In other words, how real world applications make sure that even if user is changing postback request from any tool, application is able to detect it.
Should I re-validate every piece of data for authorization on post-back?
Yes, that is correct. You should start with a 'All input is evil' philosophy and then prove that statement incorrect by validating each data point. If your entire data doesn't pass your validation, then your input is indeed evil.
Smart web applications employ both client-side and server-side validation. Client-side validation to quickly alert user on whats wrong/missing without making a server round trip and server-side validation to make sure that wrong data doesn't fall through the cracks even if someone 'fiddles' with the client side validation code (and overrides it).
Unfortunately, encrypting the data on client side won't work as then you have the keys on the client side (in JS code) as well. That won't prevent a malicious user to encrypt a malicious payload. Also obfuscations like hidden field etc. are inefficient for a malicious attacker. FYI, you don't even require fiddler to change fields/post params etc. - all you require is a firebug extension.
The mantra is "Validate every thing on server side". Period.
For Critical Applications Like Banking, i will suggest follwing security steps
1) Send Encrypted Account ID
2) Keep that account id in a hidden field and when user post data take account id from hidden field not form the textbox or label.
3) re-validate every piece of data for authorization on post-back.
I'm starting to size up a project where I feel security needs strike a little closer to home. What tools and techniques could I look at to attempt to raise an alarm when a valid login is used, but the owner of the login has given it away or had it stolen. I would prefer ASP.NET, then MVC 3, oriented stuff.
This is not a silver bullet, but perhaps you should consider employing some kind of two-factor authentication. For example: when a user creates an account with you, you require that she provide you with a phone number where she can receive text messages as part of the registration process. Then, when she attempts to log in, you text her a temporary authentication code to be used in combination with her username and password.
This ads an extra layer of security to the system, because an attacker would have to both know her username and password and have physical access to her cell phone in order to compromise her account.
I hope that's helpful.
Seems like you would get a lot of false positives... but you might try checking what IP address the login is coming from. Most people will log in from the same IP address most of the time, so when that changes, it's at least a warning sign. If you want to be very strict about security, you could maintain a whitelist (for each account) and require that they get their IP address added to the whitelist before logging in.
My bank (Chase) does this by checking a secure cookie during my username/password login. If the cookie is missing or corrupted, they require a second form of authentication, which is either a code sent via text to my phone number on file or via email to my email address on file. Once the second form of authentication is complete, they set the secure cookie and then I can login from that browser with only username and password.
Implement your own Membership provider and add field locked to model,
check for user being locked on login and do some actions
It might be useful to think of the factors of the Authentication process, so that you can be sure that you are sufficiently covering things. You can easily get ridiculous with the layers of assurances, but I happen to find that most banks now have a variation on a simple model. All of this is, of course, over SSL
User submits account name. Additionally, you can require a secondary piece of information, last 4 of account number or year part of date of birth.
Optional, but a good idea: present the user with a counter sign, that is something that verifies the identity of the server. The user selects this at registration and should be looking for this every time they attempt to log in. This aids in preventing phishing.
System checks to see if the current system using IP lookup or cookie is associated with the account. If not, presents challenge question along with password input. Otherwise, presents just the password input.
Complicated, but can actually be done in 2 pages and more secure than is usually required.
I've presented this workflow to a few bank clients and they usually remove one or two of the checks for a balance of user friendliness.
With phones with text capabilities being so common, the idea of SMS verification code as mentioned by others is also a good idea, though I haven't implemented this in a system yet, personally.
I have designed login page for one of our website where I have used following resources
Login Name and Passowrd lable and textboxes
Combo box for multilingual support
Submit button.
Now to make this page more secure I am planning to use following extra points.
CAPTCHA/ RE-CAPTCHA
Number of Retry: block after 3 unsuccessfull login attempt.
I have seen these extra things by visiting other sites. I would like to know
Whether these extar point makes somediffrence for security?
How should we implement number of retry? When should we again unblock user account.
What is right approach?
You could use ASP.NET's login control and the default SQL membership provider. If you do this, implementing the number of retries before a user is locked out is as easy as setting a config value.
Take a look at MSDN here, and scroll down to "Using the SQLMemberShipProvider" section.
Look at the NoBot control from the AjaxControlToolkit (http://www.asp.net/AJAX/AjaxControlToolkit/Samples/NoBot/NoBot.aspx). That provides some "bot protection" without the user needing to decipher a captcha.
General - Require a strong password and limit the login tries/user (not IP/cookie). If you add a five minute lock-down for a user name after three fails a bruit force attack would take more years than you site will live (dictionary attacks are not possible since you require strong passwords)*.
Protect your users - In your form, don't post the password in clear text, post a hashed version eg.
md5([your domain] + [password])
The reason you add your domain is to protect the hash of the password from the server owner (you), so if your user DB get hacked the hashed passwords you stored are useless even if your users use the same password on multiple sites. If you like stronger hash you could look for some SHA version. Make a js script that replaces the password with the hashed one before sending. Remember to have this hash calculated on the registration page, never let the password be sent from the browser in clear text. You don't want to know it!
http://en.wikipedia.org/wiki/Cross-site_request_forgery, also have your server sign the cookie values to make cookie forgery harder.
Encryption - Either use TSL/SSL or get a RSA script and encrypt your form data with your severs public_key.
Man-in-the-middle - The hardest threat to guard against, I guess that https is the easiest way but a trusted certificate costs money. If you self sign users today don't bather to look if it's the right cert or not, this requires too much form the users. Buy a cert or hope you don't have a man-in-the-middle.
I would never use re-captcha for login since a lock-down of user name is more effective and less disturbing for a user. Though re-captcha is good for account registration so you don't end up having a lot of scripted accounts.
Limiting login tries/username could be used to block a user to log in. Bruit force attacks are still available since they can attack a lot of usernames and not only one, thus keeping the attack under the limit/username block. But for a site with few (less than 10.000?) user accounts you should be quite safe.
If you are updating an existing site that has had security issues, captcha can't hurt. If it is a new site, is it public or for internal use? You can always add this later if you run into issues. If there are sensitive materials, you'll get more mileage out of enforcing strong passwords from users (though this can be annoying to them) than you'll get out of captcha (also annoying).
Several options here. You can record IP address on each attempted login and record failed attempts. 3rd fail from same IP inside of 15 minutes blocks further attempts (every attempt fails with locked account message). Additional attempts reset the 15-minute "timer." Really, there is no timer, but with each attempted login, the log it checked to see whether it has been locked within the last 15 minutes.
The login attempt log can be stored in many ways -- often a database table. There may be value in keeping a record of every login (in case there is ever a breach), or maybe you only want failed logins. Optionally, you could remove failed logins from the log when the user successfully logs in. You could have a database routine that cleans up the table from time to time of failed login records that have exceeded the waiting period (15 minutes, or whatever).
Obviously, 15 minutes is arbitrary -- this can be 1 minute or 24 hours or until the user calls your customer support line to get it reset.
I'm rewriting a website and going from a home-grown authentication model where users logged in with their account id (numbers) and password, to .NET FormsAuthentication where users will login with a username that they choose (or is available) and a stronger password. There are over 38K existing accounts and I'm trying to decide if the existing users should re-register or if I should write some code to do this on their behalf. I've already ruled out creating the usernames for the users because they won't be able to change their username. Luckily we don't have any users named Brenda Utthead.
If the user re-registers, some may gripe about having to do this step again and it may raise some support calls, but I stay with the standard process that everyone has to do. Or I can allow the user to login with their existing userid and password and then optionally give them a grace period to convert their account. I'm hesitant about the latter because it's special code and a possible threat vector because it bypasses the standard authentication mechanism and allows users to log in using less secure credentials.
This application currently accounts for about 40% of our website traffic and I'm not worried about users not coming back to the website because of the possibility of them having to re-register.
What does everyone think?
If you want your users to come back your best bet is to convert their accounts and send an email explaining the transition.
Do not make them re-register whatever you do.
You'll lose half of your users if you do that.
Give them a service so that they can enter their previous user id and have them provide their email address. Email them at the address provided and have them login with their email address as their new user name.
I am about to do the same thing. I am writing a migration page where the user logs in with his/her existing credentials and behind the scenes, I write out to the asp.net membership tables. Do a check first to make sure they haven't already migrated for all subsequent visits.
Don't make them re-register. A little work on your side is all it takes and you need to keep your customers happy.
After listening to everyone's suggestion, I've decided to modify the login. I look at the username they provide and try to guess that they're an existing user. Then I look them up in the old table and if I find a match take them to a conversion screen. There they can quickly convert their account or skip the whole process and login temporarily. The conversion form has fewer fields to fill out b/c I was able to authenticate them against the old user table so I don't need them to provide as much info.
I'm not thrilled with skipping the conversion but that option is only offered for the first 45 days from go-live.
Either convert them or find a way for both membership models to exist together, and somehow convert each user across at login or something.
Think about how long it took to get the 38k members and ask yourself if those were all wiped out, would those same people go through the hassle of signing up again. If you've got a really strong community you should be ok, the hit would just be a matter of time till you're built up.
The other thing you could do to mitigate the risk would be to send out a email, although spam blockers may filter them you could get to a high percentage of your users and tell them about the new membership stuff. Might get some older people back to the site as well in the process.
The biggest challenge is converting all the data that is associated with the user's accounts. People are going to be really upset if they've built up some sort of reputation that you're going to destroy with a new membership system.
This website is a check your balance type of website. It's not a banking site per se, but it exists as a convenience tool to users. I don't believe it would be realistic for users to cancel their accounts because they are forced to re-register.
I do like some of the ideas I'm reading in the responses though.
I would migrate their information and then on their first login ask them to confirm that their membership info is correct (just to be anal).