Working on a login system - the point where customer chooses their password for site access.
Beyond using RegEx to ensure that the password is strong enough, normally on our system all data that will wind up in the database is checked against injection etc and a reasonably restricted character set is enforced on all fields. I don't really want a particularly restrictive character set for the password, as I think it is a bit of an anti-pattern on security to control it too much.
However in the case of the password, I'll be hashing it with a salted SHA-512 for insert anyway which raises a handful of questions:
Is there any point whatsoever in restricting the character set that the customer can use in the password - ie am I exposed to any vulnerabilities outside of injection which I am assuming would be circumvented completely by the hashing?
There must be negatives to an allow-all approach - I can think of the fact that in the future what is an innocent combination now could become a dangerous one - is that a real concern, and are there others I may have missed?
Are there any characters/strings that must be rejected - would they get through the native ASP.NET protection anyway?
A bit more subjective maybe, but given it is a SHA-512 hash - is there any point in restricting the maximum length of password that the user can choose (within reasonable parameters), assuming that a password of significant size/complexity could raise a warning to confirm that they do want to set it.
Thanks for your help.
EDIT: This is an ASP.NET web application accessing a MSSQL2008 database using ADO.NET (not LINQ/EF).
From a non-English perspective - there should be no restrictions on the password.
For example, why restrict a Japanese-language speaker to using the US-ASCII character set? And why should a French speaker not use accented characters?
Given that your hash is persisted correctly there's no technical reason to restrict it.
There is little reason to worry about SQL insertion attacks unless you're actually inserting the password into the database in plain text (Danger, Will Robertson, Danger!) and even then if you paramaterize the query it won't be an issue. You should allow [a-zA-Z0-9] plus some set of special characters. Probably the only character to restrict is '<' which will trigger the ASP.net validation warning. There are a number of fun tools out there to do password complexity checking on the client side. I like this one. It provides some instant feedback to the user as they are typing.
Since the password is hashed, it will be stored in the database in hex decimal format. Therefore, I see no point of restricting the type of allowed characters. If I wanted to use a Chinese letter in my password, I should be able to do so. If I have installed an extension for Firefox that generates random bytes and uses those for my passwords, I should be able to do so. The lesson here is to not limit your users' passwords.
Also note that RegEx has a unicode support that is capable of detecting if the user has used a letter of any languages. That might become handy when you are validating the strength of the password.
Related
I am scanning my web application which i have build in Asp.net. Scanner is injecting junk data into the system trying to do blind Sql injection on the system but i am using Sql store procedures with parametrized quires which is escaping the blind sql injection but these junk entries are stored into the system as normal text i am sanitizing the inputs not to take ' and other sql related parameters.Now my question are
1) Are these junk entries any threat to the system?
2) Do i really need to sanitize the input if i am already using paramitrised quires with store procedures?
3) Scanner is not able to enter information into the system if u don't create login sequence is that a good thing?
Any other precautions i should take please let me know
Thanks
As you correctly mentioned, the 'junk' entries in your database are form submissions that Acunetix is submitting when testing for SQL injection, XSS and other vulnerabilities.
To answer your questions specifically:
1) No, this junk data is just an artifact of the scanner submitting forms. You might want to consider applying stricter validation on these forms though -- remember, if a scanner can input a bunch of bogus data, an automated script (or a real user for that matter) can also insert a bunch of bogus data.
Some ideas for better validation could include restricting the kind of input based on what data should be allowed in a particular field. For example, if a user is expected to input a telephone number, then there is no point allowing the user to enter alpha-characters (numbers, spaces, dashes, parenthesis and a plus sign should be enough for a phone number).
Alternatively, you may also consider using a CAPTCHA for some forms. Too many CAPTCHAs may adversely affect the user experience, so be cautious where, when and how often you make use of them.
2) If you are talking about SQL injection, no, you shouldn't need to do anything else. Parameterized queries are the proper way to avoid SQLi. However, be careful of Cross-site Scripting (XSS). Filtering characters like <>'" is not the way to go when dealing with XSS.
In order to deal with XSS, the best approach (most of the time) is to exercise Context-dependent Outbound Encoding, which basically boils-down to -- use the proper encoding based on which XSS context you're in, and encode when data is printed onto the page (i.e. do not encode when saving data to the database, encode when you are writing that data to the page). To read more about this, this is the easiest, and most complete source I've come across -- http://excess-xss.com/#xss-prevention
3) A login sequence is Acunetix's way of authenticating into your application. Without it, the scanner can not scan the internals of your app. So unless you have forms (perhaps on the customer-facing portion of your site) the scanner is not going to be able to insert any data -- Yes, this is generally a good thing :)
I am using Facebook API in my app to do the user authentication and then saves the user data into DB. And I am using same (i.e. facebook) username for my app if it exist else I create the username using name, but the problem is that some user's don't have their display name in English. So how can I check for such input at server side?
My app is written in Asp.net.
You can use regular expressions to check if the characters are only a, b, c...z or A, B, C...Z:
using System.Text.RegularExpressions;
Regex rgx = new Regex("^[a-zA-Z]+$");
if (rgx.IsMatch(inputData))
// input data is in English alphabet; take appropriate action...
else
// input data is not in English alphabet; take appropriate action...
It may be overkill for this task but correct way to detect input language is using something like Extended Linguistic Services APIs or services like Free Language Detection API
In your case I suggesting saving user names in appropriate encoding (like utf-8 or utf-16, which should be fine for user names on Facebook)
Your problem isn't that the usernames are in a foreign language, but rather that you are trying to store data into a database without using the appropriate character encoding (the only reason I've ever seen those ??? is when character encoding was at least one level too low for the current problem).
At a minimum, you should be using utf-8, but you probably want to use utf-16 (or even utf-32 if you're being really conservative). I also recommend this mandatory reading.
Determining whether a username is in English or not is impossible. There are too many possible variants on proper nouns to be able to provide any reliable metric. Then there are transplanted names and the like. You can try to detect if there are non-ASCII characters (I believe /[^ -~]/ should match all of them — space is the lowest "typeable" character in ASCII, ~ is the highest), but then you are compensating for the unicode problem instead of letting the computer handle that gracefully.
I am using asp.net membership and I have checked the table aspnet_membership and I can see two fields password and saltpassword which look like this QoasdDKkh5x9RizpadsGsC9N30= and
tO9xYGRkjaFGaskKnTVobiJnMDQ== respectvely.
is there any tool, Stored procedure, program, online utility tool by which I can see the actual text of that password?
The only possible way you can recover the password is via brute forcing the hash against a dictionary. This will essentially test (as many as possible) combinations of words / letters until a match is found.
Short of finding a vulnerability in the hash this is all there is. It was originally hashed exactly to prevent finding out the plaintext.
The whole point of hashing a password is that you can't recover it (or at least not easily).
The idea is that you store a hash so you can test that against the hash calculated for the password provided by the user subsequently.
I am debating using user-names as a means to salt passwords, instead of storing a random string along with the names. My justification is that the purpose of the salt is to prevent rainbow tables, so what makes this realistically less secure than another set of data in there?
For example,
hash( md5(johnny_381#example.com), p4ss\/\/0rD)
vs
hash( md5(some_UUID_value), p4ss\/\/0rD)
Is there a real reason I couldn't just stick with the user name and simplify things? The only thing my web searching resulted was debates as to how a salt should be like a password, but ended without any reasoning behind it, where I'm under the impression this is just to prevent something like a cain-and-able cracker to run against it without being in the range of a million years. Thinking about processing limitations of reality, I don't believe this is a big deal if people know the hash, they still don't know the password, and they've moved into the super-computer range to brute force each individual hash.
Could someone please enlighten me here?
You'll run into problems, when the username changes (if it can be changed). There's no way you can update the hashed password, because you don't store the unsalted, unhashed password.
I don't see a problem with utilizing the username as the salt value.
A more secure way of storing passwords involves using a different salt value for each record anyway.
If you look at the aspnet_Membership table of the asp.net membership provider you'll see that they have stored the password, passwordsalt, and username fields in pretty much the same record. So, from that perspective, there's no security difference in just using the username for the salt value.
Note that some systems use a single salt value for all of the passwords, and store that in a config file. The only difference in security here is that if they gained access to a single salt value, then they can more easily build a rainbow table to crack all of the passwords at once...
But then again, if they have access to the encrypted form of the passwords, then they probably would have access to the salt value stored in the user table right along with it... Which might mean that they would have a slightly harder time of figuring out the password values.
However, at the end of the day I believe nearly all applications fail on the encryption front because they only encrypt what is ostensibly one of the least important pieces of data: the password. What should really be encrypted is nearly everything else.
After all, if I have access to your database, why would I care if the password is encrypted? I already have access to the important things...
There are obviously other considerations at play, but at the end of the day I wouldn't sweat this one too much as it's a minor issue compared others.
If you use the username as password and there are many instances of your application, people may create rainbow tables for specific users like "admin" or "system" like it is the case with Oracle databases or with a whole list of common names like they did for WPA (CowPatty)
You better take a really random salt, it is not that difficult and it will not come back haunting you.
This method was deemed secure enough for the working group that created HTTP digest authentication which operates with a hash of the string "username:realm:password".
I think you would be fine seeing as this decision is secret. If someone steals your database and source code to see how you actually implemented your hashing, well what are they logging in to access at that point? The website that displays the data in the database that they've already stolen?
In this case a salt buys your user a couple of security benefits. First, if the thief has precomputed values (rainbow tables) they would have to recompute them for every single user in order to do their attack; if the thief is after a single user's password this isn't a big win.
Second, the hashes for all users will always be different even if they share the same password, so the thief wouldn't get any hash collisions for free (crack one user get 300 passwords).
These two benefits help protect your users that may use the same password at multiple sites even if the thief happens to acquire the databases of other sites.
So while a salt for password hashing is best kept secret (which in your case the exact data used for the salt would be) it does still provide benefits even if it is compromised.
Random salting prevents comparison of two independently-computed password hashes for the same username. Without it, it would be possible to test whether a person's password on one machine matched the one on another, or whether a password matched one that was used in the past, etc., without having to have the actual password. It would also greatly facilitate searching for criteria like the above even when the password is available (since one could search for the computed hash, rather than computing the hash separately for each old password hash value).
As to whether such prevention is a good thing or a bad thing, who knows.
I know this is an old question but for anyone searching for a solution based on this question.
If you use a derived salt (as opposed to random salt), the salt source should be strengthened by using a key derivation function like PBKDF2.
Thus if your username is "theunhandledexception" pass that through PBKDF2 for x iterations to generate a 32 bit (or whatever length salt you need) value.
Make x pseudo random (as opposed to even numbers like 1,000) and pass in a static site specific salt to the PBKDF2 and you make it highly improbable that your username salt will match any other site's username salt.
I'm trying to sanitize any data that's inputted by making sure the data is valid for a particular field (e.g. a name can't contain special characters/numbers etc..) However, I'm not sure what to do when it comes to a password field. Would I even need to bother with any sanitization as the password is simply hashed? If the user was to inject anything malicious via the password textbox, should I bother checking for anything suspicious? AFAIK, some users may (should!) have special characters such as '< >', which would normally trigger a potential attack alert. Should I just leave the password field unsanitized? Limiting input for passwords is a last resort for me, as I feel users should use all sorts of characters in their passwords.
Thanks
As long as you are hashing it in your application, you should be OK.
A bit off topic considering you are using asp.net, but a notable exception to that would be if you are using PHP and MySQL and doing something like this:
UPDATE users SET password = PASSWORD('$pwd') WHERE userid = $uid
In that case you would want to sanitize $pwd first.
If you're concerned about SQL Injection attacks, you should start using parametrized queries to interact with your database. As it's a business rule to determine what's valid characters to password, I wouldnt strip anything while my customer don't say so.
All other input should be sanitized, as they could also be displayed on your page output and could lead to XSS attacks.