Kirby Panel forgot password

Hello guys, I have created a PHP file that allows you to reset the account password in Kirby Panel if you accidentally forgot it… You can download it here… It works just like Wordpress forgot password feature; It asks for your username and sends reset instructions to the email associated with the username… The reset instructions contain a link to reset your password… It uses the Kirby toolkit for most of its functions… The url parameters are blowfish encrypted and can only be decrypted using the decrypt key auto generated in the server (the decrypt key is located in Kirby/.htresetkey)… The url parameters are “username”, “key”, and “token”… The username is your username, the key is your blowfish encrypted base64 hashed old password, and the token is the blowfish encrypted base64 timestamp…
The username parameter is used to identify which account to reset… The key parameter is used to validate the url if it matches with the old password in the server, and invalidate it if otherwise… The token parameter is just an encrypted timestamp, it uses the timestamp to check how many hours have passed when the reset link has been generated, if 5 hours or more have passed since the generation of the reset link it is automatically invalidated…
#Main features

  • Encrypted reset link
  • Reset link auto expire after 5 hours
  • Sends you the reset link via email
  • Kirby panel theme
  • CODED WITH LOVE :smile:
    #Installation
    Download and upload forgot.php file to the directory where you installed Kirby CMS…
    That’s it!!! You may now give it a wave…

PS: I can’t officially call it a plugin it or so, because it’s installation method is quite different from most Kirby plugins… You can enlighten me about plugins by replying below…

Wishing you a happy day!!,
Phoenix Aspacio :smile:

2 Likes

Great idea.

I have not looked at the entire code, but I have found one security issue: The resetkey randomizer is not cryptographically secure. I recommend the following code:

do {
  $bytes = openssl_random_pseudo_bytes(20, $crypto_strong);
  $hex = bin2hex($bytes);
} while(!$crypto_strong);

return $hex;

The random key generated by the randomizer is not used in the “KEY” parameter in the url, it is the key to encode and decode the Encrypted hashed old password…

The “KEY” parameter in the url is an “ENCRYPTED” hashed old password… Since it is encrypted, it means it needs a “KEY” to be decrypted, and that’s where the “Key Randomizer” comes in and the result randomized key is stored in “kirby/.htresetkey”…

I believe that is not a security problem, however if you’re really sure what you meant, then you can add a pull request in github for me to test it… I have a code summary for you to easily understand the whole code…

PS: I am really sorry, I am really not fun of commenting and indenting my codes…

Code Summary

Before everything runs, the php script checks if the file “kirby/.htresetkey” is existing, if it exists and contains 8 alphanumeric characters then it continues the script and returns the client a send email using username form to fill-up, if it doesn’t exist it creates the file and generates a 8 character randomized alphanumeric string to be written on the file and returns the client a send email using username form to fill-up…

After the client sends the username with the form using the POST method, the server side script automatically process it by checking if the username exists and has a valid email address associated with it, if it doesn’t then the script returns an error to the client… After the email address has been validated, the script generates a “key” and a “token”… The “KEY” will be used to be the value of the key parameter, the “KEY” is generated by encrypting (The key in encrypting it is the 8 character alphanumeric string inside the kirby/.htresetkey file) the old hashed password… The “TOKEN” will be used to be the value of the token parameter, the “TOKEN” is generated by encrypting (The key in encrypting it is the 8 character alphanumeric string inside the kirby/.htresetkey file) current time or TIMESTAMP… After “KEY” and “TOKEN” is generated, it will be attached to the Reset Password URL that will be emailed to you… So the format of the reset link would be http://example.com/forgot.php?username=%USERNAME%&key=%ENCRYPTED_OLD_PASSWORD%&token=%ENCRYPTED_TIMESTAMP%

After the email containing the reset link has been sent to the client’s email address and the client clicks the reset link… This is what happens:
Before everything runs, the php script checks if the file “kirby/.htresetkey” is existing, if it exists and contains 8 alphanumeric characters then it continues the script and returns the client a NEW PASSWORD form to fill-up if it passed the requirements below, if it doesn’t exist, it creates the file and generates a 8 character randomized alphanumeric string to be written on the file and returns the client a NEW PASSWORD form to fill-up if it passed the requirements below…

