Problem/Motivation
Drupal does not currently verify that SSL certificates use a trusted root cert. This affects any requests initiated with drupal_http_request. It also affects OpenID discovery and HTTPS redirects during that discovery.
Proposed resolution
This issue includes solutions for Drupal 8 and the Drupal 7 backport.
For Drupal 8
For Drupal 7
1) Verify SSL certificates using curl_verify_ssl_peer. This only works when PHP is compiled with cURL support.
One drawback to this approach is that cURL is not always available in shared host environments. Commenters indicated that cURL is a relatively standard feature, and this should not be as much of a factor when D8 is released.
2) Include in Drupal a bundle of X.509 certificates of public Certificate Authorities (CA) borrowed from the cURL library.
greggles mentioned in comment 24 that this might require rapid security advisories in the case of a compromised cert. Also, including certs in Drupal core would logically add a configuration requirement where admins could add new certs.
Remaining tasks
Get Drupal 8 patch in.
Backport to Drupal 7 - Comment #25 includes a patch using curl_verify_ssl_peer, but it requires testing.
Possibly backport to D6.
API changes
This could affect developers who use drupal_http_request to issue HTTPS requests against servers that do not have proper SSL certs. For example, HTTPS connections would fail when issued to an internal dev server that used a self-signed cert.
Original report by Heine
Wojtha just asked on IRC if certificates are verified. They are not.
Demo patch in a few mins.
I am still very much +1 to the patch and would RTBC it, but please create a new issue for it, because the 8.x issue code change is different than the intention here.
#2761345: PHP 5.6, 7 - drupal_http_request() behavior changes for SSL using self-signed certs
might be a good candidate and we might also want to set a default 'default' entry of securing even older PHP versions and deliberately break compatibility to make upgrade to newer versions of PHP easier (break early with docs, rather than it breaking when upgrading PHP).
Thanks!
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | drupal-n3017522-5.patch | 2.25 KB | hart0554 |
| #2 | drupal-n3017522-2.patch | 2.2 KB | joseph.olstad |
Comments
Comment #2
joseph.olstadsee Fabianx comment #81 in parent issue
Comment #3
kmcculloch commentedThanks for re-rolling my work from comment 68 in the parent issue joseph.olstad. I'd still like to see this make it into core and I'm happy to do the work to make that happen.
The "Remaining Tasks" that you copied over from the parent issue are obviously out of date; the D8 patch is in and this patch uses a different approach from what was being discussed in comment 25.
So can I get some guidance as to what still needs to be done? I'm happy to do it!
Comment #4
joseph.olstadok, if you can, please update the "Remaining Tasks" as you see it. Then remove the Issue tag "Needs issue summary update" when you're done.
Tagging this as Drupal 7.64 target (7.63 was released yesterday)
Comment #5
hart0554 commentedThis patch doesn't apply to 7.64 since it changed settings.default.php slightly - here's a updated version.
Comment #6
mustanggb commentedComment #7
joseph.olstadtriggered tests for all available versions of PHP
Comment #8
mustanggb commentedComment #9
mustanggb commentedComment #10
stephencamilo commentedComment #11
poker10 commentedRevert status - https://www.drupal.org/project/site_moderators/issues/3276540
Comment #12
mcdruid commentedThis seems a lot less relevant now than it did several years ago when PHP (5.6) had only just started verifying SSL/TLS by default, and when self-signed certificates were a lot more common.
@Fabianx and I both +1'ed this approach in #1081192: Verify peer on HTTPS if cURL available (but be careful of built-in cert bundles in the codebase) but that was several years ago. I remember being very in favour of it back then.
2017 me mentioned a contrib. implementation in the original issue: #2774269: provide conditional configuration. I outlined a more flexible approach where the context could be customised per port and/or URL as well as just by host. It looks like I didn't implement that though. I don't recall why exactly but it does seem like it might be overly complicated.
If we were to commit this, nothing would change by default.. but sites would be able to set up new configurations.
I think that sounds okay, but I am really wondering whether this is "still a thing". Would any sites actually use this?
I'll RTBC it on the basis that I think it'd be safe to commit it, but I'd like to discuss whether we should a bit further with the other maintainers.
Oh, and I expect it might need a reroll as default.settings.php keeps getting new additions.
Comment #13
joseph.olstadPatch 5 still applies (with fuzz).
Comment #14
poker10 commentedI think that the benefit of this change is that sites on PHP 5.6+ can disable SSL/TLS verification for specific hosts when using
drupal_http_request(). By default it does verify SSL and it is not possible to change it (without replacing the function entirely, see below). So probably the issue has a bit different (opposite) purpose now, as it has years before and probably doesn't have much in common with the parent/original issue.In overall, I think it is a good change, as it will add a flexibility and more users will be able to use this API function without need of the replacement.
On the other hand, two points come to my mind:
1. We have possibility to replace the
drupal_http_request()with a different function, see:So it is questionable, if there are still sites which will benefit from this - probably most of them are using this override or do not use
drupal_http_request()at all.2. The settings.php is getting bigger and bigger (but it is not necessary a bad thing, we just need to carefully consider adding new config options).
-------------------
Anyway, if we want to commit this, I think we need to add a test for the new settings. We can probably test a subdomain with expired/invalid SSL (for example something like the https://badssl.com/ offers) and check if
drupal_http_request()works with the validation enabled / disabled.I will not change the status before the final decision.
Comment #15
mcdruid commentedYup, I think the self-signed SSL cert use case was the main reason I created https://www.drupal.org/project/alt_http_client which does exactly that.
I've updated the project a few times over the years to bring in updates made to core's
drupal_http_request(), but I'm not certain when I last did so.On the basis that it's perhaps not that common to need to deviate from PHP's defaults these days, there's an argument to leave this to be dealt with in contrib.
Comment #16
mcdruid commentedOh, #3299146: re-sync with D7 core's drupal_http_request() is about updating alt_http_client with changes from core's drupal_http_request().
I think when I filed that I was waiting for a patch to be committed. Looks like it's all ready to go now.
If I updated that project, shall we close this issue for core with the recommendation that sites use alt_http_client if they need to tweak SSL options?
Comment #17
poker10 commented+1 for this. There is/will be a fully functional module with the same functionality as is proposed here. Considering a number of sites which will possible use this and also other options they have, I think this will be the best solution.
Comment #18
mcdruid commentedThere's now a 7.x-1.1 release of alt_http_client with the updates from core plus tests.
The module includes pretty much the same code as the patch in this issue:
https://git.drupalcode.org/project/alt_http_client/-/blob/7.x-1.1/alt_ht...
We should try to remember to update the module whenever core's
drupal_http_request()changes.Thanks everyone who worked on this, especially @kmcculloch for the original patch.