[SECURITY] Information disclosure on database failures

In case the database is not responding, e.g. due to "too many connections"
cut-off database credentials might be shown and system path be revealed.
In terms of security this is considered as information disclosure.
This commit is contained in:
Oliver Hader
2016-06-04 20:18:19 +02:00
parent 85f707af8a
commit 2e7133d619
2 changed files with 67 additions and 5 deletions

View File

@@ -323,15 +323,18 @@ class Database {
$sql_root = array(0 => array('caption' => 'Default', 'host' => $sql['host'], 'socket' => (isset($sql['socket']) ? $sql['socket'] : null), 'user' => $sql['root_user'], 'password' => $sql['root_password']));
}
$substitutions = array(
$sql['password'] => 'DB_UNPRIV_PWD',
$sql_root[0]['password'] => 'DB_ROOT_PWD',
);
// hide username/password in messages
$error_message = $error->getMessage();
$error_trace = $error->getTraceAsString();
// error-message
$error_message = str_replace($sql['password'], 'DB_UNPRIV_PWD', $error_message);
$error_message = str_replace($sql_root[0]['password'], 'DB_ROOT_PWD', $error_message);
$error_message = self::_substitute($error_message, $substitutions);
// error-trace
$error_trace = str_replace($sql['password'], 'DB_UNPRIV_PWD', $error_trace);
$error_trace = str_replace($sql_root[0]['password'], 'DB_ROOT_PWD', $error_trace);
$error_trace = self::_substitute($error_trace, $substitutions);
if ($error->getCode() == 2003) {
$error_message = "Unable to connect to database. Either the mysql-server is not running or your user/password is wrong.";
@@ -365,6 +368,9 @@ class Database {
@fclose($errlog);
if ($showerror) {
if (empty($sql['debug'])) {
$error_trace = '';
}
// fallback
$theme = 'Sparkle';
@@ -402,4 +408,58 @@ class Database {
die("We are sorry, but a MySQL - error occurred. The administrator may find more information in the syslog");
}
}
/**
* Substitutes patterns in content.
*
* @param string $content
* @param array $substitutions
* @param int $minLength
* @return string
*/
private static function _substitute($content, array $substitutions, $minLength = 6) {
$replacements = array();
foreach ($substitutions as $search => $replace) {
$replacements = $replacements + self::_createShiftedSubstitutions($search, $replace, $minLength);
}
$content = str_replace(
array_keys($replacements),
array_values($replacements),
$content
);
return $content;
}
/**
* Creates substitutions, shifted by length, e.g.
*
* _createShiftedSubstitutions('abcdefgh', 'value', 4):
* array(
* 'abcdefgh' => 'value',
* 'abcdefg' => 'value',
* 'abcdef' => 'value',
* 'abcde' => 'value',
* 'abcd' => 'value',
* )
*
* @param string $search
* @param string $replace
* @param int $minLength
* @return array
*/
private static function _createShiftedSubstitutions($search, $replace, $minLength) {
$substitutions = array();
$length = strlen($search);
if ($length > $minLength) {
for ($shiftedLength = $length; $shiftedLength >= $minLength; $shiftedLength--) {
$substitutions[substr($search, 0, $shiftedLength)] = $replace;
}
}
return $substitutions;
}
}