This is either a bug or a documentation issue, but it's important we figure it out.

In Drupal 7, the "rule" is that you need to have the PHP module turned on in order to be able to execute arbitrary PHP code. This was especially intended as a result of http://drupal.org/node/224333#php_permissions and related issues. The idea is that if you want to lock down your Drupal installation from arbitrary code execution, you can remove the PHP module from the filesystem, or block it from ever being enabled via custom code. That way, even if someone stumbles across a computer with an administrator logged in, there is a limit to the damage they can do.

However, the Update Manager functionality breaks this assumption. In "normal" operation of the Update Manager, this is certainly by design (as the entire purpose is to let you upload arbitrary code to your server) - however, in normal operation it also asks you for your FTP or SSH credentials right before letting you upload, so that's fine because if someone knows those they can already upload things to your server outside of Drupal.

But for certain server setups (in particular, situations where the webserver user owns the Drupal files - i.e. setups that are popular in shared hosting) the Update Manager does not ever ask you for a server password (this results from #609728: Skip authorize.php step if webroot files are owned by the httpd user). It just lets anyone logged-in with the 'administer software updates' permission upload modules to the site.

We need to decide if it's acceptable to allow that with the PHP module turned off. If it is, we need to document somehow that disabling access to the update manager (which can be done through settings.php) is sometimes necessary as part of any procedure to disallow direct arbitrary code execution (without knowledge of SSH/FTP passwords) on a Drupal site. Right now, I don't believe there is any indication of that.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

David_Rothstein’s picture

Issue tags: +Security improvements

Adding a tag.

EvanDonovan’s picture

Is the "administer software updates" permission listed as one of the permissions that affect security?

David_Rothstein’s picture

Yes, it is (at least in the admin UI - I guess http://drupal.org/security-advisory-policy hasn't been updated for Drupal 7 yet).

Without that, this would definitely be a more serious bug :)

dww’s picture

Issue tags: +Needs usability review

We're really afraid of people who leave themselves logged in as super admins and walk away from their machines at a coffee shop or something? Really? ;)

Anyway, if the workflow introduced by #609728: Skip authorize.php step if webroot files are owned by the httpd user is too permissive, we should be able to use authorize.php to ask the admin user to log in as themselves again. That'd satisfy the security concern here, right? Super rough sketch of how this would work:

(Note, this might depend on the API changes from #609772: Impossible to extend the FileTransfer class system in contrib before it actually works).

Instead of update.manager.inc directly creating a FileTransferLocal object in this case, it does special mojo to redirect to authorize.php in such a way that it's not prompting for FTP/SSH credentials, but basically a login form.

- It'd have to not call system_authorized_init(), but instead manually setup $_SESSION['authorize_filetransfer_backends'] and $_SESSION['authorize_operation'] itself.
- It'd setup authorize_filetransfer_backends to use a custom "settings form" and factory callback.
- The factory callback would basically validate the password field, and if it worked, it'd instantiate the right FileTransferLocal object to actually do the operation.
- The update/install would proceed as normal via authorize.php at this point

In fact, this last point is probably an important fix to #609772 in the update case. We actually *want* to run updates from authorize.php so we've got the low bootstrap level and have a slightly cleaner environment to operate in. It doesn't matter when installing new code, but when updating existing code, we don't want all modules bootstrapped. It's certainly evil and dumb to rely on FTP and ask for those credentials (which we don't need) if all the files are owned by the same user. But, we could verify that the user running the operation is a human that knows the password to an account with "administer software updates". Might be a bit of a UX pain in the ass. :( Especially since we never fixed #720452: Allow ability to install multiple modules at once :( Maybe there could be another settings.php killswitch for this behavior? OTOH, if they're using FTP, we ask them for their password each time, so at least it'd be consistent. In a way, that'd actually make it easier to document all this stuff, since the workflow would always be the same.

Anyway, if we actually want this approach, the first step is getting #609772 in, since the whole API for managing this stuff is completely broken in HEAD right now. I have a patch with verified working tests and squeeky-clean API docs over there, it just needs a review other than me before it's RTBC. Once that's done, we can proceed with the plan I outline here.

Meanwhile, it'd be nice to get some UX reviews of this proposed workflow...

Bojhan’s picture

This sounds like a won't fix at this point, I am not sure I fully understand but if it requires logging in again we surely are doing something wrong - asking FTP information should be enough. If the webserver allows things to pass without FTP information, are we to blame or the server configuration?

dww’s picture

@Bojhan: This would be *instead* of entering your FTP credentials, but at the exact same spot in the workflow. The concern raised here is that due to #609728: Skip authorize.php step if webroot files are owned by the httpd user, on common shared hosting server configurations (where all the files are owned by the user that httpd is running as), if a novice admin leaves themselves logged into the site all the time, and they ever leave their browser unattended, any random person could use the update manager to install malicious PHP code on the site. One assumption we had previously made is that if you completely removed the PHP module, there's no way in Drupal core to execute arbitrary PHP from the web UI. Update manager currently breaks this assumption in many cases.

So, this issue is proposing that in the special case of #609728, when the update manager currently skips authorize.php entirely and *directly* installs/updates new code, we'd still land on authorize.php. The user would technically still be logged in, they'd just be asked to provide their site admin login credentials again (extremely common when installing software updates or new code in other contexts (e.g. Apple's "Software Update").

This way, you'd have to be so foolish as to leave your machine unlocked at a coffee shop *and* tape your Drupal admin password to your laptop for any random user to install malicious PHP code on your site, even without PHP module.

But I'm still torn. My security team hat says "fix this".

My "updates should never happen during a full bootstrap" hat says to fix it. However, most of the theory behind the low bootstrap authorize.php doesn't translate into much practice. The final authorize.php landing page doesn't actually let you recover from failure, restore your site, anything. It's just a last dying breath, potentially full of red errors, telling you "bummer, I just hosed your site, sorry", and the site is already WSOD.

My "updating my site should be easy" hat (the whole premise of the Update manager) says "just document this risk and leave all the code alone."

David_Rothstein’s picture

I do like the idea of asking for their account password (although implementing it sounds a bit daunting). The UX concerns don't seem like an issue given that it's the exact same thing we make them do for the FTP case.

One relatively simple improvement we might be able to make is that we could cache "this user entered their Drupal password on authorize.php at time X" in the session and only make them type it a second time if it's been more than a few minutes (that's also what operating systems tend to do). That would solve the case of someone installing multiple modules in a row and being annoyed by having to type their Drupal password over and over again.

I don't think that documenting this would be the end of the world either (given that we already have the PHP module in core and this certainly is no bigger of a security risk than that is). However, it would be nice to be able to say that the new Update Manager in D7 is truly secure, in a way that the PHP module isn't.

cweagans’s picture

Another approach is to make it so that you could update existing modules without giving the site your FTP or SFTP information, but not install new ones. To clarify:

Situation 1)
All of my drupal files are owned by the same user and group as my web server. I can go update any module without FTP of SFTP information. In order to install a new module, I'd need to supply credentials.

