Path: machine_name/transliterate?replace_pattern=a@e%00&replace=a
Сallback:
href="https://api.drupal.org/api/drupal/core%21modules%21system%21src%21Machin...">MachineNameController::transliterate
All parameters that we pass to preg_replace come from the request so can be easily tweaked. That makes it possible to exploit dangers of preg_replace.
The vulnerability is mitigated by the fact that we bumped minimal PHP version yesterday. So that new installations of Drupal 8 are not affected, however tweaked url parameters still produce some warnings for them.
Example of how it works on PHP 5.4.6 and erlier:
http://sandbox.onlinephpfunctions.com/code/7b5b2893eb4ce2ad69f129d683a2a...
This was reported as part of the Drupal 8 security bug bounty program
https://tracker.bugcrowd.com/submissions/ca620796c7ce73e4aaa04283fdda3a4...
Comment | File | Size | Author |
---|---|---|---|
#24 | interdiff-2508735-18-24.txt | 599 bytes | darol100 |
#24 | 2508735-Code-injection-via-preg_replace-24.patch | 2.77 KB | darol100 |
#21 | 2508735-Code-injection-via-preg_replace-21.patch | 2.04 KB | darol100 |
#21 | interdiff-2508735.txt | 613 bytes | darol100 |
#19 | 2508735-19.patch | 1.54 KB | dawehner |
Comments
Comment #1
Chi CreditAttribution: Chi commentedJust realized that we did not yet. It is just a policy.
Comment #2
Chi CreditAttribution: Chi commentedSec Bug #55856 was fixed in PHP 5.4.7.
Sandbox: http://3v4l.org/YvY2J
Comment #3
Chi CreditAttribution: Chi commentedComment #4
dawehnerSo what we should do as part of that issue is to write a test. The bufix will be done automatically as part of #2508231: Raise minimum required version of PHP to 5.5.9 if I understand it correctly?
Comment #5
Chi CreditAttribution: Chi commentedThe code with wrong parameters emits warnings on any PHP version. I would add some validation for the parameters. At least preq_quote for $replacement_pattern variable. But I am not sure whether it suits Drupal GIGO policy.
In my opinion we should prevent any PHP errors that can be caused by wrong user input, only because it can expose some information about server directory structure. It also reduces the risk of getting security issues like this one.
Comment #6
dawehnerWell yeah I totally think we should validate our regular expression here ... well ideally we would not pas it along, given what happens if you can execute a really slow regular
expression. Maybe an idea, could we hash them and also sent a token along, so we know, its always coming from Drupal itself?
So would it be safe enough to just validate on of the following characters:
[a-zA-Z0-9\[\]\(\)\.\+\*\\]
?Comment #7
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedHere's a simple start on a patch.
Seems like the idea is to replace multi-lingual patterns? I don't know - this whole methods smells bad.
Comment #8
dawehner@pwolanin
I think the most important part of this issue is not to fix it but to rather write the tests given that it will be fixed in PHP 5.5 anyway.
Comment #9
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commented@dawhener - yes, agreed, especially since it's not at all obvious what the point of this method is.
Comment #10
chx CreditAttribution: chx commentedWait a minute, if this is fixed in PHP 5.5 and we raising to PHP 5.5 what do we want to test?? It's not our duty to test the PHP engine.
Comment #11
catchIf we get PHP warnings from user input, we should try to prevent those too, but that's just a major bug and not release blocking at all. The test could definitely check for those.
Once we require PHP 5.5, I think I'd probably downgrade this to major, but we should leave it critical until that's actually happened.
Comment #12
dawehnerWell, tests are also an explicit documentation of what is going on or should. Whether under the hood the problem still exists or not, is kinda an implementation detail :)
Comment #13
xjm@catch, @alexpott, @effulgentsia, and I discussed this issue today. This issue becomes major once #2508231: Raise minimum required version of PHP to 5.5.9 is committed, but currently that issue needs to be postponed pending testbot support. Since this is a nasty security vulnerability for current D8 sites, we propose committing the current patch as a hotfix pending the necessary review, without waiting for test coverage. Then we'll downgrade the issue to major for test coverage and any needed improvement.
Comment #14
Fabianx CreditAttribution: Fabianx for Drupal Association commentedI've reviewed the issue and proposed fix carefully again and using preg_quote solves the problem.
HOWEVER:
I can't RTBC it, because of:
modules/image/src/PathProcessor/PathProcessorImageStyles.php: $rest = preg_replace('|^' . $path_prefix . '|', '', $path);
modules/search/search.module: $text = trim(preg_replace('/' . $boundary . '(?:' . implode('|', $keys) . ')' . $boundary . '/iu', '\0', ' ' . $text . ' '));
modules/system/src/MachineNameController.php: $transliterated = preg_replace('@' . $replace_pattern . '@', $replace, $transliterated);
lib/Drupal/Core/Block/BlockBase.php: $transliterated = preg_replace('@' . $replace_pattern . '@', '', $transliterated);
using the exact same pattern. (audited via:
grep preg_replace -r modules/ lib/ | grep --color '\. \$'
)At least BlockBase looks really really suspicious.
I suggest to do a more extensive search - but there are a lot of preg_replace in core.
Comment #15
tim.plunkettIn BlockBase, on the previous line it's just
$replace_pattern = '[^a-z0-9_.]+';
, not sure why it even uses a temporary variable.Though it does have this comment:
Comment #16
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedComment #17
dawehnerWell to be clear, this requires access to "administer site configuration" which is registered ...
lib/Drupal/Core/Block/BlockBase.php: $transliterated = preg_replace('@' . $replace_pattern . '@', '', $transliterated);
Agreed, we control the
replace_pattern
entirely.Note: $keys are preg_quoted(), see
Comment #18
Fabianx CreditAttribution: Fabianx for Drupal Association commentedI think we still should set a good example in Core.
Someone might just grep for code in core or see it accidentally while looking at the API docs and then "learn" from it ...
Comment #19
dawehnerWell fair ...
Comment #20
Fabianx CreditAttribution: Fabianx for Drupal Association commented#19 is missing #7 unfortunately ...
Comment #21
darol100 CreditAttribution: darol100 as a volunteer and commented@Fabianx,
I have combine #7 and #19.
Comment #23
Fabianx CreditAttribution: Fabianx for Drupal Association commented#21 Uhm, no we wanted to change MachineNameController.php, too.
Comment #24
darol100 CreditAttribution: darol100 as a volunteer and commentedoops... I did not notice that it was a different file. Here is an updated version of the patch base on #23 suggestion.
Comment #25
pwolanin CreditAttribution: pwolanin as a volunteer and at Acquia commentedper xjm in #13, let's create a follow-up for test coverage and resolve the bug now.
Patch looks like a reasonable combination of the 2 preg_quote calls and cleanup in BlockBase
Comment #26
dawehnerI think this is far given that its a non issue in 5.5 AND the testbot probably can't test this either because they are running in a higher PHP version.
Comment #27
Fabianx CreditAttribution: Fabianx for Drupal Association commentedRTBC + 1, Looks good to me.
Comment #28
MiroslavBanov CreditAttribution: MiroslavBanov commentedDoesn't the page on php.net say that the
/e
modifier is deprecated, not removed?http://php.net/manual/en/function.preg-replace.php
I don't understand how bumping PHP version solves anything?
Comment #29
Chi CreditAttribution: Chi commented@MiroslavBanov, since the pattern is enclosed by delimiters you cannot inject
/e
modifier without exploiting null byte vulnerability that was fixed in PHP 5.4.7.Comment #30
MiroslavBanov CreditAttribution: MiroslavBanov commented@Chi
Thanks for the clarification.
Comment #31
alexpottCommitted d433aec and pushed to 8.0.x. Thanks!
As per #13, let's open a followup for adding the test coverage.
Comment #33
Fabianx CreditAttribution: Fabianx for Drupal Association commentedOpened #2515736: Add test coverage for "Code injection via preg_replace()".
Comment #34
YesCT CreditAttribution: YesCT commentedremoving tag since the follow up was opened.
Comment #35
willzyx CreditAttribution: willzyx commentedThis change seems to create some trouble with machine name inputs. See #2525870: Regression: machine name inputs no longer work properly after #2508735