[RFC] No PHP tags

php.internals

Yasuo Ohgaki

12 years ago
Hi all, "Optional PHP tags by php.ini and CLI options" RFC has been discussed very long time. https://wiki.php.net/rfc/nophptags I would like to know is there anyone who would like not to have this. I think it's good counter measure for LFI, but you might have different perspective. If it is possible, I would like to address as much as opinions possible before voting. Are there anyone who think we should have this? What is the reason? Thank you
-- Yasuo Ohgaki yohgaki@ohgaki.net

Stas Malyshev

12 years ago
Hi!
> "Optional PHP tags by php.ini and CLI options" RFC has been discussed very > long time. > > https://wiki.php.net/rfc/nophptags > > I would like to know is there anyone who would like not to have > this.
Yes. Such change would create a lot of complications on dealing with PHP files, as syntax and parsing would be dependent on ini values, which means one can not predict without knowing the exact environment how specific file is going to be parsed. We already made that mistake with short tags, and I don't think it makes sense to make it again. We do not need to fragment PHP into two incompatible codebases, so that some libraries only run with one set of settings and others run with different set of settings.
> I think it's good counter measure for LFI, but you might have > different perspective.
This is not a serious countermeasure and can not be relied on as a security measure. The correct security is not including local files with unsanitized names and use open_basedir if required.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Rasmus Lerdorf

12 years ago
On 02/09/2014 11:35 PM, Yasuo Ohgaki wrote:
> Hi all, > > "Optional PHP tags by php.ini and CLI options" RFC has been discussed very > long time. > > https://wiki.php.net/rfc/nophptags > > I would like to know is there anyone who would like not to have > this. I think it's good counter measure for LFI, but you might have > different perspective. > > If it is possible, I would like to address as much as opinions possible > before voting. > > Are there anyone who think we should have this? > What is the reason?
I think this would actually weaken security. Having two very different parsing modes means that if you mix the modes and include a file in one mode meant to be included in the other would leak the source code to the world which is arguably a worse security issue than the sloppy coding issue you are trying to prevent here. -Rasmus

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Mon, Feb 10, 2014 at 5:14 PM, Rasmus Lerdorf <rasmus@lerdorf.com> wrote:
> I think this would actually weaken security. Having two very different > parsing modes means that if you mix the modes and include a file in one > mode meant to be included in the other would leak the source code to the > world which is arguably a worse security issue than the sloppy coding > issue you are trying to prevent here. >
I agree that having 2 parsing modes is problematic. Users may avoid this by having "<?php" at the top always. I'll write "<?php" always and it should be recommended for maximum security. Even though there is downside, it has advantage to consider. There are scripts out there that suffer LFI due to embed by default. If other languages have the same issue, I don't care much. PHP is the only one which is affected a lot. Other languages have the same issue, but it's under very limited context. The main objective of this RFC is to make PHP as secure as other languages with respect to LFI. It's one of the reason why some companies do not adopt PHP as their platform and I would like to change it. Perhaps, we may force to write "<?php" even when script only mode? Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Andrew Faulds

12 years ago
On 10/02/14 07:35, Yasuo Ohgaki wrote:
> Hi all, > > "Optional PHP tags by php.ini and CLI options" RFC has been discussed very > long time. > > https://wiki.php.net/rfc/nophptags > > I would like to know is there anyone who would like not to have > this. I think it's good counter measure for LFI, but you might have > different perspective. > > If it is possible, I would like to address as much as opinions possible > before voting. > > Are there anyone who think we should have this? > What is the reason? > > Thank you
I support the idea in principle; I think it's silly that files which are entirely code need to have <?php at the start. But it's impractical to implement, and hey, <?php means PHP code has its own magic number :)
-- Andrea Faulds http://ajf.me/

Sebastian Krebs

12 years ago
2014-02-10 8:35 GMT+01:00 Yasuo Ohgaki <yohgaki@ohgaki.net>:
> Hi all, > > "Optional PHP tags by php.ini and CLI options" RFC has been discussed very > long time. > > https://wiki.php.net/rfc/nophptags > > I would like to know is there anyone who would like not to have > this.
I sooo much don't care. But with the many downsides in mind I'd keep it.
> I think it's good counter measure for LFI, but you might have > different perspective. > > If it is possible, I would like to address as much as opinions possible > before voting. > > Are there anyone who think we should have this? > What is the reason? > > Thank you > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net >
-- github.com/KingCrunch

Yasuo Ohgaki

12 years ago
Hi Sebastian, On Mon, Feb 10, 2014 at 11:16 PM, Sebastian Krebs <krebs.seb@gmail.com>wrote:
> I sooo much don't care. But with the many downsides in mind I'd keep it.
Could you list them up so that I may address issues? I agree with Rasmus that having 2 parsing modes is problematic. Other than that, I don't see serious downsides. Thank you!
-- Yasuo Ohgaki yohgaki@ohgaki.net

Madara Uchiha

12 years ago
Yeah... No. On Mon, Feb 10, 2014 at 11:42 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:

Lester Caine