Situation 2)
All of my drupal files have the ownership set in an intelligent manner. I must supply FTP or SFTP information in order to update existing modules, or install new ones.

David_Rothstein’s picture

Status: Active » Needs review
FileSize
1.83 KB

How about we start by updating some of the documentation (the description of this functionality in the settings.php file itself is currently wrong), and then leave this issue open for further changes afterwards?

Something like the attached, perhaps?

dww’s picture

Yes, that's certainly a good start. The only thing I'd consider adding is a link to http://drupal.org/server-permissions (although that page seems to have been reorganized into a more catch-all place, so that might not be helping much).

Stevel’s picture

-1 for asking the account password to the user here.

Users using an external authentication mechanism (openid, single sign on, ssl authentication etc.) don't have a valid password known to drupal, so it's impossible to check for it.

The comment looks like the best we can do without building a complete authentication abstraction layer.

deviantintegral’s picture

Patch in #9 still applies.

Is http://drupal.org/node/244924 the link it should include and what /server-permissions used to be?

sun’s picture

Version: 7.x-dev » 8.x-dev
Category: bug » task
Issue tags: +Needs backport to D7

As long as we're talking about a documentation-only change, this is a task.

xjm’s picture

Tagging issues not yet using summary template.

xjm’s picture

Status: Needs review » Needs work
Issue tags: +Novice

Well, let's get the documentation fix in, at least. (And I think the page in #10 isn't really useful and probably needs a different alias now at that.)

Tagging novice to reroll #9 against the current D8 codebase.

marji’s picture

Status: Needs work » Needs review
FileSize
1.69 KB

Hey guys, I rerolled #9 against the current D8 codebase.
Patch attached.

marji’s picture

Issue tags: +DDU2012

Adding DDU2012 I tag I omitted in #16 :)

cweagans’s picture

DDU2012? What's that?

xjm’s picture

Status: Needs review » Reviewed & tested by the community

Drupal Down Under. :) They're having a code sprint today.

I think #16 is RTBC, since the handbook documentation is not-so-useful. We can set it back to active for other changes after.

David_Rothstein’s picture

Status: Reviewed & tested by the community » Needs review

Per #12, should we link to http://drupal.org/node/244924 instead?

Also:

+ * will not be prompted for SSH or FTP credentials (note that these server
+ * setups are common on shared hosting, but are inherently insecure).

Although "inherently insecure" is a little strong (the issue is more that it expands the attack surface in the case of other vulnerabilities, rather than being a vulnerability in and of itself), I guess we should keep it, since it's consistent with other code comments elsewhere in Drupal.

Actually, we probably should link to http://drupal.org/node/244924 and word this in a way that explicitly discourages people from changing the file permissions/ownership just to make the Update Manager "work better".... Reading through the comments at http://drupal.org/documentation/install/modules-themes/modules-7, for example, it seems like people have discovered this little trick without understanding the consequences. We probably should be explicitly discouraging it in this code comment.

Bojhan’s picture

