News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Trying to reset passwords on the forum database

Started by tomreyn, July 26, 2013, 11:31:37 AM

Previous topic - Next topic

tomreyn

Hi,

on our staging site, running SMF 2.0.4, I'm trying to reset the password for an existing admin user by editing the database, setting passwd = '' and password_salt = '':

mysql> UPDATE smf_members SET passwd = '', password_salt = '' where member_name = 'someadmin';
Query OK, 1 row affected (0.09 sec)
Rows matched: 1  Changed: 1  Warnings: 0


Next I confirm these are now properly nulled:
mysql> SELECT passwd, password_salt FROM smf_members WHERE member_name = 'someadmin';
+--------+---------------+
| passwd | password_salt |
+--------+---------------+
|        |               |
+--------+---------------+
1 row in set (0.00 sec)


So indeed that's deleted. I expect to be unable to login, using username 'someadmin' and its password at this point. However, I am!
When I do, and follow this up by the same SQL query I get this:
mysql> select passwd, password_salt from smf_members where member_name = 'someadmin';
+------------------------------------------+---------------+
| passwd                                   | password_salt |
+------------------------------------------+---------------+
| 49a95f90f1ccf03d37c0980d077f2009f8a459d1 | f737          |
+------------------------------------------+---------------+
1 row in set (0.00 sec)