12 years ago
Yasuo Ohgaki wrote:
>> I sooo much don't care. But with the many downsides in mind I'd keep it. > > Could you list them up so that I may address issues? > I agree with Rasmus that having 2 parsing modes is problematic. > Other than that, I don't see serious downsides.
I though https://wiki.php.net/rfc/source_files_without_opening_tag just about summed it up? From RFC
> If you are curious about this reputation, search CVE for number of PHP LFI
Given the substantial difference between the number of sites running PHP and other languages is it really surprising that it gets the most attention? This is just another 'education' problem rather than ini proliferation one! The 'Modern Frameworks' who might use it have already removed the problem other ways, so why do they need it? The ones that might benefit from it will never switch it off anyway, so what use is it?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Kris Craig

12 years ago
On Sun, Feb 9, 2014 at 11:35 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> Hi all, > > "Optional PHP tags by php.ini and CLI options" RFC has been discussed very > long time. > > https://wiki.php.net/rfc/nophptags > > I would like to know is there anyone who would like not to have > this. I think it's good counter measure for LFI, but you might have > different perspective. > > If it is possible, I would like to address as much as opinions possible > before voting. > > Are there anyone who think we should have this? > What is the reason? > > Thank you > > -- > Yasuo Ohgaki > yohgaki@ohgaki.net >
Though I realize I'm in the minority here, I've always supported the idea of doing something like this. From an MVC standpoint, it would be nice to be able to include script-only files. These scripts would not be able to include template mode scripts, either. The main problem is, as others have stated, the fact that it'll be very prone to human error. If someone includes a script-only file as template mode, they'd be dumping the entire source for all the world to see. The only way around that-- as far as I can figure, at least-- would be to throw an exception when including a template mode file that doesn't contain a PHP open tag. The problem with that, unfortunately, is that it would almost certainly cause BC breakage. That may or may not be acceptable for a major increment like PHP 6, but certainly not for the 5.x branch. There's also the usefulness question. While I agree that it's definitely not a "must have" feature, I would venture to say it does qualify as a "would be nice" feature. Whether or not that merits implementation would be a matter for debate. It might be useful to include this in the next poll we do and see what the larger dev community thinks about this, as it's something we've debated off-and-on for years now. --Kris

Yasuo Ohgaki

12 years ago
Hi all, Let me rephrase. Does anyone argue that the fact Local script inclusion is *much grater security threat* than local script expose. "Local script expose" is the only drawback of this RFC. Currently, insecure include()/require() allows script execution. With this RFC, insecure include()/require() may allow script expose. Latter is obvious error as it shows wrong behavior while script execution is not obvious at all. If user care to script expose, they can simply add "<?php" at the top of script as it is now. We can make secure program with register_globals=On as well as embed everything by default. The same argument applies here. IMHO.
-- Yasuo Ohgaki yohgaki@ohgaki.net On Mon, Feb 10, 2014 at 4:35 PM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:

Rasmus Lerdorf

12 years ago
On 2/11/14, 9:42 AM, Yasuo Ohgaki wrote:
> Let me rephrase. Does anyone argue that the fact > > Local script inclusion is *much grater security threat* than local script > expose. > > "Local script expose" is the only drawback of this RFC. > Currently, insecure include()/require() allows script execution. > With this RFC, insecure include()/require() may allow script expose. > > Latter is obvious error as it shows wrong behavior while script execution > is > not obvious at all. If user care to script expose, they can simply add > "<?php" > at the top of script as it is now. > > We can make secure program with register_globals=On as well as embed > everything by default. The same argument applies here. IMHO.
You need 2 things to go wrong though. 1st, you need a way for someone to upload arbitrary files, and second, you need a include $_GET['filename'] somewhere. However, if you think about it, the include part is completely secondary, if you can upload arbitrary files you can just request them directly in order to execute them so the include part is irrelevant. Or, if you remove the arbitrary upload part you are down to only being able to include already existing files but most files don't actually do anything on their own. PHP files tend to either be top-level template files designed to be shown to the user, or they contain functions or classes which do nothing until called. The act of including them typically doesn't actually execute any code. So yes, in my view script exposure is a more serious problem than script execution from an insecure include so your suggested change would make things worse, not better. -Rasmus

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Wed, Feb 12, 2014 at 3:10 AM, Rasmus Lerdorf <rasmus@lerdorf.com> wrote:
> On 2/11/14, 9:42 AM, Yasuo Ohgaki wrote: > > Let me rephrase. Does anyone argue that the fact > > > > Local script inclusion is *much grater security threat* than local script > > expose. > > > > "Local script expose" is the only drawback of this RFC. > > Currently, insecure include()/require() allows script execution. > > With this RFC, insecure include()/require() may allow script expose. > > > > Latter is obvious error as it shows wrong behavior while script execution > > is > > not obvious at all. If user care to script expose, they can simply add > > "<?php" > > at the top of script as it is now. > > > > We can make secure program with register_globals=On as well as embed > > everything by default. The same argument applies here. IMHO. > > You need 2 things to go wrong though. 1st, you need a way for someone to > upload arbitrary files, and second, you need a include $_GET['filename'] > somewhere. However, if you think about it, the include part is > completely secondary, if you can upload arbitrary files you can just > request them directly in order to execute them so the include part is > irrelevant. >
I'm aware of this issue. That's the reason why I added script()/script_once() to original proposal. (include()/require() works as it is now. For compatibility, users may simply wrap include() to have script() for older PHP) Or, if you remove the arbitrary upload part you are down to only being
> able to include already existing files but most files don't actually do > anything on their own. PHP files tend to either be top-level template > files designed to be shown to the user, or they contain functions or > classes which do nothing until called. The act of including them > typically doesn't actually execute any code. So yes, in my view script > exposure is a more serious problem than script execution from an > insecure include so your suggested change would make things worse, not > better.
Attackers can use script inclusion to do anything, including reading scripts and any other security sensitive files. They can do more than reading with LFI. Therefore, LFI is worse than script exposure to me. I like the way PHP works. Embedded script nice for web applications and we should not drop it, but it's better for security if it is restricted to only where it is needed. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Wed, Feb 12, 2014 at 8:13 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:
> On Wed, Feb 12, 2014 at 3:10 AM, Rasmus Lerdorf <rasmus@lerdorf.com>wrote: > >> On 2/11/14, 9:42 AM, Yasuo Ohgaki wrote: >> > Let me rephrase. Does anyone argue that the fact >> > >> > Local script inclusion is *much grater security threat* than local >> script >> > expose. >> > >> > "Local script expose" is the only drawback of this RFC. >> > Currently, insecure include()/require() allows script execution. >> > With this RFC, insecure include()/require() may allow script expose. >> > >> > Latter is obvious error as it shows wrong behavior while script >> execution >> > is >> > not obvious at all. If user care to script expose, they can simply add >> > "<?php" >> > at the top of script as it is now. >> > >> > We can make secure program with register_globals=On as well as embed >> > everything by default. The same argument applies here. IMHO. >> >> You need 2 things to go wrong though. 1st, you need a way for someone to >> upload arbitrary files, and second, you need a include $_GET['filename'] >> somewhere. However, if you think about it, the include part is >> completely secondary, if you can upload arbitrary files you can just >> request them directly in order to execute them so the include part is >> irrelevant. >> > > I'm aware of this issue. That's the reason why I added > script()/script_once() > to original proposal. (include()/require() works as it is now. For > compatibility, > users may simply wrap include() to have script() for older PHP) >
I forgot to mention 2nd. I usually disable engine for upload directory by httpd.conf or do not allow to upload anything under webroot. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Rasmus Lerdorf