Issue tags: -Needs usability review

Why is this still not in? Its stalled on a code comment? Sometimes I feel our major/critical change basically made all majors into normals.

xjm’s picture

Status: Needs review » Needs work

Since the patch in #16 is for a documentation improvement, let's incorporate David's changes into that improvement. This would be a good novice task.

Albert Volkman’s picture

Patch updated with @David_Rothstein's suggestions. Unable to interdiff because previous patch no longer applies.

Albert Volkman’s picture

Status: Needs work » Needs review
jurgenhaas’s picture

The patch from #23 doesn't apply anymore, so I re-rolled and attached it.

Status: Needs review » Needs work

The last submitted patch, update-manager-932110-25.patch, failed testing.

Albert Volkman’s picture

Status: Needs work » Needs review
FileSize
1.79 KB

Re-rolled.

jurgenhaas’s picture

Status: Needs review » Reviewed & tested by the community

This is working fine for me.

Note: The patch for D7 will have to be re-rolled as patch #27 won't apply.

webchick’s picture

Version: 8.x-dev » 7.x-dev
Component: update.module » documentation
Status: Reviewed & tested by the community » Patch (to be ported)

Looks good to me, and seems to incorporate the latest feedback.

Committed and pushed to 8.x. Moving to 7.x for backport. Also changing the documentation component, since this is purely a docs fix now.

dcam’s picture

Status: Patch (to be ported) » Needs review
FileSize
1.79 KB

Backported #27 to D7.

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

Looks like the same fix as was committed to d8, thanks for the backport!

jhodgdon’s picture

Status: Reviewed & tested by the community » Fixed

Committed to 7.x (pure docs).

David_Rothstein’s picture

Title: On some servers, Drupal 7 allows administrators to directly execute arbitrary code even without the PHP module » On some servers, the Update Manager allows administrators to directly execute arbitrary code even without the PHP module
Version: 7.x-dev » 8.x-dev
Component: documentation » update.module
Status: Fixed » Active

I guess we should still keep this open for Drupal 8, though. (Especially in light of people wanting to use #1675260: Implement PHP reading/writing secured against "leaky" script for module upgrades and the like...)

Re #11 and comments before it, I'd love to see a generic "reauthenticate-on-demand" capability in Drupal core, and this would definitely be the first place to use it. I guess that's really the only way to fix the issue at this point.

David_Rothstein’s picture

Issue tags: -Novice

Not exactly "Novice", though...

David_Rothstein’s picture

Version: 8.x-dev » 7.x-dev
Status: Active » Reviewed & tested by the community

This was committed to Drupal 7, but for some reason was reverted later: http://drupalcode.org/project/drupal.git/commitdiff/3b64ddd9630648eb267d...

I assume that was by mistake...

I could fix it myself, but I'll leave it to another core committer to confirm that I'm not going crazy :)

(And don't worry, @webchick, it was your commit but you're certainly not the only one who might have done this. I just left a similar comment on #1722244: drupal_get_destination() is missing a @return, and that one you definitely weren't responsible for :)

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Err. Right. No idea what happened there. :P

RE-committed and pushed to 7.x. :P Forreal this time.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

David_Rothstein’s picture

Version: 7.x-dev » 8.x-dev
Status: Closed (fixed) » Active

Back to Drupal 8 (per #33)...

YesCT’s picture

Yep. Taking a look at this it looks like there are two concurrent next steps here:

  • 'a generic "reauthenticate-on-demand" capability in Drupal core' (per #33)
  • update issue summary (in case it helps someone new, here is the contributor task help doc for that: http://drupal.org/node/1427826)

'a generic "reauthenticate-on-demand"' sounds kind of complicated. Who would be a good person to have the right skills to tackle that? maybe we could ping a couple people to see if they are interested. and/or some more detail about what that would entail might be helpful.

jhedstrom’s picture

Seems like the only thing left here for 8.x is to revert the change as per #35?

YesCT’s picture

Issue tags: +Security

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

  • webchick committed b64b971 on 8.3.x
    Issue #932110 by Albert Volkman, David_Rothstein, marji, jurgenhaas: On...

  • webchick committed b64b971 on 8.3.x
    Issue #932110 by Albert Volkman, David_Rothstein, marji, jurgenhaas: On...

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

  • webchick committed b64b971 on 8.4.x
    Issue #932110 by Albert Volkman, David_Rothstein, marji, jurgenhaas: On...

  • webchick committed b64b971 on 8.4.x
    Issue #932110 by Albert Volkman, David_Rothstein, marji, jurgenhaas: On...

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

  • webchick committed b64b971 on 9.1.x
    Issue #932110 by Albert Volkman, David_Rothstein, marji, jurgenhaas: On...

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev
quietone’s picture

Status: Active » Needs work
Issue tags: +Needs followup

A patch was committed to 8.x (#29) and to 7.x (#32) for this. The 7.x one was accidentally reverted but then restored (#36). This all points to this being completed.

It appears the only left is to create a followup for #33 and then this can be closed. Adding tag for a followup.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.