3

When a user registers I clean the password with mysql_real_escape_string as follow

$password = clean($_POST['password']); 

Before adding it into database I use :

$hashedpassword = sha1('abcdef'.$password);

and save it into mySQL.

My question is should I clean it or am I protected that the password is hashed before adding it into the DB ?

rook
  • 66,304
  • 38
  • 162
  • 239
EnexoOnoma
  • 8,454
  • 18
  • 94
  • 179
  • **NEVER** "clean" the password using sha1 is already very strong method of input validation, i'm sure its much stronger than whatever "clean()" does. – rook Sep 01 '11 at 18:36
  • You should use `crypt()` to store passwords instead of `sha1`. Also using placeholders with `mysqli` or `PDO` is the preferred method. – Mike Sep 01 '11 at 20:12

6 Answers6

10

Well, there is one major misunderstanding.

mysql_real_escape_string() does not clean anything. It has nothing to do with security at all.

This function is used just to escape delimiters and nothing more. It can help you to put string data into SQL query - that's all.

So, every string you're going to put into query (by putting it in quotes), you have to prepare it with this function. In all other cases it would be useless or even harmful.

Thus,
out of this misunderstanding, you're doing 2 major mistakes here:

  • you're using this function not with data that's actually going to the query
  • you can spoil your password by adding some symbols to it, so, it become unusable

Also, as a side note, please bear in mind that this function should be always used in conjunction with mysql_set_charset, or otherwise a "_real_" part of this function become useless

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
  • 3
    +1 i agree escaping should not be though of as "cleaning" data. – rook Sep 01 '11 at 19:09
  • +1 I missed that this question is (*really*) about using `mysql_real_escape_string` on data not *directly* related to an SQL query. –  Sep 01 '11 at 19:36
2

If you are applying the clean() function on it (which I assume is an awful mixture of stripslashes/htmlentities/addslashes), then the hash you generate with sha1() might not be the hash for the actual password.

This will work by accident even if the password contained special charactes. But only as long as you always follow the exact same procedure. And actually you should be properly escaping the $sha1 hash afterwards (even if unneeded). And more actually, you should use a scheme that involves a better salt (per-user).

But to answer your question: This is working in your case; and not a problem. It's just not correct.

mario
  • 144,265
  • 20
  • 237
  • 291
  • Why do you say you should escape the sha1 hash, it is a hexadecimal string. There is nothing to escape in a hexadecimal string. What point am I missing? – kasterma Sep 02 '11 at 00:47
  • @kasterma: That's true. It's however not a matter of necessity, but of prudence. If you hang on to the outdated mysql_ functions, you shouldn't be sloppy with it. – mario Sep 02 '11 at 01:25
1

Yes. Always. Or, better yet use placeholders (which are available in both PDO and mysqli) see best way to stop SQL injection in PHP.

The reason to always use some form of escaping (even the outdated and cumbersome mysql_real_escape_string) is to be consistent. Saving the few cycles because "it isn't needed here" (and it "isn't needed here" because sha1 returns a string of hex characters) is irrelevant if it -- due to lack of consistency -- leads to bugs and/or compromises later.

Bugs/compromises can be introduced by a lack of consistency and forgetting to "escape" a different field later or it may be due to a small code range where the new requirements to "escape" was overlooked. (Imagine if a future version saves a binary or base-64 SHA1 signature.) Both of these trivial vectors can be eliminated through better practices.

Happy coding.


The user enters data. The database stores the data. The point of "escaping" the data (or, better yet, use placeholders/parameterized queries) is making sure the data makes it into the database correctly and safely. If the data needs to be treated specially, then handle this at the data level -- the actual operation of dealing with the SQL should be simple, consistent, and reliable. (Note that mysql_real_escape_string doesn't change the data seen by the database, rather it ensures that the data is the real data -- that which was passed to the mysql_real_escape_string function -- after the database parses the SQL command.)

It is quite sad, but the entire point of needing to "escape" still exists because of the incorrect concatenation of data into SQL strings. This "problem" has been solved for many, many years with the use of placeholders which allows the SQL command and the data to be kept isolated. Prepared statements may also be more efficient, depending upon other factors. And, quite honestly, I can't see how people can stand to look at/write the mess created with string manipulation (even without all the added "escaping" code) of SQL commands in general.

Community
  • 1
  • 1
1

There is NO need to use anything else than the hashing pass afterwards, there is no chance that something would screw your insertion, and XSS would be even more impossible. (note the “more impossible” part)

However... I suggest you to trim() the password before hashing it, so you will be sure that the user entered something. Also, check the trimmed password with strlen() before “hashing”

This code is enough for passwords... Where $pass is the posted password.

$pass = trim($pass);
if (strlen($pass) > 5) // it has to be bigger than 5 chars long.
{
    $pass = sha1($pass); // or use crypt() as some have suggested.
    // pass is ready to be inserted.
}
    else
{
    // pass is not correct and you should handle this as you want~
}


Now that I can, I ask, why did you remove the email password recovery question? I was about to answer to it.

Greetings.

  • 1
    Hi there thank you for this, I have a question though, is letting spaces vulnerable ? Also, I asked again that question and corrected something on it. – EnexoOnoma Sep 02 '11 at 17:45
  • Letting spaces will make no change... the resulting hash will always be safe to insert. But I recommend trimming whitespaces from the beginning and ending of the string because many users have a bad tendency to add unnecesary spaces in either the beginning or ending of a field. And also if you do not trim, whitespaces would be counted as a character and that would make passwords to be sensitive to trailing whitespaces added when entering the password. I hope you got my confusing explanation. :P –  Sep 02 '11 at 18:23
  • If my answer answers your questions please pick it as the correct one. I will take a look to the other one now. –  Sep 02 '11 at 18:24
0

In this particularl case, if you only use the hashed form of the string in your query, you'd be safe from SQL injection. SHA1 does not output any SQL metacharacters that would break your string, so this:

$pw = sha1($password);
$sql = "INSERT INTO .... VALUES ('$pw')";

would be "safe".

However, it is good practice to get in the habit of ALWAYS escaping everything, even if it's not strictly required. Better to go a little overboard with it, when it's not needed versus forgetting it in one tiny little spot and your site getting pwned.

Marc B
  • 356,200
  • 43
  • 426
  • 500
0

Really, in this case you need not mysql_real_escape_string here, because sha1 returns only string of a-f0-9 chars, that must not be escaped.

But it's bad idea to skip it here.
Why if you will change sha1 to other function, that may cause error. Simply, you will forgot to add mysql_real_escape_string. Besides, it's more semantic(I don't even speak about security) to use escaping function for all of your actions: storing in db, printing HTML/XML, executing shell commands.

Besides, as pst says its great idea to use placeholders

RiaD
  • 46,822
  • 11
  • 79
  • 123