Requirements:

  • Username must exist… It is checked by searching for the file
    $_GET[‘username’].".php" that is stored in the kirby panel accounts folder…
  • The encrypted value in the “KEY” parameter must be equal to the
    hashed password in the $_GET[‘username’].".php" that is stored in the
    kirby panel accounts folder. It is checked by Decrypting (The key in decrypting it is the 8 character alphanumeric string inside the kirby/.htresetkey file) the encrypted value in the “KEY” parameter, after the value has been decrypted it will be compared to the old hashed password in the $_GET[‘username’].".php" …if matched continue script, return error if otherwise…
  • The encrypted value in the “TOKEN” parameter must not be 5 hours or
    more old, otherwise it will invalidate the reset link… It is checked
    by Decrypting (The key in decrypting it is the 8 character
    alphanumeric string inside the kirby/.htresetkey file) the encrypted
    value in the “TOKEN” parameter, after the value has been decrypted,
    the hours have passed since the decrypted TIMESTAMP will be counted…
    If less than 5 hours then continue script, return error if otherwise.

If the client has passed the requirements and sends the New Password with the form using the POST method rechecks the requirements above and if it passes again it will hash the NEW PASSWORD and write it in the $_GET[‘username’].".php" that is stored in the
kirby panel accounts folder… If everything is fine, then the sript should return a message saying that “You may now login with your new password in kirby panel”…

I understand how your code works, thanks anyway. :smile:

An encryption key always needs to be random, no matter what gets encrypted by it. The PHP rand function shouldn’t be used at all for crypto, because it’s not random enough. Using more secure (more random) bytes generated by OpenSSL is always better.

You can simply replace your generateRandomString function code with my code (you need to replace the 20 with $length though). I strongly recommend using more than 8 or 10 bytes, because that’s very easy to attack using brute force. The encrypted data is not very sensitive (the password is hashed anyway), but I still think that it makes sense to use strong encryption, because otherwise it would be very easy to fake the token parameter.

@lukasbestle thanks for the information I would try to follow your advice and adjust some things because if we make the key very long it could lead to 414 Request-URI Too Long error…

Well, no. Encrypted data does not get longer if the key is longer.

Ahhh!! Okay :wink: Thanks!!!

Good idea. I think this function belong to the core. Anyone against it? If so, why?

1 Like

It would indeed be better to have that in the core, maybe you can post a feature request on Github, @jenstornell?

2 Likes

I don’t think you can be against this feature, but I’m not sure whether it would be used by enough users to be worth it. Because a site typically has not many users, you can always ask the admin to set a new password for you. Implementing a password reset in the Panel core can create security issues.

I think that depends on the site and the admin might not always be available.

Would this be less secure than using an external solution like @PhoenixPeca has suggested? I would think that such a feature would be better off in the core.

1 Like

That’s true!

No, definitely not. Given a well structured code that follows security best practices, it’s not insecure. But every additional feature (even more every feature that might allow unauthorized access to a CMS) can be insecure. This feature requires much care if integrated into the Panel IMHO.

2 Likes

If this feature will be added to the core, then I think it would be better to have the feature that can turn it off with the config file… I mean, not all administrators wanted a forgot password feature because enabling it would lead to possible security issues as stated above… :smiley:

1 Like

I just thought the same thing. The best of both worlds. Then hardcore developers can use their alternative own super security system, like this one for example. The rest can use a secure core default password resetter.

@lukasbestle Does that sound good to you?

Added an issue on github:

I think this feature should be added to the Kirby panel core. Therefor I added the issue to the Kirby panel repository. Then Bastian can deside what to do with it.

He could:

  • Close the issue without doing anything about it
  • Implement your or any other solution for it
  • Make an own solution for it

I cant even understand my own code; its too messy… I wish bastian can create another way to create reset password system…

I think that making it an optional feature is a great solution!

2 Likes

I totally agree. Most of my customers would not need such a function, therefore it would make sense to make this optional. I would not want to use potentially risky feature if there is no need for it.

And there it should be.

Hi there,

What is the status of this?

I’ve noticed that the original plugin isn’t there anymore


any reason for taking it down?

@samnabi, I guess this is also a crucial feature for online shopping, I mean it is pretty much expected that an online store allows customers to reset their passwords, no?

Thanks

This might have been the reason:

1 Like