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.

1. 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.

2. 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.