12 years ago
On 2/11/14, 3:33 PM, Yasuo Ohgaki wrote:
> I forgot to mention 2nd. I usually disable engine for upload directory > by httpd.conf > or do not allow to upload anything under webroot.
Right, you don't put your upload dir under your webroot. Even with php disabled, you wouldn't want your upload dir in your web root since the bad guys could upload nasty javascript or other interesting things and xss/csrf your users through that. As for LFI, I usually just set my open_basedir to the directories I know my application will access files from. So even if I make a mistake somewhere, the bad guys won't be able to trick any of my includes into including any other files. This seems like a much simpler and more effective way to combat LFI than introducing a template mode. -Rasmus

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Wed, Feb 12, 2014 at 10:29 AM, Rasmus Lerdorf <rasmus@lerdorf.com> wrote:
> On 2/11/14, 3:33 PM, Yasuo Ohgaki wrote: > > I forgot to mention 2nd. I usually disable engine for upload directory > > by httpd.conf > > or do not allow to upload anything under webroot. > > Right, you don't put your upload dir under your webroot. Even with php > disabled, you wouldn't want your upload dir in your web root since the > bad guys could upload nasty javascript or other interesting things and > xss/csrf your users through that. > > As for LFI, I usually just set my open_basedir to the directories I know > my application will access files from. So even if I make a mistake > somewhere, the bad guys won't be able to trick any of my includes into > including any other files. This seems like a much simpler and more > effective way to combat LFI than introducing a template mode.
I agree completely . Sorry that the RFC was hard to read. I reorganized the RFC. script() and script_once() will solve most of LFI issue. I added "Open Issue" section. I think all we have to consider is whether we allow a little inconsistency for directly called scripts or not. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Lester Caine