(I've slightly redacted the above values.)

Now this is exactly the same password hash as there was before, but a new salt.

If, after replacing passwd and password_salt of this user by an empty string, I try to login with incorrect credentials, though, then the login fails as expected.

This seems very wrong, and I am very puzzled, hopefully I am just misunderstanding something. Can you help me understand:

  • How the deleted credentials are restored, and where from
  • Why a different salt results in the same password hash
  • What the proper approach is to enforce that all users to go through an e-mail backed password reset - apparently it's not this

Thank you.

Kindred

there is no way to force users to reset their passwords...

The fields in the database were used to require users to RE-ENTER their password with the upgrade from MD5 to SHA1 (or the import of the password fomr another system) so that the password was correctly hashed into the new schema.

However, none of that forces a user to CHANGE the password and there is no way to do an email-force-change.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

tomreyn

Hmm, no way to reset users' passwords, this would be very disappointing (pretty much every other standard web application I can think of does provide a documented way to do this - this is not bashing, I'm just saying I can't imagine this is necessarily so).

So if credentials aren't stored there, where are they stored?

Also, if I replace the users' password by an empty string but keep the salt intact, I am no longer able to authenticate with the previous credentials. So these values do seem to have an impact.

Kindred

right....   there needs to be a password in the field. Otherwise the account has no way to authenticate at all.

I never said that the values have no effect.

If you put the password in plaintext and empty the salt value, it will force the user to re-enter the password, in order to acquire the correct salt. This is the way we have handled transferring login data from other systemns, like a CMS to SMF.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

tomreyn

Quote from: Kindred on July 26, 2013, 12:38:03 PM
right....   there needs to be a password in the field. Otherwise the account has no way to authenticate at all.

Well, I'm saying that if the password is set to the empty string then the user can authenticate fine. Which is worrying me.

However, for the password reset that we want to carry out, ensuring that users are unable to authenticate is exactly what we plan to do. We want to put them in to a situation where their old credentials will not work, so they have to use the password reset option to receive a confirmation code at their registered e-mail address, click on that and set a new password. How can we achieve this if it does not work by setting the passwords to the empty string?

Quote from: Kindred on July 26, 2013, 12:38:03 PM
I never said that the values have no effect.

I concur. You indicated that these fields were used to migrate users from previous authentication schemes to the current one. I must have jumped to conclusions there.

Quote from: Kindred on July 26, 2013, 12:38:03 PM
If you put the password in plaintext and empty the salt value, it will force the user to re-enter the password, in order to acquire the correct salt. This is the way we have handled transferring login data from other systemns, like a CMS to SMF.

We do not know the users' plaintext passwords (If we did, something would be very wrong already). We can generate random strings and place those in the passwd field, though. That's not as nice as being able to ensure that authentication will fail (this new password could still be guessed) but it is an acceptable compromise. Is this what you are suggesting to ensure that users will be unable to authenticate using a known password?
I'm having trouble understanding what you mean by "in order to acquire the correct salt". The user doesn't actually need to (nor should) get to know the salt which was used to generate the password hash.

Maybe SMF just uses the term "salt" differently than it is used elsewhere? Classically, a salt is value which is unique to an account, or is randomly generated. The salt is then used while hashing the user provided plain text password to the hashed variant, which is stored in the database. During authentication, the password provided by the user is combined with the hash and the same hashing mechanism used when originally storing the hashed password. The result of this calculation is then compared to the stored password hash.

Is this not how password hashing and authentication works in SMF?

Kindred

I'm not exactly certain.

I know I have used that field in the way I described to handle third-party bridges.

I'll have ot pass the more detailed answers off to a dev-type person who knows the code better than I do...
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

tomreyn

Thanks, I would appreciate a developers' response very much.

Chalky


emanuele

Okay, let's try to shade a bit of light (not that because authentication is one of the parts I carefully skip as much as possible :P).

Case 1:
* remove password *and* salt: yes, in that case first-comes-first-serves. The user is authenticated. Warning: this situation should never become reality, never! (even though I may have an idea that this can happen...have to check). Anyway, in fact is not really a good situation, it should probably be changed.

Case 2:
* remove password: no login possible at all.

Case 3:
* remove salt: warning and second request of introducing the password, then authenticated as normal. This is done on purpose, because salt was introduced only in ...don't remember, I think somewhere between 1.0 and 2.0, so in order to migrate users to use the salt this has become necessary.

Now, what does salt mean in SMF terminology?
Exactly what it means anywhere else: something that is attached to the password to increase the strength of the encryption.
Then, why "change" the password with an identical one generates in the database the same hash?
Because the salt is not used to salt the db password, but to salt the password stored in the cookie in order to keep your session "alive".
A good reading remains Arantor's post.

ChalkCat: I would *never* suggest that mod, *never*. Firstly because I wrote it ( :P), secondly because force users to change their passwords has the usual negative side-effect of passwd1, passwd2, passwd3, etc.

If you want to reset your users' passwords I would suggest you this script instead that does exactly that: takes all the users in the db, generates a random password and mails it.


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

Chalky


tomreyn

Yes, thanks indeed, Emanuele.

So I guess we'll go with removing the users' passwords, but not their salts. I don't exactly understand why this is so, but am glad to have received a definitive reply on the matter.

Quote from: emanuele on July 26, 2013, 03:27:13 PM
Now, what does salt mean in SMF terminology?
Exactly what it means anywhere else: something that is attached to the password to increase the strength of the encryption.
Then, why "change" the password with an identical one generates in the database the same hash?
Because the salt is not used to salt the db password, but to salt the password stored in the cookie in order to keep your session "alive".
A good reading remains Arantor's post.

Thanks for explaining what this salt is used for, and for pointing me to Arantor's excellent post. I heavily agree to what he said there, especially that there are several more serious issues, but that the shortcomings in the hashing mechanism are also relevant.

emanuele

Quote from: tomreyn on July 26, 2013, 04:35:44 PM
So I guess we'll go with removing the users' passwords, but not their salts. I don't exactly understand why this is so, but am glad to have received a definitive reply on the matter.
Why do you want to empty out the password field?

Why don't you use the script I linked?


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

tomreyn

We want to keep the accounts of users who will not react to our e-mails inactive. We also want users to choose their own password based on our new password policy. And we do not want to send out passwords to user in plain text.

From what I understand your script generates a new, immediately active password for every registered user (whether they used their account during the past five years or not), and sends them through plain text e-mail. I did not actually read your code, though, just took a quick look at the thread you kindly pointed me to, so I may be wrong there.

To make and keep accounts inactive until people either reset their passwords (by means of requesting a password reset link and acing on it upon receipt and before a given deadline), we assumed the best method would be to replace all password by an empty string. This still seems to be our best options now. We must, however, not set the password_hash field to an empty string, since then, even if we also delete all current sessions, for reasons I find quite dubious, when a client with a forum cookie (containing the old username and password) accesses the forum, the hashed password is regenerated and written to the database, so the account is factually reactivated with the former password.

emanuele

Then you may have to read again my post:
Quote from: emanuele on July 26, 2013, 03:27:13 PM
Case 2:
* remove password: no login possible at all.
That means they will *never*, *ever* be able to login again. Not even recovering the passwords. At least from my tests.

According to what you want to achieve the only option is take my script, copy the resetPassword function from Subs-Auth.php to the script (remove the require_once too from the script) and remove the part about sending the email or (and that is probably much better) send an email informing them that the password has been reset and they will need to ask for a new one.


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

tomreyn

#14
After replacing my test accounts' password by an empty string in the database, deleting cookies on the client, failing to login and going through the password reset by e-mail, I was able to login fine. So this approach does seem to work.

When you say "recovering the passwords", do you refer to the process of setting a new user-provided password after receiving a password reset link by e-mail?

I do agree that the process you are suggesting, which basically boils down to replacing every users' password by a "randomly generated" one (actually those are a bit weak, the password takes one of 2147483647 (~2^31) values which can be pre-calculated), would work, too, with the exception that these randomly generated passwords could be guessed (an empty password can't be guessed since authentication will always fail until the user sets a new password during the password reset process). We'd also loose the ability to tell whether a given users' password has been reset, yet, or not.

The reason why you think that it will not be possible to ever login again if the password is set to the empty string, is this based on your test, or based on reviewing the code?

emanuele

It didn't work when I test on one computer, it worked on another one... I guess I misread something when testing it the first time.


Take a peek at what I'm doing! ;D




Hai bisogno di supporto in Italiano?

Aiutateci ad aiutarvi: spiegate bene il vostro problema: no, "non funziona" non è una spiegazione!!
1) Cosa fai,
2) cosa ti aspetti,
3) cosa ottieni.

tomreyn

Thanks for having tested again, and for having reported back, Emanuele, that's reassuring.

Advertisement: