WordPress.org

Make WordPress Core

Opened 7 years ago

Last modified 8 months ago

#28625 assigned enhancement

Enhancement: Add constants to support SSL connections for mysqli

Reported by: hypertextranch Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 4.0
Component: Database Keywords: has-patch needs-unit-tests
Focuses: privacy Cc:

Description

In order to support SSL'ed MySQL connections with the mysqli_* functions introduced in WordPress 3.9 / PHP 5.5 mysqli_ssl_set() must be called to set the path to the SSL certs and keys to be used by the MySQL client before mysqli_real_connect() is called.

We should add the following optional constants to allow for users to configure secure connections to the database.

  • MYSQL_SSL_KEY
  • MYSQL_SSL_CERT
  • MYSQL_SSL_CA
  • MYSQL_SSL_CA_PATH
  • MYSQL_SSL_CIPHER

In addition this should only be set if the feature flag MYSQLI_CLIENT_SSL is set for the existing MYSQL_CLIENT_FLAGS constant.

Attachments (5)

r28625.patch (1.0 KB) - added by hypertextranch 7 years ago.
Initial proposed patch
sslkey.patch (1.2 KB) - added by andrewbevitt 7 years ago.
Patch which passes options directly instead of checking files exist
sslkey-v2.patch (1.2 KB) - added by andrewbevitt 7 years ago.
Updated to document when SSL options are set.
28625.2.diff (1.5 KB) - added by pbiron 8 months ago.
update patch so it applies cleanly
db.php (5.5 KB) - added by szaqal21 8 months ago.
db.php

Download all attachments as: .zip

Change History (28)

@hypertextranch
7 years ago

Initial proposed patch

#1 @hypertextranch
7 years ago

  • Keywords has-patch added
  • Summary changed from Enhancement: Add constants for support SSL connections for mysqli to Enhancement: Add constants to support SSL connections for mysqli

#2 @andrewbevitt
7 years ago

I agree this should be included. But, the patch shouldn't silently drop the certificate file if the file does not exist. This would allow the connection to be opened without SSL; assuming the MySQL server allows that.

It would be better to pass the parameter as given, and allow the mysqli_real_connect call to fail. This seems to be the intended idea, as the PHP docs for mysqli_ssl_set indicate it always returns TRUE (http://www.php.net/manual/en/mysqli.ssl-set.php).

Last edited 7 years ago by andrewbevitt (previous) (diff)

@andrewbevitt
7 years ago

Patch which passes options directly instead of checking files exist

#3 @hypertextranch
7 years ago

Your proposed method works for me. But just for good measure I think we should add a comment in the if ( $call_set ) block, maybe something along the lines of...

// SSL added here! :-)

#4 @DrewAPicture
7 years ago

  • Keywords dev-feedback added

@andrewbevitt
7 years ago

Updated to document when SSL options are set.

#5 @SergeyBiryukov
7 years ago

  • Keywords 4.1-early added
  • Milestone changed from Awaiting Review to Future Release

#6 @hypertextranch
7 years ago

Seems like this did not get into 4.1; guess we should target 4.2 instead?

#7 @szaqal21
6 years ago

Keep in mind that solution based on constants will force SSL for every new connection so there could be problem when creating new wpdb for database which doesn't support SSL. I think SSL should be set per wpdb object.

#8 @nacin
6 years ago

@pento, any thoughts on this?


How do other software projects handle configuration for this? I presume they do not use constants, and thus can use an array (in the case of PHP projects).

Replying to szaqal21:

Keep in mind that solution based on constants will force SSL for every new connection so there could be problem when creating new wpdb for database which doesn't support SSL. I think SSL should be set per wpdb object.

I agree with the concern here.

#9 follow-up: @pento
6 years ago

  • Keywords needs-refresh needs-unit-tests added; dev-feedback 4.1-early removed
  • Milestone changed from Future Release to 4.5

Other projects generally use PDO, and do their DB config as arrays, instead of constants.

mysqli_ssl_set() was added in PHP 5.3 - we probably should add a function_exists() check, even though it'd really only be a problem if someone has defined WP_USE_EXT_MYSQL as false in PHP 5.2. (And maybe fail to connect in this case, so that we're not silently using a non-SSL connection.)

For the concern about new wpdb instances, perhaps we need to add an $options parameter to wpdb::__construct()? $options['ssl'] would be an array of the SSL options (if your global config doesn't do SSL, or you want different SSL options), or false to prevent an SSL connection. Undefined uses the global config.

For the actual patch itself, I'm not wild about adding a pile of constants, but that's kind of the best option that keeps with the WordPress-y way. I can't decide if the foreach / call_user_func_array combination is too clever, or just the right amount of clever. It'd need to be reworked to work with $options, anyway. Also, it needs unit tests.

With all that said, I find myself being in favour of adding this functionality to Core, instead of recommending a drop-in. It's useful, it increases security, and I don't think it's possible to render your site unrecoverably broken (worst case: remove the constants from wp-config.php) with it.

#10 in reply to: ↑ 9 @INNOVOT
6 years ago

Replying to pento:

With all that said, I find myself being in favour of adding this functionality to Core, instead of recommending a drop-in. It's useful, it increases security, and I don't think it's possible to render your site unrecoverably broken (worst case: remove the constants from wp-config.php) with it.

100% agree with the final sentence. In this day and age there is no excuse not to use secure communications. Hope this does make it to Core.

Last edited 6 years ago by INNOVOT (previous) (diff)

#11 @johnbillion
6 years ago

  • Owner set to pento
  • Status changed from new to assigned

This ticket was mentioned in Slack in #core by jorbin. View the logs.


6 years ago

#13 @jorbin
6 years ago

  • Milestone changed from 4.5 to Future Release

#14 @hypertextranch
5 years ago

I agree with most of what pento suggests as well but in the meantime I have published the plugin I've been using to set SSL flags for connections as a stop gap.

https://wordpress.org/plugins/secure-db-connection/

#15 @maheshbhavana
4 years ago

Why is this not yet part of latest wordpress release? I thought ssl is basic.

This ticket was mentioned in Slack in #forums by danhgilmore. View the logs.


4 years ago

#17 @pento
21 months ago

  • Owner pento deleted

#18 @pbiron
8 months ago

Just wondering what is necessary to jump-start the effort on this ticket moving again (hopefully, for 5.8)?

I have a new project where I require secure DB connections. I've tests @hypertextranch 's plugin and it seems that it will work for us. However, since it uses a custom db.php drop-in, would be really nice to have this in core as there are many other highly used plugins (e.g., W3TC and QM) that need/want their own drop-ins.

@pbiron
8 months ago

update patch so it applies cleanly

#19 @pbiron
8 months ago

  • Keywords needs-refresh removed

refreshed patch so that it applies cleanly.

#20 @pbiron
8 months ago

  • Focuses privacy added

#21 follow-up: @pbiron
8 months ago

Note, I discovered over the weekend that, in at least some cases, WP 5.6 is capable of opening a secure connection to MySQL without any mods (or need for something like the Secure DB Connection plugin).

Don't know whether that is a result of changes in core/MySQL/PHP since this ticket was opened (until a few days ago I didn't know that encrypted connections to MySQL where possible :-)

I've tested in the follow 2 environments, and all I had to do was add

define( 'MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL )

to wp-config.php to get an encrypted connection.

Windows

WP 5.6
PHP 7.4.13
MySQL 5.7.10
Apache 2.4.37

CentOS 7

WP 5.6
PHP 7.4.14
MySQL 5.7.33
Apache 2.4.6 (altho I believe this includes many patches after that offial version num)

That doesn't mean that this ticket can be closed however. I guess there are setups that would require specifying other than default certs, which the patch allows to happen.

p.s. threw together a little plugin that displays whether the connection is secure:

  • At a Glance (and Network Right Now) dashboard widget (like Secure DB Connection does)
  • an admin bar node
  • a Site Health test and debug_info (the text of those need more work)

You can grab it from it from GitHub

#22 in reply to: ↑ 21 @hypertextranch
8 months ago

Replying to pbiron:

Note, I discovered over the weekend that, in at least some cases, WP 5.6 is capable of opening a secure connection to MySQL without any mods (or need for something like the Secure DB Connection plugin).

Don't know whether that is a result of changes in core/MySQL/PHP since this ticket was opened (until a few days ago I didn't know that encrypted connections to MySQL where possible :-)

I've tested in the follow 2 environments, and all I had to do was add

define( 'MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL )

to wp-config.php to get an encrypted connection.

I believe it depends on your server setup, if the system MySQL client was installed with trusted root certs and your database is using a key/cert that's signed by a root cert that you trust on the client then just adding the MYSQLI_CLIENT_SSL flag is enough. On modern systems with more root CAs preinstalled and use of cloud based database services that configure and install keys signed by common root CAs the need to explicitly set custom keys/certs/CAs becomes less needed.

This issue / patch was made for a time when things like https://letsencrypt.org didn't exist and spinning up a database didn't always come with a cert and might mean needing to generate random self-signed stuff.

#23 @szaqal21
8 months ago

SSL shouldn't be set by constants inside db_connect(), it will force SSL for every new wpdb() even for custom (external connections) to databases without SSL support. SSL should be set by passing some extra args to new wpdb() or some kind of filter before connection is made.

Attaching my db.php dropin.

@szaqal21
8 months ago

db.php

Note: See TracTickets for help on using tickets.