As discussed on the mailinglists and on my blog. When running multiple sites on one server, maintained or adminstered by various people, then one really wants to disable all use of php input. Not only by permissions, but really.
Because sticking stuff in permissions means that you cannot hand out "administer users" "administer permissions" etc. in practice, the same as disallowing about 30% of all administration functions. That is bad.
Hence I stripped all the php stuff from filter.module and stuck it in a phh input module. If you remove that module, you can finally go to sleep again, without worrying about one client 0wnz0r1ng your server the next morning. Or for that matter, one funny client stealing all stuff from the other client (by including his settings.php).
Allowing PHP trough the web is bad. Always. IMO. I want to be able to run drupal without any php input at all. This patch is the first step towards that.
Note that i do not want to *remove* the option, for it is usefull (unsafe, but usefull) for a lot of people.
Just that I want to be able to sleep again :)
Bèr
PS: setting this to critical is intentional; Setting it to code needs work too. For IMO this is a critical post 4.7 task. One that should be dealt with immediately after the release. (for backportability, most of all)
| Comment | File | Size | Author |
|---|---|---|---|
| #52 | php_0.patch | 15.25 KB | Zen |
| #50 | php-update_1.patch | 3.7 KB | Zen |
| #46 | php-update_0.patch | 3.72 KB | Zen |
| #41 | php-install.patch | 1.58 KB | Zen |
| #36 | php-update.patch | 3.72 KB | Zen |
Comments
Comment #1
killes@www.drop.org commentedIf you cant sleep due to PHP filters you should get out of the hosting business. ;->
SCNR
Comment #2
chx commentedSee http://drupal.org/node/46857 also.
Comment #3
killes@www.drop.org commentedI prefer this solution over the one proposed by chx.
Comment #4
adrian commented+1 on this approach.
For hosting providers, this is fairly important.
the php filter is like handing people a loaded gun.
Comment #5
chx commentedI thought this as the second step after my patch. But even if only this one gets in, I am fine.
And this is not post 4.7 but pre 4.7. Releasing another version with PHP filter... dangerous.
Comment #6
morbus iffI prefer this approach over chx's too. Some notes:
* I'd rather it be called filter_php.module, to sort properly and to be more indicative of it's function.
* I'd all for it being post 4.7, and not pre 4.7. This is, IMO, not as big a problem as chx makes it out to be.
* "run PHP (be carefull)" is, IMO, too .. .. . .. "condescending". I'd much rather a neutral "allow input to be PHP".
I'll see about working on a revision sometime next week.
Comment #7
Bèr Kessels commentedoff topic, but still rather important: mty plans for the blocks visibility.
For now we got the permission in. But this means that anyone who can change permissions, can get to PHP level, can get anywhere. In otgher words, taht particular part needs a lot of love too. But that IMO is a very unrelated patch. Here are my plans:
* Get a block_visibility hook in: any modulecan decide on the visibility of a block.
* block.module will be using that o present some basic visibility settings (I was thinking in the line of what we have in 4.6°
* php_block_vis.module (or even the phpinput.module in this patch) would use that hook to present php options for adding/removing blocks acc. to PHP input.
But, I need to stress, that that is a next step, IMO. This patch is important enough to not let it wait for that plan.
Bèr
Comment #8
rbrooks00 commentedI think this needs to be done as an option and not an absolute (i.e. we are removing this from core and making it a contributed module). This has the potential to cause problems for a lot of sites that might be using this if they all of a sudden upgrade and can't author PHP anymore. PHP is frequently used for small dynamic blocks and pages, see: http://drupal.org/node/39282
If we are talking about a hosted situation wouldn't someone be able to download this module and install it anyway? If they don't have FTP access then it could be something in the settings.php file.
This approach seems to drastic to correct a problem that doesn't exist for many people. It would be good as an optional feature though.
Comment #9
chx commentedBer's patch contains the php_filter.module , we could keep it in core.
Comment #10
drewish commented+1, I think this is an excellent idea.
Comment #11
Richard Archer commented+1 for this concept.
Comment #12
fax8 commented+1 for me. php code evaualtion should be on an separate module.
this patch also adds the permissions "run PHP (be carefull)" which is more
straightforward than going to administer » input formats » PHP code » edit .
A little problem:
should be:
Comment #13
morbus ifffax8: please recheck your comment. I am unable to detect the difference between those two snippets.
Comment #14
Stefan Nagtegaal commentedMorbus, I think it's in the indentation... :-)
Comment #15
moshe weitzman commentedlooks good to me. we need to update existing input formats, right? also need to enable this module for sites currently using the filter. the update path needs work.
Comment #16
kbahey commented+1 for this.
Keep it in core, as a separate module, disabled by default.
Let people enable it if they so want. Staying in core means that it will be constantly scrutinized and not neglected/overlooked.
Comment #17
drewish commentedMorbus Iff, the if block doesn't have a closing }.
Comment #18
morbus iffAh! Thankee.
Comment #19
Bèr Kessels commentedthis patch has the closing } added.
Comment #20
Steven commentedAlso, by requiring the user to set up the php_input module, there is a risk that they will plunk it into the default Filtered HTML format. How do we avoid this?
Comment #21
chx commentedComment #22
Bèr Kessels commentedabout the persmission
We can remove the permission. Or use it in the filter.
The latter has the problem that it feels odd because the filter system has its own private and rather confusing permission system. (not going into that now :p).
The first has the problem that it will be re-introduced in a few days wen we move over the PHP for block visibiliy. My idea of that permission was, indeed, to use it sidewide. For all the PHP input, also in contribs.(I already rewrote sections module to use the blocks permission)
So both scenarios have their pro's and con's. I would say we
* either choose NO 'can use php input' permission at all.
* or use it in *all* places. Meaning in the filter settings too.
Comment #23
moshe weitzman commentedok folks. anyone willing to refresh this patch and write the update?
Comment #24
gerhard killesreiter commentedI've wrtiten paranoia.module which disables the creation of new php filters. You still need to delete the existing one manually (although I could move that into the install script).
Is this a useful solution to this thread?
Comment #25
Bèr Kessels commentedI am testing the project by Gerhard. And so far, it seems a good alternative for this patch.
I would love a "visionary" comment by Dries, about what route he likes: Solve such "security" issues in contribs, or build them into core.
If the latter, we cannot close this thread. If the first, I would love to close it.
Comment #26
drummLets consider this for the next version.
Comment #27
Zen commentedReviving:
Rerolled Bèr's patch + changed php_input to php_filter + incorporated Unconed's points.
Update patch + language fixes to be addressed once primary changes are given the green light.
Please feel free to update patch rather than wait for me to do so :)
Thanks,
-K
Comment #28
Zen commentedMissed a chunk.
Comment #29
chx commentedRe. Steven's question, how we avoid putting PHP filter into Filtered HTML -- what about a mechanism that would make it possible for a filter to define that it is a standalone filter and it can not be mated with anything? Or if it is decided that it is only PHP filter that needs this mechanism, then simply make filter module recogn it and refuse to put it into any format which is not empty and refuse to add anything to a format which contains the PHP filter.
Comment #30
Bèr Kessels commentedre: filters. I'd say that *on top of the filters* the global permission 'insert php' should be in place. So, regardless who you assign php input filters to, they won't work if that person has no got 'insert php' access'.
Off course we would need to communicate this in the interface too. e.g. by graying out the 'php input filter' for roles without the access to 'insert php'.
Comment #31
Zen commentedI personally think that a dire warning will suffice. Let's not over-engineer here.
Thanks,
-K
Comment #32
Stefan Nagtegaal commentedFirst of all, i did not test the patch (yet)..
But wouldn't it be better, to not display the option at all if the sufficient permissions aren't there for the user?
Once again, I did not tested the patch yet...
Comment #33
Bèr Kessels commented@zen, this is not about over-engineering, this is security. We should 'engineer' this is such a way, that an admin can go to sleep once (s)he has the PHP input permissions set, or unset. Knowing that these permissions will make sure that those *without* the permissions can never insert or inject PHP.
Example: here, at Drupal.org I suddenly had rights to insert PHP at one moment, due to a misconfiguration after an upgrade. Now, that is not a huge issue, since I had quite high admin rights anyway. But it shows that an admin still needs to take great care. Such a critical issue as allowing PHP input, should work VERY transparent. If I do not give someone PHP rights, that person should not be able to insert PHP. Nothing more nothing less. We cannot expect everyone to be aware that in some far corner of the Drupal site, another setting can/will grant that same person PHP rights again.
Comment #34
dries commentedLooks good, but please rename the module to php.module. Thanks.
Comment #35
Zen commentedBlanket rename of php_filter to just php as per Dries' request. No other changes. Setting to RTBC.
I'm working on the updater patch as we speak.
-K
Comment #36
Zen commentedUpdater patch attached. While #35 is RTBC, this patch is _not_. Please review and test.
Thanks,
-K
Comment #37
nedjoThis change is indeed needed.
At the same time, we should be developing a broader solution to the problem of conditionally limiting PHP input. I've posted a complimentary patch to add a variable we can set in settings.php, 'php_input', which would be the means of preventing all user-input PHP code on a site, http://drupal.org/node/134779.
Comment #38
Steven commentedI'm not convinced this is the best approach... if you are afraid of PHP input, you may want to lock down other things on a Drupal site too. A paranoia.module seems a much better solution than removing useful features from Drupal core. Unless someone can bring up some solid arguments why that approach is not viable, I'd prefer not committing this patch.
Pasteable PHP snippets are a very useful way of customizing your site for example. With this change, we now require novice users to 1) Enable an additional module 2) Add a new input format, with the right permissions 3) Add the filter to the newly created format. If we do go down this road, at the very least, there should be a module_enable hook to create the format with the filter in it, otherwise we will have clueless people dropping the php filter into the Filtered HTML format.
As for a global php_input variable... this is very un-Drupal-like. It doesn't appear like the variable would cleanly disable PHP from the UI everywhere, but merely lock it down for use. That could lead to a frustrating experience for users for that installation.
Comment #39
chx commentedI love having PHP around to do quick stuff on my site (running queries from node/add/page -- lovely!) . As for security well, it can be dangerous, but to the hell with it, we have now much better defaults and the choice checker than we had a year and a half ago. I would like to hear what Heine thinks over this one.
Comment #40
Bèr Kessels commentedMany people, systems and distributions consider "able to run aribtrary code" as a critical security hole. When you install Drupal, you have such a possibility. It is arguable wether this is a valid and handy feature (Drupal community leans towards that) or a critical security hole. Fact remains, that for many people it /is/ a security issue at the very least.
Drupal (community) can do two things: ignore these people and defend the argument of this being a feature, not a security hole. And tell them to "use some hack around the hole", by attempting
Or we can offer a way to remove the feature.
IMO the latter is by far the a) cleanest, b) securest, c) simplest.
Note that this does not mean removeing it from core, as Steven makes you think. We must simply *offer people the ability* to remove it from core. This is not the same!
By sticking all the PHP input in one module, the only thing one needs to do, is remove that module.
That way, it is CERTAIN that no-one can run PHP. Since the feature is not there at all. This is very different from havin the feature around, yet denying access to it. The latter can be seen as a security hole that is still in your application, without having a *known* way to abuse it.
So: again: We are not argueïng to remove this from core. We are simply trying to isolate all the PHP input in one module, and with that, offer users a way to choose for themselves if they take the risk of having this feature around. Freedom to Choose ++.
Comment #41
Zen commented.install file patch attached to add a PHP code input format.
There are 3 patches now:
#35 - reviewed.
#36 - To be reviewed & tested.
#41 - To be reviewed & tested.
Comment #42
dries commented1. I think it makes sense to move this to an additional module that can be removed from disk.
2. At the same time, I agree with Steven that it is safer/better if _we_ can pre-configure this, then when the user has to configure it him selves. It's less prone to errors.
I think we can do (1) and pre-configure the PHP input format so (2) isn't a concern. Heck, we could even enable the PHP input filter by default but still make it easy to disable.
----
Another solution, but not necessarily better, would be to rely on PHP's "disable_functions" setting. You can globally disable function calls by listing them in the disable_functions variable in your php.ini file. I haven't tried it yet, but if a hosting company globally disables eval(), maybe we can wrap the PHP filter code in a function_exist() call? So, when eval() is disabled, we degrade gracefully (assuming that function_exist() would work for disabled functions). Not sure if it would work, but I figured, I'd float the idea.
The disable_functions approach might be better because it is a technique that hosting companies are probably already familiar with -- it fits their workflow. However, it might be problematic because other parts of Drupal might rely on eval(). The locale module, for example, uses something like '@eval("return intval($locale_formula);");' ...
Comment #43
Steven commentedI'm just wondering if paranoia.module isn't better because there are other things to consider. A somewhat insecure contrib module could allow a privileged admin to upload .php files for example. And generally, you may want to lock down some other settings in the administration, like allowed file extensions. Remember that .pdf XSS vulnerability which is still out there?
It just seems to me that turning the php filter off is just one of many things that need to be done, and that there is very little reason to make core less useful out of the box. The PHP code filter is way more than just a development tool. It helps people build sites and gives those who would otherwise shy away from PHP an easy way of customizing simple snippets.
As long as it as simple as turning on the relevant module, I'd be okay with it though.
Comment #44
nedjoThis would be easier to evaluate as a single patch rather than three. The first one at any rate needs more work (see below).
I think that's the idea. In fact, most people won't have to turn it on--that will be done in the relevant install profile.
Besides the PHP filter, the other part of core we need a solution for is the PHP block configuration. That's what's in my patch at http://drupal.org/node/134779 (and, yes, it deals with the UI as well as the data handling). Should I rewrite that to be part of this patch?
I'm thinking we should move
drupal_eval()into php.module, perhaps renaming it tophp_eval(). That way we know it can't be called unless the module is present.When this patch is applied, contrib modules wanting to conditionally add user PHP input could test for the php module:
(replacing the need for the configuration setting I'd previously suggested).
Comment #45
dries commentedSteven -- what else would a paranoia module do, and how? Could you try and provide an itemized list of some ideas?
I see two problems with a paranoia module:
1. The user can disable/enable it. We want to ISP owner to have control here, not the user. So when the ISP owner, removes php.module, he/she knows that the site owner can't re-enable it.
2. ISP have their own workflow and audit processes. When you look at this through the eyes of a very conservative ISP, there is only one solution ... and that's to disable certain functions at the PHP-level. It's a simple switch that is guaranteed to work, and that doesn't put additional burden on their shoulders. They don't want to audit our code, or inspect whether the paranoia module really works. All they want to know is whether Drupal degrades gracefully when eval() is disabled. If I were an ISP, I would not want to rely on or trust paranoia.module, I just want to use disable_function. Is that a viewpoint you can relate to?
However, if you look at this from a user's point of view, a paranoia module might be the better choice.
Comment #46
Zen commentedUpdate number changed from 2007 to 2008.
#35 - reviewed.
#46 - To be reviewed & tested.
#41 - To be reviewed & tested.
I think everybody is in general agreement that the filter should live in a separate module #35: User Node Favorites/Bookmarks. There is no other way to disable it from everybody including UID #1. It is still going to remain in core.
New installations will (based on the installation profile) have it disabled by default; it is safe to assume that by the time an admin decides that he needs a PHP filter, he will have understood how to enable modules. Enabling the module #41: User option to make email address visible. installs the format and sets everything up.
Upgraded installations will see no difference [#46] other than having the ability to turn it off via the modules page. A warning has been provided for this case.
ISPs aside, without the PHP filter disabled, one cannot have a safe multi-site installation without custom frippery. Multi-site A's admin will be able to access the settings.php etc. of multi-site B using the PHP filter. The point of a multi-site is lost unless all the sites have the same admin or something similarly restrictive.
-K
Comment #47
killes@www.drop.org commentedDries: http://drupal.org/project/paranoia
You can't disable the module if you can't access the database.
Comment #48
dries commentedZen -- looks good to me. When I enable the PHP filter module, will it properly configure itself or is that left for the user?
Comment #49
Zen commentedUpdated the update patch to sync with HEAD.
@Dries: The .install and the system update both create a PHP code input format and add the PHP evaluator filter to it.
#35 - reviewed.
#49 - To be reviewed & tested.
#41 - To be reviewed & tested.
Thanks,
-K
Comment #50
Zen commentedAnd the patch :/
#35 - reviewed.
#41 - To be reviewed & tested.
#50 - To be reviewed & tested.
-K
Comment #51
dries commentedZen, could you roll everything into one big patch. I'd like to test and commit this. :)
Comment #52
Zen commentedAll in one patch.
Thanks,
-K
Comment #53
dries commentedI've tested this, and committed it to CVS HEAD. We can refine this as necessary but it marks an important first step. Thanks Zen and Ber.
Comment #54
(not verified) commentedComment #55
nedjohttp://drupal.org/node/124158 follows up on this patch by moving PHP page matching and
drupal_eval()to php.module.Comment #56
gábor hojtsyUnfortunately the upgrade path of this patch is less than satisfactory. See http://drupal.org/node/194304