Why does PDO print my password when connection fails?

I have a simple site where I am connecting to a Mysql server using PDO.

$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER', 'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); 

I had some traffic on my site, and the connection limit to the server was reached, and the site gives this error with my password PLAIN!

Fatal error: exception for exception 'PDOException' with message 'SQLSTATE [08004] [1040] Too many connections' in /home/domain/html/index.php:xxx Stack trace: # 0 / home / domain / html / index. php (64): PDO β†’ __ construct ('MySQL: host = Crazy ...', 'USER', 'SECRET', Array) # 1 {main} thrown /home/domain/html/index.php on line 64

Ironically, I switched to PDO for security reasons, so it really shocked me because this exact error is something that you can very easily provoke on most sites using a simple HTTP attack.

Now I wrapped my connection in a try / catch block, but still think this is disastrous!

I am new to PDO, and so my question is: what should I do to be considered safe? How to establish a connection in a safe way? Are there other known security holes like this one that I should be aware of?

+43
security php mysql pdo connection
Jun 23 2018-11-11T00:
source share
4 answers

You must have display_errors = off in your PHP.ini anyway to avoid this problem. Errors that reveal such data come from many places, in addition to PDO.

Yes, you should also have it in a try / catch block.

You can also $pdo->setAttribute(PDO::ERRMODE_SILENT) , but then you need to manually check the error codes, and not use the try / catch block. See http://php.net/manual/en/pdo.setattribute.php for additional error constants.

+15
Jun 23 2018-11-11T00:
source share

Well, that made me giggle a bit, using error reporting is for debugging purposes, it allows me to quickly find and fix problems.

When you are in a live environment, your server should be configured only for internal logging, and not for direct output, so basically you will need to disable error output in your php.ini .

 display_errors = Off 

But while you are in your test environment, this stack is just a tool that will help you and customize.

If errors occur in a live environment, they will be logged, so you should always check your log files and then correct them.

People may indicate that you can manage errors in your PHP application, but by personal preference, I think this is the wrong way to do this, setting up the INI and configuration files for your web server and MySQL / MsSQL will lead to more sharp control.

If your application is a public application, then it would be nice to handle errors in the application, since a large percentage of clients may be on shared hosting and not have full access to server configurations.

+6
Jun 23 2018-11-11T00:
source share

A simple workaround to catch the PDOException thrown by the PDO constructor:

 try { $dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER', 'SECRET',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")); } catch (PDOException $e) { throw new Exception('Could not connect to database'); } 
+6
Sep 30 '14 at 12:40
source share

We use the encoded username and passwords and decode them in the PDO constructor, then we catch the PDOException and raise a new PDOException with the old exception from his message, so that the trace displays only the encoded username and password.

A good encryption library for PHP is: defuse / php-encryption

https://github.com/defuse/php-encryption

Code example:

 <?php class myPDOWrapper extends PDO { public function __construct(string $dns, string $encodedUser, string $encodedPassword) { try { parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword), [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ] ); } catch (PDOException $exception) { throw new PDOException($exception->getMessage()); } } private function decodeFunction(string $encoded): string { return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey()); } private function decodeKey(): \Defuse\Crypto\Key { static $key = null; if(null === $key) { $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY')); } return $key; } } 
+1
May 29 '17 at 10:57
source share



All Articles