How to fetch back Drupal 7 master password (uid 1)

Share and options

Sometimes you lose your master password. Won't describe here how you managed to do it, since distraction that lead to that kind of errors is a burden to carry for all of us.

Drupal 6 was quite easy to recover, because its passwords were encrypted using the well known MD5 digest algorithm, while Drupal 7 uses SHA512 and a custom seed depending on the site. This statement makes us unable to use well known functions for that.

In order to recover your password, there are two easy steps.

Generate a password

Password generation is the hardest thing to achieve, because of Drupal 7 hash algorithm. Because it would be a pain in the ass to rewrite it ourself, we are going to use Drupal core's include file to do it.

First, go to your site's root dir, and run PHP's console, then type this:

pounard@guinevere ~ $ cd /var/www/blog-d7/www
pounard@guinevere /var/www/blog-d7/www $ php -a
Interactive shell

php > require_once 'includes/bootstrap.inc';
php > require_once 'includes/password.inc';
php > $my_password = 'i_love_you_mom';
php > print _password_crypt('sha512', $my_password,
   _password_generate_salt(DRUPAL_HASH_COUNT));
$S$CnDAlEJa9/QSCZURnzYkhZF97XzGekyqRBWNUjdDLJIBBgOnJE99
php > exit
pounard@guinevere /var/www/blog-d7/www $

Got it? Copy the generated hash such as:
$S$CnDAlEJa9/QSCZURnzYkhZF97XzGekyqRBWNUjdDLJIBBgOnJE99 you have here.

If you are working on a remote environment on which you cannot connect, you can put this specified code in a file such as password.php such as this one:

<?php
if (isset($_GET['p'])) {
  require_once dirname(__FILE__) . '/includes/bootstrap.inc';
  require_once dirname(__FILE__) . '/includes/password.inc';
  print _password_crypt('sha512', $_GET['p'], _password_generate_salt(DRUPAL_HASH_COUNT));
  exit();
}
print "No password to hash.";

And then hit your site using: http://domain.tld/password.php?p='i_love_you_mom'. The hash will appear on your browser's tab. Don't forget to remove it once you done it.

Set it into the database

Then, use your favorite *SQL client, then type:

UPDATE users SET password = '$S$CnDAlEJa9/QSCZURnzYkhZF97XzGekyqRBWNUjdDLJIBBgOnJE99' WHERE uid = 1;
DELETE FROM flood;

Notice that the second is not mandatory, but if you attempt to many login failing to log in, Drupal would have set your own username/ip into flood table.
And you're done, you can then go and login in your site.

Commentaires

#1 – There is also one more way:

There is also one more way:

jimmy@onikode:~/www/acquia/docroot/scripts$ php password-hash.sh "newpassword"

Returns the hash.

#2 – Thanks

Thank you very much for this simpler way, I didn't notice this script file.
As you can see, I'm pretty much straighforward when it comes to introspect other's code:)

#3 – Can't you use just drush?

Can't you use just drush?

drush user-password

#4 – This would be a nice solution

This would be a nice solution, nevertheless:

pounard@blaster:/var/www/blog-d7/www
[Mon Jun 13, 15:38] $ drush help user-password
Invalid command user-password.                     [error]
An error occurred at function : drush_core_help    [error]

Am I missing something? May be I have a too old Drush version.
EDIT: Ah still running a 3.x on my personal box, this explains things! Thanks for the tip anyway.

Ajouter un commentaire