Strange PasswordRecovery behavior?

Strange PasswordRecovery behavior?

am 08.11.2007 23:08:02 von morganpdx

I have a PasswordRecovery web control as part of my login functionality that
I have successfully tested in an application I'm building. I was asked to
migrate some historical user data into the aspnet_application_services tables
for this app, so I thought the best thing to do would be to just migrate all
the user data with the exception of the passwords, and add text to the
membership comment that read 'EncryptMe' or something like that. Then just
write a method that would check the comments, and if it said the same thing
(encryptme) it would reset the password using the membership object
ResetPassword method. Ok so all this works like a charm, until I try to do
the password recovery as if I was one of these historical users logging in
and trying to find out my new password that was generated. The email arrives
without a hitch, except...only HALF the password shows up. I confirmed this
because I output the newly generated passwords when I run the reset password
method, and then compared it to the one in the email. The last example
looked like this:

Generated password: BvCj@y-b88KO{U
Emailed password: 88KO{U

I'm stumped. Any ideas? I did notice that there's no longer a password
salt in the membership database, could this be the problem? Any idea how to
deal with it if it is?

Help!!

TIA,

Morgan
Web Developer
Portland, Oregon

RE: Strange PasswordRecovery behavior?

am 09.11.2007 09:29:55 von wawang

Hi Morgan,

That's indeed a very strange issue. If you handle the PasswordRecovery's
SendingMail event and check MailMessageEventArgs.Message.Body, does it
already contain truncated password?

The default Membership provider should have already enabled resetting
password when recoverying password; what if you comment the call to
ResetPassword and use PasswordRecovery directly?

If you create a small test web application from scratch and test this
PasswordRecovery function, does it work?


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

RE: Strange PasswordRecovery behavior?

am 09.11.2007 20:48:01 von morganpdx

I checked the MailMessageEventArgs.Message.Body, and it was truncated already
at that point. So I changed the web config to not allow password retrieval
and allow password reset, and that worked. Thanks for the recommendation!
It's not the solution I was hoping for, but it is perfectly workable.

I am still curious as to why the passwords were being truncated in the first
place, and only on the historical data? I checked a non-historical user, and
the password retrieval worked as expected. I also double checked the
truncation effect for historical entries, and was able to consistently repeat
it. My only guess remains that it has to do with the password salt column,
since that is populated on non historical data and empty for historical
entries. Any ideas? Insight into how the salt works?
--
Morgan
Web Developer
Portland, Oregon


""Walter Wang [MSFT]"" wrote:

> Hi Morgan,
>
> That's indeed a very strange issue. If you handle the PasswordRecovery's
> SendingMail event and check MailMessageEventArgs.Message.Body, does it
> already contain truncated password?
>
> The default Membership provider should have already enabled resetting
> password when recoverying password; what if you comment the call to
> ResetPassword and use PasswordRecovery directly?
>
> If you create a small test web application from scratch and test this
> PasswordRecovery function, does it work?
>
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>

RE: Strange PasswordRecovery behavior?

am 12.11.2007 06:38:42 von wawang

Hi Morgan,

The password salt is used to further protect the password from attaching by
using a random string to prefix the password before hashing it:

#Security Briefs: Hashing Passwords, The AllowPartiallyTrustedCallers
Attribute -- MSDN Magazine, August 2003
http://msdn.microsoft.com/msdnmag/issues/03/08/SecurityBrief s/

To slow down the attack, use salt. Salt is a way to season the passwords
before hashing them, making the attacker's precomputed dictionary useless.
Here's how it's done. Whenever you add an entry to the database, you
calculate a random string of digits to be used as salt. When you want to
calculate the hash of Alice's password, you look up the salt value for
Alice's account, prepend it to the password, and hash them together.


You can also use Reflector (http://www.aisto.com/roeder/dotnet/) to view
MembershipProvider.EncodePassword:

internal string EncodePassword(string pass, int passwordFormat, string
salt)
{
if (passwordFormat == 0)
{
return pass;
}
byte[] buffer1 = Encoding.Unicode.GetBytes(pass);
byte[] buffer2 = Convert.FromBase64String(salt);
byte[] buffer3 = new byte[buffer2.Length + buffer1.Length];
byte[] buffer4 = null;
Buffer.BlockCopy(buffer2, 0, buffer3, 0, buffer2.Length);
Buffer.BlockCopy(buffer1, 0, buffer3, buffer2.Length,
buffer1.Length);
if (passwordFormat == 1)
{
HashAlgorithm algorithm1 =
HashAlgorithm.Create(Membership.HashAlgorithmType);
if ((algorithm1 == null) &&
Membership.IsHashAlgorithmFromMembershipConfig)
{

RuntimeConfig.GetAppConfig().Membership.ThrowHashAlgorithmEx ception();
}
buffer4 = algorithm1.ComputeHash(buffer3);
}
else
{
buffer4 = this.EncryptPassword(buffer3);
}
return Convert.ToBase64String(buffer4);
}


Based on my understanding, ResetPassword should also be using this method
to reset the password. I'm not sure why it will include a password salt
while the database actually doesn't have one. Maybe you could post some
code here to let me reproduce the issue on my side and find out why.

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

RE: Strange PasswordRecovery behavior?

am 14.11.2007 22:15:00 von morganpdx

Here's some code and data for you to try working with:

Password:
hk4aoIj2cSjpcGtDIqnxt78ao71pnIyLbTPH+Tv3KR4=
MMlZVIjED94iuCadeB9nNhiqYW1s28t3a2s83OIbjaE=


PasswordFormat:
2
2

PasswordSalt:
(EMPTY STRING)
Jm/fuPDVPA22OYVC0WJ95A==

Comment:
"EncryptMe"
(NULL)

Code:
foreach (MembershipUser theUser in allUsers)
{
if (theUser.Comment == "EncryptMe")
{
p = theUser.ResetPassword();
theUser.Comment = "";
Membership.UpdateUser(theUser);
}
}



Insert the two records into aspnet_membership (fill in the rest of the
columns with whatever defaults or data you like)

Run the code, it should generate a new password for the record w/ no salt
(You can add the 'encryptme' to the other record too, so you know what the
passwords are for both)

try to retrieve both passwords. One should work, one should not.

--
Morgan
Web Developer
Portland, Oregon


""Walter Wang [MSFT]"" wrote:

> Hi Morgan,
>
> The password salt is used to further protect the password from attaching by
> using a random string to prefix the password before hashing it:
>
> #Security Briefs: Hashing Passwords, The AllowPartiallyTrustedCallers
> Attribute -- MSDN Magazine, August 2003
> http://msdn.microsoft.com/msdnmag/issues/03/08/SecurityBrief s/
>
> To slow down the attack, use salt. Salt is a way to season the passwords
> before hashing them, making the attacker's precomputed dictionary useless.
> Here's how it's done. Whenever you add an entry to the database, you
> calculate a random string of digits to be used as salt. When you want to
> calculate the hash of Alice's password, you look up the salt value for
> Alice's account, prepend it to the password, and hash them together.
>

>
> You can also use Reflector (http://www.aisto.com/roeder/dotnet/) to view
> MembershipProvider.EncodePassword:
>
> internal string EncodePassword(string pass, int passwordFormat, string
> salt)
> {
> if (passwordFormat == 0)
> {
> return pass;
> }
> byte[] buffer1 = Encoding.Unicode.GetBytes(pass);
> byte[] buffer2 = Convert.FromBase64String(salt);
> byte[] buffer3 = new byte[buffer2.Length + buffer1.Length];
> byte[] buffer4 = null;
> Buffer.BlockCopy(buffer2, 0, buffer3, 0, buffer2.Length);
> Buffer.BlockCopy(buffer1, 0, buffer3, buffer2.Length,
> buffer1.Length);
> if (passwordFormat == 1)
> {
> HashAlgorithm algorithm1 =
> HashAlgorithm.Create(Membership.HashAlgorithmType);
> if ((algorithm1 == null) &&
> Membership.IsHashAlgorithmFromMembershipConfig)
> {
>
> RuntimeConfig.GetAppConfig().Membership.ThrowHashAlgorithmEx ception();
> }
> buffer4 = algorithm1.ComputeHash(buffer3);
> }
> else
> {
> buffer4 = this.EncryptPassword(buffer3);
> }
> return Convert.ToBase64String(buffer4);
> }
>
>
> Based on my understanding, ResetPassword should also be using this method
> to reset the password. I'm not sure why it will include a password salt
> while the database actually doesn't have one. Maybe you could post some
> code here to let me reproduce the issue on my side and find out why.
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>

RE: Strange PasswordRecovery behavior?

am 16.11.2007 09:40:05 von wawang

Hi Morgan,

Thanks for your detailed code. I've been able to reproduce the issue on my
side.

Further research shows the PasswordSalt column is essential for
SqlMembershipProvider to retrieve the password. Usually this column is
maintained internally by the provider and you don't need to handle it.
Since your scenario is related to some legacy data and need to migrate to
it, I suggest use following function to generate a PasswordSalt value for
each user which currently doesn't have one:

string GenerateSalt()
{
byte[] data = new byte[0x10];
new RNGCryptoServiceProvider().GetBytes(data);
return Convert.ToBase64String(data);
}


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.

RE: Strange PasswordRecovery behavior?

am 16.11.2007 17:01:01 von morganpdx

Thanks Walter! works like a charm :D
--
Morgan
Web Developer
Portland, Oregon


""Walter Wang [MSFT]"" wrote:

> Hi Morgan,
>
> Thanks for your detailed code. I've been able to reproduce the issue on my
> side.
>
> Further research shows the PasswordSalt column is essential for
> SqlMembershipProvider to retrieve the password. Usually this column is
> maintained internally by the provider and you don't need to handle it.
> Since your scenario is related to some legacy data and need to migrate to
> it, I suggest use following function to generate a PasswordSalt value for
> each user which currently doesn't have one:
>
> string GenerateSalt()
> {
> byte[] data = new byte[0x10];
> new RNGCryptoServiceProvider().GetBytes(data);
> return Convert.ToBase64String(data);
> }
>
>
> Regards,
> Walter Wang (wawang@online.microsoft.com, remove 'online.')
> Microsoft Online Community Support
>
> ==================================================
> When responding to posts, please "Reply to Group" via your newsreader so
> that others may learn and benefit from your issue.
> ==================================================
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>