12 years ago
Yasuo Ohgaki wrote:
> I like the way PHP works. Embedded script nice for web applications and we > should not drop it, but it's better for security if it is restricted to > only where it is needed.
OK Re-reading the whole RFC ... it is all about 'template_mode' being used to switch tag handling on and off? PHP 'Open' tag being optional seems to be secondary? ------------------ function render_template($template, $template_vars) { ini_set('template_mode', 'on); // Older PHP ignores // Do what ever required as template ini_set('template_mode', 'off'); // Older PHP ignores } ------------------ When switching on template_mode what actually happens? Is it actually in PHP mode so that you have to add a ?> before loading raw html and then 'close' with a <?php before switching template mode off. How does one 'include' a raw html file with embedded PHP? The include needs to be in PHP space, but needs to open the file in html mode?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Yasuo Ohgaki

12 years ago
Hi Lester, I think the RFC is too long, so I'll reorganize it. Old contents remains as reference to that people could understand past discussions. On Wed, Feb 12, 2014 at 8:43 AM, Lester Caine <lester@lsces.co.uk> wrote:
> Yasuo Ohgaki wrote: > >> I like the way PHP works. Embedded script nice for web applications and we >> should not drop it, but it's better for security if it is restricted to >> only where it is needed. >> > > OK Re-reading the whole RFC ... it is all about 'template_mode' being used > to switch tag handling on and off? PHP 'Open' tag being optional seems to > be secondary? > > ------------------ > function render_template($template, $template_vars) { > ini_set('template_mode', 'on); // Older PHP ignores > // Do what ever required as template > ini_set('template_mode', 'off'); // Older PHP ignores > } > ------------------ > > When switching on template_mode what actually happens? Is it actually in > PHP mode so that you have to add a ?> before loading raw html and then > 'close' with a <?php before switching template mode off. How does one > 'include' a raw html file with embedded PHP? The include needs to be in PHP > space, but needs to open the file in html mode?
Template mode may be specified only when PHP is started, IMO. (INI_SYSTEM) Current RFC is INI_ALL, though. If users would like to use template_mode=on, they use include()/require() as usual. This is simpler than current RFC. User may do for any PHP version. function render_template($template, $template_vars) { include($template); } Anyway, current RFC allows template_mode=off/of at anytime, and it should not change include()/require() behavior at all. That's the reason why I propose script()/script_once() for script only include, and it should not change behavior depends on template_mode. Does this answer to you? I'll reorganize the RFC from now. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Lester Caine

12 years ago
Yasuo Ohgaki wrote:
> Does this answer to you? > I'll reorganize the RFC from now.
I'll refer you agin to https://wiki.php.net/rfc/source_files_without_opening_tag which was cloulding my own reading of the new rfc! Tom's first paragraph is the pertinent bit ... In the past I did my best work while sleeping. Gather all the facts and go to bed ... invariably I'd wake up as I have now in the early hours of the morning with an answer. Problem these days is simply remembering enough information to work with. As we get older the 20+ years old stuff remains stubbornly stable and we forget the new stuff! That is why as you get older you will start objecting to unnecessary change ... I still hit <Ctrl><C> for copy even where the 'new' version is <Shift><Ins> :( But as usual I'm digressing ... old age. RFI is as far as I an tell simply a matter of of configuring the web server to only process .php files via PHP ? If you are allowing users to upload .PHP files onto your machine in a location they can then run them you have bigger problems than PHP. LFI is the one that will allow corrupted files containing .php tags to run if you have not taken care of them while they are being uploaded. ONLY permanently disabling embedding will guarantee that these files do not get accidentally loaded. i.e. 'changes the spirit of PHP too much' ... ---- function render_template($template, $template_vars) { ini_set('template_mode', 'on'); // Older PHP ignores include($template, $template_vars); // Or use any other method to render. ini_set('template_mode', 'off'); // Older PHP ignores } ---- Simply pushes the problem around a little and still requires that '$template' does not point at a file that contains embedded nasties? include($template.'.php', $template_vars); does the job a lot easier? Modern frameworks ... if they are well designed ... should already have addressed all of the holes that could allow tainted files to be accessed. Embedding is the essence of PHP and for many users adding a few lines of PHP to an essentially html document is all that is needed. They don't need the ton of framework code? Smarty dropped embedded PHP from their templates in S3 'because of the security risk' but all it actually did was required that the problem php code in S2 scripts was moved back into the calling PHP. It lost a LOT of flexibility and passed the buck rather than fixing the problem. It did not fix the risk at all. I don't see how this is doing any more than pushing the problem around? You still need to properly sanitise the material and if people want to do stupid things like ini_set('template_mode', 'on'); // Older PHP ignores include($_GET['template']); // Or use any other method to render. ini_set('template_mode', 'off'); // Older PHP ignores can you really protect them anyway? Anybody who codes like that when the problems are so well advertised can't be protected except by turning off 'PHP'. I'm sure many newer users would be better off simply ignoring embedded html altogether. It would make there code a lot more secure and would remove the need for tags, but is that then PHP?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Lester Caine

12 years ago
Lester Caine wrote:
> can you really protect them anyway?
Yasuo Have you actually looked at the 'Some recent LFI issues' that are listed? I don't thing any one of them would have been protected from by this change? Providing a php page that can DISPLAY or run any file that it can read is not going to be protected from by switching embedding off?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Yasuo Ohgaki

12 years ago
Hi Lester, On Wed, Feb 12, 2014 at 2:56 PM, Lester Caine <lester@lsces.co.uk> wrote:
> Lester Caine wrote: > >> can you really protect them anyway? >> > Yasuo > Have you actually looked at the 'Some recent LFI issues' that are listed? > I don't thing any one of them would have been protected from by this > change? Providing a php page that can DISPLAY or run any file that it can > read is not going to be protected from by switching embedding off?
1st one is file upload vulnerability. I'll replace it something else. 2nd one is http://seclists.org/bugtraq/2012/Apr/53 $filepath = "$path_to_citrus/$load.php"; if (file_exists($filepath)) { include('./'.$load.'.php'); I'm not sure what they are loading. script() prevents from reading /etc/passwd or any other files. 3rd one is https://localhost/vtigercrm/modules/com_vtiger_workflow/sortfieldsjson.php?module_name=../../../../../../../../etc/passwd%00 It could also be protected by script(). 4th one is http://TARGET/onefilecms/onefilecms.php?f=../../../../etc/passwd The same as 3rd one. It works well for LFI. Important thing is include()/require() needs extra care to make sure it's secure. I would suggest to validate all inputs, but user may have invalid validation. Single mistake could be serious disaster. It's better if there is script() for sure. (Defense in depth) Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Lester Caine

12 years ago
Yasuo Ohgaki wrote:
> Have you actually looked at the 'Some recent LFI issues' that are listed? I > don't thing any one of them would have been protected from by this change? > Providing a php page that can DISPLAY or run any file that it can read is > not going to be protected from by switching embedding off? > > 1st one is file upload vulnerability. I'll replace it something else. > 2nd one is > > http://seclists.org/bugtraq/2012/Apr/53 > $filepath = "$path_to_citrus/$load.php"; > if (file_exists($filepath)) { > include('./'.$load.'.php'); > > I'm not sure what they are loading. script() prevents from reading /etc/passwd > or any other files.
Since it is loading a .php file there has to be a valid .php file to load? This is simply another file upload vulnerability? 3 and 4 as far as I can see expected the files being loaded to contain embedded php, and so the environment needed to be secured better and the application rewritten. I accept simply disabling php would have blocked the hole, but it also would stop the whole application working? Certainly onefilecms has been completely reworked and is no longer vulnerable ... as far as I can see ... I've not looked at the other app now. I still don't see how - short of switching off embedding permanently - you will stop critics with ulterior motives from calling PHP insecure? Other than that one element, php is as at risk as the other languages. Once embedding is switched off either by calling the file using 'script()' ( which I view would transparently switch embedding off so not need any ini switch! ) or by the physical ini switch, then yes PHP is any other language, so if they are so worried about it ... use something else? I could almost be convinced about the 'script()' option, but I would then insist the loaded file HAD <?php at the top and any other php tag would flag an error. It was loosing that 'security blanket' in the other rfc that grated ... but I don't see the point of the ini switch unless at some point you want to disable embedding permanently :(
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Yasuo Ohgaki

12 years ago
Hi Lester, On Wed, Feb 12, 2014 at 2:39 PM, Lester Caine <lester@lsces.co.uk> wrote:
> LFI is the one that will allow corrupted files containing .php tags to run > if you have not taken care of them while they are being uploaded. ONLY > permanently disabling embedding will guarantee that these files do not get > accidentally loaded. i.e. 'changes the spirit of PHP too much' ... > > ---- > function render_template($template, $template_vars) { > ini_set('template_mode', 'on'); // Older PHP ignores > include($template, $template_vars); // Or use any other method to > render. > > ini_set('template_mode', 'off'); // Older PHP ignores > } > ---- > > Simply pushes the problem around a little and still requires that > '$template' does not point at a file that contains embedded nasties? > include($template.'.php', $template_vars); does the job a lot easier? >
Since current PHP has null byte attack protection, this is good enough protection. I agree. The objectives of this RFC is to make PHP as secure as other languages. Other language developers do the same silly mistakes, yet almost all of them were not considered as "critical security issues" unlike PHP. This is what I would like to change. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Yasuo Ohgaki

12 years ago
Hi all, Let me rephrase more accurately. Does anyone argue that following fact is debatable? Local script inclusion is *much grater security threat* than local script expose. "Local script expose" is the only drawback of this RFC. Currently, insecure include()/require() allows script execution. With this RFC, insecure include()/require() may allow script expose. If users care to script expose, they can simply add "<?php" at the top of script as it is now if script contains security sensitive data. (Correction: Script expose could not be obvious.) We can make secure program with register_globals=On as well as embed everything by default. The same argument applies here. IMHO. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net On Wed, Feb 12, 2014 at 2:42 AM, Yasuo Ohgaki <yohgaki@ohgaki.net> wrote:

Lester Caine

12 years ago
Yasuo Ohgaki wrote:
> Let me rephrase. Does anyone argue that the fact > Local script inclusion is *much grater security threat* than local script > expose.
Since I'm happy to make my scripts available anyway. Exposure is irrelevant. Hackers can see how the code is constructed and see that there is little point trying to attack me via local script inclusion simply because I do not allow any uploaded files to be used within the live code. And But what I don't understand here is why only pure code pages are a risk? Many of the included files on the sites I'm managing have embedded html so they need the tags to be active. Header and footer blocks are more html than php and use <?= ?> tags to embed variable data along with (now) <?php ?> for the heavier processes. Surely it's just as easy to be naughty inside a block as it is simply providing a hacked page of script? That is if you have unsafe code ... surely switching off just one '<?php' will only happen on sites that are already safe anyway?
-- Lester Caine - G8HFL ----------------------------- Contact - http://lsces.co.uk/wiki/?page=contact L.S.Caine Electronic Services - http://lsces.co.uk EnquirySolve - http://enquirysolve.com/ Model Engineers Digital Workshop - http://medw.co.uk Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

Rowan Collins

12 years ago
Yasuo Ohgaki wrote (on 11/02/2014):
> Local script inclusion is*much grater security threat* than local script > expose.
I've been trying to follow the pros and cons of this RFC, and I'm really scratching my head on what the security benefit is supposed to be. As I understand it, for this to even be relevant security-wise, it would need to involve a dynamic file path being included, and an attacker somehow influencing either which file was loaded, or the contents of that file. The scenarios I can see are: 1) the include was intended to be PHP code, and the attacker substitutes different PHP code of their choice 2) the include was intended to be PHP code, and the attacker accesses non-PHP data already on server 3) the include was intended to be non-PHP data, and the attacker substitutes PHP code of their choice 4) the include was intended to be non-PHP data, and the attacker accesses different non-PHP data already on server This sentence in the RFC Summary sounds like it's talking about 3:
> However, embedded scripts are serious security risk as it can
executes any PHP code in any files. But if somebody is using include() for non-PHP data, they're using the wrong function anyway, end of story. Barring bugs in the engine (e.g. null byte handling) 1 and 4 are something that no language can guard against: substituting code for code, or data for data (if include() couldn't do it, file_get_contents() could). There's a lot of talk in the RFC about validating file *contents*, but it seems to me that careful whitelisting of file location and naming is generally more relevant (e.g. "/etc/passwd" doesn't end in ".php", so it's kind of obvious you shouldn't be passing it to an include statement). 2 seems to be more relevant to me: without the "always echo if no <?php found" rule, it's easier to trick include() into acting like readfile(). The failure to load the expected PHP code would probably cause a Fatal Error anyway, but the contents might be exposed first. But that doesn't seem to be the exploit that is being discussed on this RFC. Or am I misunderstanding completely? Could somebody enlighten me with an artificially simplified example of a code execution attack that is possible today but would be prevented (or preventable) with the proposed change? Thanks,
-- Rowan Collins [IMSoP]

