How to secure settings.php file in Drupal

Settings file protection by password encryption

Settings.php was criticized for storing the plain text MySQL username and password. This procedure will let us remove the username and password from the settings.php and let us put that credentials outside of the website directory and store into another folder which can be taken care by security team or server managing people.

To do this, include a line at the top of settings.php file:

require_once '../secure_mysite/secure_credentials.php';

This line specify that include a script called “secure_credentials.php” and if it’s not found, stop the script from further running. For now, we have created a secure folder called “dbpw” which we have stored outside of website directory. We stored our php script into this folder and call that script using above line inside settings.php.
This secure_credentials.php contain two function i.e. one for encryption and one for decryption.


function encrypt_credentials($username, $password, $encrypted_key = NULL, $iv = NULL) {
  $method = "AES-256-CBC";
  $password_file = "/www/htdocs/secure_mysite/pass.txt";
  $key_file = "/www/htdocs/secure_mysite/key.txt";
  $wasItSecure = true;
  $ivlen = openssl_cipher_iv_length($method);
  $iv = openssl_random_pseudo_bytes($ivlen, $wasItSecure);

  if (!file_exists($key_file)) {
  	if(!$fh = fopen($key_file, "w")) { die("

Could Not Open Key File"); } $encrypted_key = openssl_random_pseudo_bytes(32); $result = fwrite($fh, $encrypted_key); fclose($fh); } $encrypted_data = openssl_encrypt($password, $method, $encrypted_key, 0, $iv); //create a file handler by opening the file if(!$fh = fopen($password_file, "w")) { die("

Could Not Open Password File"); } $txt = $username . ":" . $encrypted_data . ":" . $iv; $result = fwrite($fh, $txt); if($result) echo "Username and Password successfully encrypted and stored\n"; fclose($fh); } function decrypt_credentials($param) { $password_file = "/www/htdocs/secure_mysite/pass.txt"; $key_file = "/www/htdocs/secure_mysite/key.txt"; $method = "AES-256-CBC"; $filecontents = file_get_contents($key_file); $all_words = preg_split('/[\s]+/', $filecontents, -1, PREG_SPLIT_NO_EMPTY); if(!$fh = fopen($password_file, "r")) { die("

Could Not Open Password File"); } while(!feof($fh)) { $line = fgets($fh, 4096); $from_file = explode(":", $line); } $decrypted_pass = openssl_decrypt($from_file[1], $method, $all_words[0], 0, $from_file[2]); fclose($fh); return ($param == 'username') ? $from_file[0] : $decrypted_pass; }

Encryption Function:

function encrypt_credentials($username, $password, $rand_pass = NULL, $iv = NULL) {}

This function takes 4 parameters in which 2 are optional, but username and password is required. This function used AES-256-CBC encryption method to encrypt the password. To use the encryption properly I have used:

string openssl_encrypt ( string $data , string $method , string $password [, int $options = 0 [,string $iv = "" ]] )

For making this script more automatic and independent I have generated 3rd argument $encrypted_key in above function by using an inbuilt function openssl_random_pseudo_bytes(). This key will be stored in a separate key file called “key.txt”. The key will be generated only once when the program runs first time. If you want to generate a new or different key you have to delete key.txt file. The openssl_encrypt() function require one more parameter which is “iv” (initialization vector) as the 5h parameter. The “iv” is generated automatically in this script by PHP inbuilt function openssl_random_pseudo_bytes(). Then all these parameters passed into openssl_encrypt() function to generate the encrypted data. The generated data will be stored inside “pass.txt” file. This text file contain 3 parameters as well which are separated by “:” parameter.
Username: Encrypted Data: IV

To run the above function we need to run this command by CD into the folder and then run the command from the command line:

 php -r 'require "secure_credentials.php";encrypt_credentials("superman", "makeitsecure!#2");' 

Where superman is example of username and makeitsecure!#2 is the password.

You will only need to run this command with username and password. With this command it will call the encrypt_credentials() function inside the secure_credentials.php file and store the results in pass.txt file. File pass.txt will look something like this:

 superman:cmWK+ymPjL7vB5v4+FM39A==:°ß™™ÊÏ s߈ÜÄVë 

When the settings file will run it will call the decrypt function.
The two statements inside the settings file will call the decrypt function in the secure_credentials.php file.

$databases = array (
  'default' => 
  array (
    'default' => 
    array (
      'database' => 'yourdb',
      'username' => decrypt_credentials('username'), //Note this statement
      'password' => decrypt_credentials('password'), //Note this statement
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',

When this function is called, it looks for the pass.txt, opens it and decrypt the password and send the password in the decrypted format to the Drupal back again.
By above process we are not storing the plain password anywhere and the password will be only known by the Person who will run the command line function. If he forgots the password, this command line function needs to be run once again.