Database credentials are logged when there is a connection exception

Created on 13 June 2019, over 5 years ago
Updated 16 January 2024, 11 months ago

Moved from security bug report: "This should be a pubic hardening since there is no direct exploit"

Risk: If someone has
* At least read-only access to wherever php is writing its error logs,
* And can cause Drupal to fail to connect to the database (or can just wait for a network event that causes this),
Then they can find the username and password Drupal is using to connect.

This is with Drupal 8.6.16
I’m fairly certain this is in just Drupal Core, but haven’t actually tried it with just a base install.

If Drupal fails to connect to the database, it logs to the standard error log: (sanitized our database and password info with XXXX)
PDOException: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or
service not known in /var/www/html/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php on line 79 #0 /var/www/html/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php(420): PDO->__construct('mysql:host=va-v...', 'XXXdevweb', 'XXXXXXXXXXXX', Array)\n#1 /var/www/html/core/lib/Drupal/Core/Database/Database.php(371): Drupal\\Core\\Database\\Driver\\mysql\\Connection::open(Array)\n#2 /var/www/html/core/lib/Drupal/Core/Database/Database.php(166): Drupal\\Core\\Database\\Database::openConnection('default', 'default')\n#3 [internal function]: Drupal\\Core\\Database\\Database::getConnection('default')\n#4 /var/www/html/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php(79): call_user_func_array('Drupal\\\\Core\\\\Dat...', Array)\n#5 /var/www/html/core/lib/Drupal/Component/DependencyInjection/Container.php(171): Drupal\\Component\\DependencyInjection\\PhpArrayContainer->createService(Array, 'database')\n#6 /var/www/html/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php(260): Drupal\\Component\\DependencyInjection\\Container->get('database', 1)\n#7 /var/www/html/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php(62): Drupal\\Component\\DependencyInjection\\PhpArrayContainer->resolveServicesAndParameters(Array)\n#8 /var/www/html/core/lib/Drupal/Component/DependencyInjection/Container.php(171): Drupal\\Component\\DependencyInjection\\PhpArrayContainer->createService(Array, 'cache.container')\n#9 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(543): Drupal\\Component\\DependencyInjection\\Container->get('cache.container')\n#10 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(904): Drupal\\Core\\DrupalKernel->getCachedContainerDefinition()\n#11 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(476): Drupal\\Core\\DrupalKernel->initializeContainer()\n#12 /var/www/html/core/lib/Drupal/Core/DrupalKernel.php(692): Drupal\\Core\\DrupalKernel->boot()\n#13 /var/www/html/index.php(19): Drupal\\Core\\DrupalKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request))\n#14 {main}

Which includes both the username (XXXdevweb) and password (XXXXXXXXXXXX) in plain text.

The problem is in core/lib/Drupal/Core/Database/Driver/mysql/Connection.php in the catch for line 419. The default error handler prints the sensitive information.
try {
$pdo = new \PDO($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
}
catch (\PDOException $e) {
if ($e->getCode() == static::DATABASE_NOT_FOUND) {
throw new DatabaseNotFoundException($e->getMessage(), $e->getCode(), $e);
}
if ($e->getCode() == static::ACCESS_DENIED) {
throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);
}
throw $e;
}

The below fixes the issue, but uses DatabaseAccessDeniedException() incorrectly, and shouldn’t be used, but a new exception handler like it would probably be the correct solution. I just don’t have the time to dig into things to identify what’s the correct resolution, and this works well enough for us.
diff a/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php b/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php
429c429
> throw $e;
---
< throw new DatabaseAccessDeniedException($e->getMessage(), $e->getCode(), $e);

--
Thanks,

Billy Arnold
Senior Systems Administrator
Virginia Interactive / VI

🐛 Bug report
Status

Closed: duplicate

Version

11.0 🔥

Component
Database 

Last updated 2 days ago

  • Maintained by
  • 🇳🇱Netherlands @daffie
Created by

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024