Yasuo Ohgaki

12 years ago
Hi Rowan, On Thu, Feb 13, 2014 at 7:43 AM, Rowan Collins <rowan.collins@gmail.com>wrote:
> Yasuo Ohgaki wrote (on 11/02/2014): > >> Local script inclusion is*much grater security threat* than local script >> expose. >> > > I've been trying to follow the pros and cons of this RFC, and I'm really > scratching my head on what the security benefit is supposed to be. > > As I understand it, for this to even be relevant security-wise, it would > need to involve a dynamic file path being included, and an attacker somehow > influencing either which file was loaded, or the contents of that file. > > The scenarios I can see are: > > 1) the include was intended to be PHP code, and the attacker substitutes > different PHP code of their choice > 2) the include was intended to be PHP code, and the attacker accesses > non-PHP data already on server > 3) the include was intended to be non-PHP data, and the attacker > substitutes PHP code of their choice > 4) the include was intended to be non-PHP data, and the attacker accesses > different non-PHP data already on server > > This sentence in the RFC Summary sounds like it's talking about 3: > > > However, embedded scripts are serious security risk as it can executes > any PHP code in any files. > > But if somebody is using include() for non-PHP data, they're using the > wrong function anyway, end of story. >
Right. This is what I would like to change. In other languages, such script inclusion ends up syntax error, end of attack. In PHP, this may end up - disclosing any information in file, disaster. - executing any embedded scripts, fatal disaster. This difference is enough reason to introduce some kind of protection. There are number of ways to inject piece of PHP code into files. Attacker can exploit other feature/vulnerability to take over server completely. Session file is one of the common method. Barring bugs in the engine (e.g. null byte handling) 1 and 4 are something
> that no language can guard against: substituting code for code, or data for > data (if include() couldn't do it, file_get_contents() could). There's a > lot of talk in the RFC about validating file *contents*, but it seems to me > that careful whitelisting of file location and naming is generally more > relevant (e.g. "/etc/passwd" doesn't end in ".php", so it's kind of obvious > you shouldn't be passing it to an include statement). >
We don't have to care much that other languages cannot protect neither. IMO. 2 seems to be more relevant to me: without the "always echo if no <?php
> found" rule, it's easier to trick include() into acting like readfile(). > The failure to load the expected PHP code would probably cause a Fatal > Error anyway, but the contents might be exposed first. >
Compile error will not display any code/contents except a piece displayed as error message. But that doesn't seem to be the exploit that is being discussed on this
> RFC. Or am I misunderstanding completely? > > Could somebody enlighten me with an artificially simplified example of a > code execution attack that is possible today but would be prevented (or > preventable) with the proposed change? >
I think you have enough skill to prevent script inclusion attacks. However, all PHP users are not. Take a look at vulnerability reports, you'll find number of LFI that could be prevented by this RFC. http://packetstormsecurity.com/search/?q=LFI These are only reported LFI vulnerabilities and there are countless vulnerable scripts in the wild. I don't see any reason to keep doors open for attackers. We are better to close as many doors as possible, especially for fatal disaster(script execution). Thank you for the comment! Regards, P.S. I was added script()/script_once() to the original RFC. However, it may be easier for users to have template()/template_once() that parses file as embedded PHP script mode always and keep include()/require() for script inclusion. This way, users do not have to rewrite include()/require() to script(). Anyone has any comments?
-- Yasuo Ohgaki yohgaki@ohgaki.net

Rasmus Lerdorf

12 years ago
On 02/12/2014 05:30 PM, Yasuo Ohgaki wrote:
> I think you have enough skill to prevent script inclusion attacks. However, > all PHP users are not. Take a look at vulnerability reports, you'll find > number of LFI that could be prevented by this RFC. > > http://packetstormsecurity.com/search/?q=LFI > > These are only reported LFI vulnerabilities and there are countless > vulnerable scripts in the wild. > > I don't see any reason to keep doors open for attackers. We are better to > close as many doors as possible, especially for fatal disaster(script > execution). > > Thank you for the comment! > > Regards, > > P.S. I was added script()/script_once() to the original RFC. However, it > may be easier for users to have template()/template_once() that parses file > as embedded PHP script mode always and keep include()/require() for script > inclusion. This way, users do not have to rewrite include()/require() to > script(). Anyone has any comments?
I just went through about 20 LFIs at http://packetstormsecurity.com/search/?q=LFI and in every single case an appropriately set open_basedir would have prevented the LFI. That seems pretty definitive to me. The feature to prevent LFI is already there. We do not need another one. Especially one that introduces a confusing distinction between scripts and templates which really has nothing to do with the underlying problem. So the real problem is two-fold. People are making these mistakes in the first place, and second, they are not coding defensively and setting open_basedir. You are still asking people to actively make a defensive coding change with this RFC, but the people who make these mistakes and don't code defensively aren't suddenly going to change so they would not benefit. -Rasmus

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Fri, Feb 14, 2014 at 12:07 AM, Rasmus Lerdorf <rasmus@lerdorf.com> wrote:
> On 02/12/2014 05:30 PM, Yasuo Ohgaki wrote: > > I think you have enough skill to prevent script inclusion attacks. > However, > > all PHP users are not. Take a look at vulnerability reports, you'll find > > number of LFI that could be prevented by this RFC. > > > > http://packetstormsecurity.com/search/?q=LFI > > > > These are only reported LFI vulnerabilities and there are countless > > vulnerable scripts in the wild. > > > > I don't see any reason to keep doors open for attackers. We are better to > > close as many doors as possible, especially for fatal disaster(script > > execution). > > > > Thank you for the comment! > > > > Regards, > > > > P.S. I was added script()/script_once() to the original RFC. However, it > > may be easier for users to have template()/template_once() that parses > file > > as embedded PHP script mode always and keep include()/require() for > script > > inclusion. This way, users do not have to rewrite include()/require() to > > script(). Anyone has any comments? > > I just went through about 20 LFIs at > http://packetstormsecurity.com/search/?q=LFI and in every single case an > appropriately set open_basedir would have prevented the LFI. That seems > pretty definitive to me. The feature to prevent LFI is already there. We > do not need another one. Especially one that introduces a confusing > distinction between scripts and templates which really has nothing to do > with the underlying problem. > > So the real problem is two-fold. People are making these mistakes in the > first place, and second, they are not coding defensively and setting > open_basedir. You are still asking people to actively make a defensive > coding change with this RFC, but the people who make these mistakes and > don't code defensively aren't suddenly going to change so they would not > benefit.
I agree. People who realize importance of security must develop application defensively. They must validate all inputs strictly when inputs are supplied. They must use all protection mechanism available. It's perfectly true that users can write robust web applications with PHP, but Packet Storm reports show that we are better to have yet another protection for disasters. People write weak applications/codes. I audit Rails application also. Rails is not a magic platform that makes web applications secure. Those people write weak applications with Rails would write weak applications with PHP, too. I'm sure many of them would write LFI vulnerable codes. Yet, their applications do not have fatal disaster like LFI. PHP is for the web. Web is extremely dangerous as serious professional attackers exploit web for money. Introducing yet another effective counter measure for fatal error is valuable for PHP community because there are vulnerable applications/codes. I cannot accept the fact that PHP could be much insecure than others when the same developers write applications... <?php ini_set('template_mode', 'OFF'); // All require()/include() are protected against typical LFI require($some_module); // script only require($another_module); // script only // Need template(embedded) mode. Extra caution here. template($mytemplate . '.php'); // embedded script. Users may have LFI with template() still, but attack vector is limited to template(). It's much easier for users to pay extra attentions to limited template() rather than all script inclusions. (It's easier to audit, too :) Perhaps, we may be better to force template() to have ".php" extension (or 2nd required param as extension), so that template($template); includes "${template}.php" always. It's much secure thanks to your(Rasmus) null byte attack protection. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Rasmus Lerdorf

12 years ago
On 02/13/2014 02:51 PM, Yasuo Ohgaki wrote:
> PHP is for the web. Web is extremely dangerous as serious professional > attackers exploit web for money. Introducing yet another effective > counter measure for fatal error is valuable for PHP community because > there are vulnerable applications/codes. I cannot accept the fact that > PHP could be much insecure than others when the same developers write > applications...
Perhaps the biggest part of writing secure applications is understanding your tools and your environment. The more complicated they are, the harder it is to use them correctly. You are asking to add a brand new high-level concept to PHP by adding a distinction between a template and a non-template file. As far as PHP is concerned, everything is a "template", although we never use that term. Even a plain text file with no php tags is a template. There is no technical difference between a file containing: hello world and one containing: <?= "hello world\n"; They both compile to exactly: ECHO 'hello+world%0A' RETURN 1 So what is a template? What isn't a template? Is it a template simply because it contains a PHP tag? Or is a file not a template because it doesn't? Or is it the name of the file? What about its location? In the end, none of these things fully define a template. A template is defined by the context in which it is used. Changing this basic characteristic of PHP is a really serious change and you are going to need a much better argument than simple LFI for it to have any chance in a vote I would suspect. Striving to make PHP more secure for neophyte developers is always a worthy goal, but it needs to be done in a way that doesn't make things worse. I think this particular approach would make things worse by needlessly complicating things. -Rasmus

Yasuo Ohgaki

12 years ago
Hi Rasmus, On Fri, Feb 14, 2014 at 9:00 AM, Rasmus Lerdorf <rasmus@lerdorf.com> wrote:
> Striving to make PHP more secure for neophyte developers is always a > worthy goal, but it needs to be done in a way that doesn't make things > worse. I think this particular approach would make things worse by > needlessly complicating things. >
I agree that needless complexity should be avoided. Switching template mode on and off is tricky, although existing codes can be secured without many lines of change. There are options for LFI mitigation. There might be convincing solution. I cannot think of one now, though. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Rowan Collins

12 years ago
Yasuo Ohgaki wrote (on 13/02/2014):
> > But if somebody is using include() for non-PHP data, they're using > the wrong function anyway, end of story. > > > Right. This is what I would like to change. > In other languages, such script inclusion ends up syntax error, end of > attack.
I was talking here about my cases 3 and 4, where the author is *deliberately* using include for something other than code. There is already a correct function for that, which is readfile(), or more likely file_get_contents() and then some processing, so no changes are needed to introduce it.
> There are number of ways to inject piece of PHP code into files. > Attacker can exploit other feature/vulnerability to take over server > completely. Session file is one of the common method.
Are session files relevant to this discussion, or was this just a side note?
> Compile error will not display any code/contents except a piece > displayed as error message.
That's not quite true. A fatal error can occur after output has been flushed through to the browser. The include statement will succeed (acting like readfile()), and the fatal error, if any, will happen afterwards, e.g. because an expected class definition was not loaded.
> Take a look at vulnerability reports, you'll find number of LFI that > could be prevented by this RFC.
I looked at some of the examples in the RFC, but I don't understand how they relate to this proposal. No amount of links to vulnerability reports can tell me that, but you can. What I am asking for is an example - real or artificial, I don't mind - with an explanation of how it behaves now, and how that behaviour would be improved by the proposed change. Note that I'm not trying to shoot down your proposal - on the contrary, I'm trying to make sure its benefits are clearer, so that people will have a better means of judging it. Regards,
-- Rowan Collins [IMSoP]

Yasuo Ohgaki

12 years ago
Hi Rowan, On Sat, Feb 15, 2014 at 2:10 AM, Rowan Collins <rowan.collins@gmail.com>wrote:
> > >> But if somebody is using include() for non-PHP data, they're using >> the wrong function anyway, end of story. >> >> >> Right. This is what I would like to change. >> In other languages, such script inclusion ends up syntax error, end of >> attack. >> > > I was talking here about my cases 3 and 4, where the author is > *deliberately* using include for something other than code. There is > already a correct function for that, which is readfile(), or more likely > file_get_contents() and then some processing, so no changes are needed to > introduce it. > >
3) the include was intended to be non-PHP data, and the attacker substitutes PHP code of their choice 4) the include was intended to be non-PHP data, and the attacker accesses different non-PHP data already on server These are abuse of feature. It's better to disable such usage.
> > > There are number of ways to inject piece of PHP code into files. Attacker >> can exploit other feature/vulnerability to take over server completely. >> Session file is one of the common method. >> > > Are session files relevant to this discussion, or was this just a side > note?
Yes, it is relevant as PHP executes fragment of code in a file always. Many codes save user supplied data in session. i.e. It can be used for LFI attack that executes arbitrarily codes .
> Compile error will not display any code/contents except a piece displayed >> as error message. >> > > That's not quite true. A fatal error can occur after output has been > flushed through to the browser. The include statement will succeed (acting > like readfile()), and the fatal error, if any, will happen afterwards, e.g. > because an expected class definition was not loaded.
When a language executes data files as program, it ends up with syntax error during compile time almost always. PHP compiles script, then executes. Program may output something before data file inclusion, but it must be intended output. Data file inclusion results in syntax error and content would not be exposed. Attacker may disguise script a data file. Insufficient data file validation may permit script execution in other languages, too. I'm not concerned much about this case. New RFC will address this issue, though.
> Take a look at vulnerability reports, you'll find number of LFI that >> could be prevented by this RFC. >> > > I looked at some of the examples in the RFC, but I don't understand how > they relate to this proposal. No amount of links to vulnerability reports > can tell me that, but you can. > > What I am asking for is an example - real or artificial, I don't mind - > with an explanation of how it behaves now, and how that behaviour would be > improved by the proposed change. > > Note that I'm not trying to shoot down your proposal - on the contrary, > I'm trying to make sure its benefits are clearer, so that people will have > a better means of judging it.
I'll abandon this RFC since I came up with better idea. New RFC will address all issues have been discussed in this and other threads. All discussions were valuable. Thanks a lot to all! Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net

Johannes Schlueter

12 years ago
On Sat, 2014-02-15 at 07:28 +0900, Yasuo Ohgaki wrote:
> 3) the include was intended to be non-PHP data, and the attacker > substitutes PHP code of their choice > 4) the include was intended to be non-PHP data, and the attacker accesses > different non-PHP data already on server
People using the wrong feature won't be fixed by adding yet another way to open a file. johannes

Yasuo Ohgaki

12 years ago
Hi Johannes, On Sat, Feb 15, 2014 at 8:53 AM, Johannes Schlüter <johannes@schlueters.de>wrote:
> On Sat, 2014-02-15 at 07:28 +0900, Yasuo Ohgaki wrote: > > 3) the include was intended to be non-PHP data, and the attacker > > substitutes PHP code of their choice > > 4) the include was intended to be non-PHP data, and the attacker accesses > > different non-PHP data already on server > > People using the wrong feature won't be fixed by adding yet another way > to open a file.
I have an idea. Please wait for a new RFC. Regards,
-- Yasuo Ohgaki yohgaki@ohgaki.net