Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
install system
Priority:
Major
Category:
Task
Assigned:
Issue tags:
Reporter:
Created:
5 Apr 2013 at 02:47 UTC
Updated:
29 Jul 2014 at 22:08 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
chx commentedThis is what the patch will be once those two are in. It might be easier to review.
Comment #3
chx commentedComment #5
chx commentedI forgot to inherit the password during install form submit and system module install. One line change really, just hard to see because meanwhile webchick committed the override patch (huzzah!)
Comment #6
xjmSee: #630446: Allow SimpleTest to test the non-interactive installer
Comment #7
xjmTalked to @alexpott and I'm closing #630446: Allow SimpleTest to test the non-interactive installer as a duplicate. However, in that issue, @alexpott raised a concern about this hunk (which this patch just removes, but that issue moved to later in the request with a
drupal_valid_test_ua()check):.
Comment #7.0
xjmUpdated issue summary.
Comment #8
alexpottPatch attached adds the 403 for security back in and adds the test from #630446: Allow SimpleTest to test the non-interactive installer and tidies up a couple of things.
@chx this work is awesome...
I think it is a bug we don't test the interactive installer... look at the followup issues listed (thanks @xjm)
Comment #10
David_Rothstein commentedDoes this:
actually provide any more security than this?
In other words, if we believe checking drupal_valid_test_ua() is good enough, can't we just leave the first check out after all?
It seems like drupal_valid_test_ua() might be good enough, but the reason the installer is more sensitive is that if you can access that you can completely take over the server at any time (because once you install you automatically get user 1 privileges). Meanwhile, the other checks of drupal_valid_test_ua() throughout core might really only need to protect against the situation where an attacker stumbles across an in-progress (or never cleaned up) simpletest run and tries to spoof visiting that? (Which is itself only dangerous if that simpletest run also happened to configured the test site insecurely for the purposes of the test, e.g. gave anonymous or authenticated users high level permissions... so overall a lot more far-fetched.)
The security of drupal_valid_test_ua() is also weaker than other tokens in Drupal since by definition it cannot use anything stored in the database to construct it (only the filesystem):
On the other hand, I'm having trouble figuring out a scenario where someone could have access to all the file properties above and not also have access to the database.
I think there was an issue where this was discussed before but I can't seem to find it now.
Comment #11
David_Rothstein commentedAs much as I think this issue is awesome, we should be accurate with the categorization; incomplete test coverage is not a critical bug. If it were, we'd be in trouble :)
And we do test the interactive installer already (doesn't the testbot do it for us every time it tests a patch?)... what's nice about this issue, though, is that it allows us to test as many installation options as we want to, whereas the testbot only runs a single basic one.
By the way, see my comment at #630446-18: Allow SimpleTest to test the non-interactive installer for an idea on how we might be able to combine these two issues together (because testing the interactive and non-interactive installer should ideally not be different from the perspective of the person writing the test even if it's different underneath) but for now I think we should keep them separate since this issue is inherently a lot more difficult than that one.
Comment #12
xjmAt least one of these two issues is a critical task, because we consistently have critical regressions due to the installer being broken. Rather than playing tug-of-status I'll leave it to others to decide how to combine them. :)
Comment #13
alexpottFixing silly mistake in the SimpleTestTest...
I think that the conditions below are not quite equivalent and the explicit 403 preferable. The second condition will pass if
$GLOBALS['databases']is not empty - regardless of the result ofdrupal_valid_test_ua(). The first condition ensures that if the simpletest user agent is set you must also have a valid token.However, the essential question is: Is
drupal_valid_test_ua()code enough?Comment #14
chx commenteddrupal_valid_test_ua is pretty secure, yes. The fileXtime provides some security -- you can have a somewhat good guess and only need to try, say, less than a million variants. Not a lot by today's standards. But, the hash salt is a tricky one to guess. Let's make sure it's there.
Comment #15
David_Rothstein commentedI think you mean "empty" rather than "not empty"? My thought was that if $GLOBALS['databases'] is empty then it doesn't matter because anyone can already use install.php in that case (regardless of Simpletest or not). However, with all the Simpletest-specific settings.php swapping going on now perhaps that is not guaranteed.... and also the explicit 403 check is a lot easier to understand when reading the code, so yeah, I agree, let's just keep both.
It's not just about guessing it; if you manage to get read access to a site's code repository, then you can find the hash salt directly in settings.php. Whereas for other Drupal tokens you would need access to the code repository and also would need to get your hands on a database backup (with the private key) in order to reconstruct the token.
I think @pwolanin would be a good reviewer here; as far as I remember he was responsible for adding the Simpletest check to the installer originally.
Comment #16
chx commentedOK then let's do this: aside from a valid token you need to be able to write the filesystem along with creating a new dir which we somewhat presumed not even "leaky" upload scripts do. One hunk of interdiff is just keeping up with the now-RTBC installer error report patch. This patch will be ready the moment that gets in.
Comment #17
chx commentedKeeping up with HEAD. This should be ready.
Comment #19
chx commented*blush*
Comment #20
chx commentedalexpott drawn my attention to drupal_get_has_salt() -- surely the commit of that broke my patch cos I didnt change a thing between #16 and #17 in bootstrap.inc. So let's use it.
Comment #21
xjmTagging for security review.
Comment #22
chx commentedActually? drupal_get_hash_salt() never returns empty so we can remove all the bootstrap.inc changes! I asked pwolanin to review this per David Rothstein's request, hopefully he can RTBC it.
Comment #22.0
chx commentedUpdated issue summary.
Comment #23
pwolanin commentedI'm unsure about the logic here:
Looks like you don't need the if() again, but it could be part of the else{} above?
Comment #24
chx commentedI am glad if that's all the problems you can find with this patch :)
Comment #25
pwolanin commentedSo, I'm wondering if we can lock this down further so basically this test will fail unless there is specific setup in advance? Maybe an extra flag or key in settings.php that's not populated in a default install?
We are removing a blanket prohibition on the interactive install and opening a significant potential attack surface.
Comment #26
chx commented> Maybe an extra flag or key in settings.php that's not populated in a default install?
Yes, that's done.
Comment #27
pwolanin commentedHmm, ok - that was apparent from the patch - would be good to explain why that setting is protective.
Comment #28
chx commentedComment #29
alexpottFixing a immensely minor nit :)
But I want this patch in - so removing a possible objection :)
Comment #30
xjmI hope we're being really defensive against a bug with our later code installing over the main
settings.php. :) Is there we could be more explicit here or later about what we do when it is a test request?This comment is really confusing now and should be updated and clarified.
It took me like 5 minutes of staring at this before I figured out what it was on about. This is basically about the
$databaseassignment above, to ensure that the same values are used for both paths? I guess? Can we clarify, and add a comment above$databaseas well if that's important?A comment explaining what we're doing and why would be more valuable than defending this hunk being where it doesn't seem to belong. Maybe it should be factored out into a separate function? In any case, what are we sorting out of the database submission here and why? Seems like code smell.
Er. How temporary is this temporary fix? Are we going to fix it here or in a followup? Could you explain a little more?
My guess is: Normally, an empty path is considered to be the front page. During installation, no path is set because we're running install.php, not index.php. But why does this matter to simpletest, and why is it different from the upgrade path tests? I checked in UpgradePathTestBase and there is nothing like this.
Needs a docblock. Why do we need to override this?
Uh... isn't this the else hunk, where we're not in a test? The comment doesn't make any sense to me here.
Minor things I'll clean up:
The first sentence no verb. :)
So, there's a similar, clearer comment on
UpgradePathTestBase, which I'll use here. But my question is, why the heck are they calling t()? We already don't translate assertion messages. I'll file a separate issue for this."Original" is misspelled. Also, a comma is missing.
These need docblocks.
Nitpicks: "SimpleTest" should be either CamelCase or lowercase, and "Back up" should be two words when used as a verb.
test-specific, overriding the.
Comment #31
xjmBack to our regularly scheduled wizard.
Comment #32
chx commentedComment #33
David_Rothstein commentedI think this makes sense. Although is it possible one of these directories (and the associated settings.php file) is left on the filesystem due to an aborted test run, and the attacker could find and reuse that? Maybe there's no way they could reinstall in that case though - I'm not sure - in which case it would be no different from the situation we have now.
It took me a while to figure why it was OK for the new code to let through a request with an invalid drupal_valid_test_ua(). It's probably OK, but in the spirit of making the code easier to understand (and also reducing the attack surface) I think it would be better if the installer rejected invalid ones outright as soon as possible. So basically, keeping both code blocks above around (rather than deleting the first), but adding
!drupal_valid_test_ua()to the if() statement in the first (similar to earlier patches). Yes, I do realize this is pretty much a 180 degree turnaround from my earlier opinion in this issue...Comment #34
David_Rothstein commentedOr combining the two code blocks, I guess, since you probably have to move the first one later in order to add drupal_valid_test_ua() to it. So something like this:
Comment #35
chx commentedThere is no point in filtering for simpletest* as the db prefix is only used when the hash is valid, that's why I deleted the old code: it made no sense.
Comment #36
David_Rothstein commentedRight, that's why I eventually concluded it was OK to remove, but in the name of defense in depth (and easier to understand code) I think it still makes a lot of sense to keep.
Basically, if someone is trying to access install.php with a forged simpletest user agent header, we know they're up to serious no good... so why not reject the request as early as we possibly can?
Comment #37
chx commentedA forged simpletest agent will behave the same as visiting install.php and terminate with install already done exception. There's no point in adding code to stop it early; it stops early enough. It makes it easier to test for install already done exceptions, in fact, if we don't.
Comment #38
benjifisher#32: 1961938_32.patch queued for re-testing.
Comment #40
attheshow commentedRerolled patch against latest dev.
Comment #41
attheshow commentedChanging status to needs review.
Comment #42
alieffring commentedI just spent a day wrestling with getting D8 running, and finally got it working after resolving two issues:
1 - Parts of it were exceeding the 30 second execution time. I don't know if there's much that can be done about this. Is calling set_time_limit() is kosher?
2 - Guzzle was failing because the curl extension wasn't enabled. Should the script check to see if this and other extensions are enabled?
Comment #43
chx commented1. this test is not particularly different to any other, that should not be necessary
2. All tests would fail if cURL is disabled. I thought simpletest had curl as a hook requirement. That's a separate issue if it doesn't.
Comment #44
andrew.lieffring commentedI realized after posting that this issue was about writhing automated tests for the installer, not manual testing the installer for usability. I will try to find a better issue for my concerns. Sorry.
Comment #45
chx commentedRerolled. As these things go, the diffdiff is fairly readable.
Comment #46
attheshow commentedI was learning how to re-roll a patch this morning at DrupalCon Portland. Just out of curiosity, what was wrong with my patch in #40. Any ideas?
Comment #47
chx commentedThanks for rerolling the patch! The problem is that
'value' => drupal_hash_base64(drupal_random_bytes(55)),is now obsolete andCrypt::randomStringHashed(55)is used now instead. This caused the patch to not apply in the first place but during the manual re-apply you copy-pasted from the old one without checking what / why failed and moved. This is an unusally tricky issue as far as rerolls go, it's much more typical to have an irrelevant bit of context information to change.Sorry for confusing you with only adding a diff between #45 and #32. Here's an interdiff for #40-#45.
Comment #49
chx commentedComment #50
tim.plunkettThis is the only part I'm very unsure of. Why is this no longer needed? Obviously an in-code comment isn't necessary, but if you could say why in the issue I'd appreciate it.
empty is misspelled.
is "costs" the right word?
Otherwise this is actually very sensible and readable when you really look at it. There are some great changes in here. Thanks for keeping this going chx.
EDIT: My question was answered above, see #36
Comment #51
dawehnerSo why do we remove the backtrace, doesn't it have valid information in there? I guess this is the same problem as https://drupal.org/node/1158322#comment-7189458
Some comment would be nice.
drupalGet has parameters for query so let's use it.
Comment #52
chx commentedSee #37, other two addressed.
Comment #53
chx commentedI have no clue what is happening there but strtr bails on the backtrace; it's not used; so let's nuke it. There might be a PHP bug hiding there; it might be the serialization issue; I do not know but since it's not used, it's no problem.
Actually, that core/install.php rather needs base_url, much like getUpdatePhp() in lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
Comment #54
dawehnerIt is important that we can test our installer.
Comment #55
yesct commentedI looked at this for core gates doc stuff, and didn't see anything blocking.
These are great comments in this patch.
I noticed these tiny things, so just did them.
1.
https://drupal.org/node/1354#todo
not blocking, since this line is changing, might as well use the standard @todo.
2.
https://drupal.org/node/325974
public function setUp() {
3.
https://drupal.org/node/1354#classes
"If you use a namespace in documentation, always make sure it is a fully-qualified namespace (beginning with a backslash)."
Comment #56
yesct commentedhttps://drupal.org/node/325974
"There is no PHPDoc on this function since it is an inherited method."
---
Maybe we want to update the testing standards doc to use [@inheritdoc}? But I think we dont start doing it here. #2007766: {@inheritdoc} in tests on setUp and getInfo
I left the setUp protected, if it really should be, then an issue needs to be opened to update the standard.
(see also similar conversation in the past: #1757566-49: Convert user account e-mail templates to configuration system. maybe can be fixed as part of #1869794: Update tests coding standards doc and make consistant with 1354 where appropriate).
----
note interdiff is to #54 @dawehner's, so can skip mine in #55.
----
Anyway since we are only finding these small things here, looks good to me.
Comment #57
yesct commentedshould be rtbc when the bot comes back.
Comment #58
catchTook a look through this and I think it's reasonable. Committed/pushed to 8.x.
Comment #59.0
(not verified) commentedUpdated issue summary.