php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #62745 Extend echo and print possiblity
Submitted: 2012-08-04 14:13 UTC Modified: 2012-08-09 02:00 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:1 (50.0%)
From: kjelkenes at gmail dot com Assigned:
Status: Wont fix Package: Output Control
PHP Version: 5.4.5 OS: *
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
41 - 9 = ?
Subscribe to this entry?

 
 [2012-08-04 14:13 UTC] kjelkenes at gmail dot com
Description:
------------
This is a feature request regarding the "echo" and "print" functions used in PHP. The echo/print statement is used for output. As of today there are no way of extending these statements, leading to potential security risks.


If we could extend the echo function at a given time with a handler/closure this could really improve the security of PHP. 


Say we have the following security risk (XSS injection):

$data = "<h1><script>alert('hi');</script></h1>"; // From db.

echo $data;



Today we need custom functions to escape this such as:

function escape($data){
    return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
}

echo escape($data);



What if we could implement a handler for the echo/print statements such as this:

// Define a handler:
$outputHandler = function escape($data){
    return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
};


/**
 * Sets a output handler for php, it's used in echo and print statements.
 * @param string $name The identity of this handler ( Unique )
 * @param mixed $outputHandler function name or callback closure to use.
 * @param mixed $flags What type of satements to use this function.
 */

add_output_handler('xss_filter',$outputHandler, OutputHandler::F_ECHO | OutputHandler::F_PRINT);


/**
 *  Removes a given output handler by it's name.
 */
remove_output_handler('xss_filter');




Then we could use normal statements:

echo '<script>alert('This will never be exected.')</script>';


And when we don't need it anymore:

remove_output_handler('xss_filter');



This way, one can be sure that the output of ANY kind is actually stripped, without implementing a whole new templating system for PHP.

Also this does not break any kind of PHP applications running, it just adds new functionality that is (let's face it) really needed for PHP.


This is also great for MVC frameworks, just apply it before executing a view file and remove it after!


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-08-04 19:30 UTC] keithm at aoeex dot com
You can already accomplish this using output buffering if so desired.  I don't 
see a need to add anything else into the mix.  For example:

------------------------------------------
<?php
$outputHandler = function($data){
	return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
};

ob_start($outputHandler);

echo '<script>alert(\'This will never be executed.\')</script>';

------------------------------------------

outputs:
&lt;script&gt;alert(&#039;This will never be executed.&#039;)&lt;/script&gt;
 [2012-08-05 01:23 UTC] kjelkenes at gmail dot com
For the comment above.

Ok, You don't see the need?

Output buffering is something completely different. Yes you can do the same with output buffering.. But it still includes the HTML that was not printed by the parser.



What about this case, do you really think output ob_start() buffering???

ob_start();
<?php echo $user->getName()?>
<b> This is ALSO cached by output buffer function.....</b>
$content = ob_get_flush();


That script... yes .. ob_start() before everything and ob_get_contents() will return the complete parsed content... but it does NOT intercept the ECHO statement, meaning if you where about to try parsing:


Meaning Output buffering functions could NEVER intercept the echo statement ( RATHER THE WHOLE THING ) . 


What if we wanted to intercept the real echo statement and not the ob_* functions..


Seriously your comment does not make sense. You are talking about ob_* functions while this is a whole another case, please don't follow this ticket.
 [2012-08-05 05:43 UTC] phpmpan at mpan dot pl
From my point of view, keithm provides a solution that does exactly the thing you have asked for. Output buffering wasn't created for this purpose, but it can be easily used for it without breaking anything. If this is not what you wanted, maybe your description is not clear enough?

However this is a solution for a problem that doesn't exist in reality.
 1. Most of the data output by scripts should never be escaped.
    Yet your idea causes ALL data to be escaped, producing garbage.
 2. In few specific cases there are small portions of data from untrusted
    sources that should be escaped. In such cases a single call is enough.
    What you want to be introduced requires 3 lines of code (enable escaping,
    echo, disable escaping) just to make same thing a single function call
    could do.
 3. Even worse: the concept is perpendicular to echo by design,
    but not perpendicular to echo by behaviour. Hence it's a design error.
 [2012-08-05 06:55 UTC] laruence@php.net
1. if you want taint mode, refer to : http://pecl.php.net/taint
2. if you want escape output: refer to http://www.php.net/manual/en/function.ob-
start.php

thanks
 [2012-08-06 01:01 UTC] aharvey@php.net
The commenters are right: output buffering already deals with the feature as requested, and as Laruence points out, the taint extension is available for the underlying issue if you want to go down that road.

Closing.
 [2012-08-06 01:01 UTC] aharvey@php.net
-Status: Open +Status: Wont fix -Package: Unknown/Other Function +Package: Output Control
 [2012-08-06 13:07 UTC] kjelkenes at gmail dot com
Ignorance, gotta love it. There is really a difference of output buffering functions and this, I do of course know of the output buffering functions, this is NOT RELATED. Read on to really see what I mean about this.



This is how people in most cases write their VIEW logic. Meaning ending and starting <?php echo ..?> every time they echo stuff.. That also means you should ESCAPE ALL data that comes to echo, else you are just not SAFE. 


index.php:


<?php
  // Web page title.
  $title = 'My website';
  // A item from the database.
  $item = array('title' => '<script>alert("Hi!")</script>');
?>

<?php ob_start() ?>
<html>
	<head>
		<title><?php echo $title?></title>
	</head>
	<body>
		<div><p><?php echo $item['title']?></p></div>
	</body>
</html>
<?php
$content = htmlspecialchars(ob_get_flush(),ENT_QUOTES,'UTF-8');
echo $content;

/*  Returns:
&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;My website&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div&gt;&lt;p&gt;&lt;script&gt;alert(&quot;Hi!&quot;)&lt;/script&gt;&lt;/p&gt;&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;


FAIL?! We NEED a echo handler....
*/
?>




Obviously this won't work if people wrote their template like this (but that's up to them...):


index.php

echo "
<html>
	<head>
		<title>{$title}</title>
	</head>
	<body>
		<div><p>{$item['title']}</p></div>
	</body>
</html>
";



This is wanted behaviour (The use of htmlspecialchars wouldn't be necessary if we had a handler that intercepted the echo statement.):


<?php
  // Web page title.
  $title = 'My website';
  // A item from the database.
  $item = array('title' => '<script>alert("Hi!")</script>');
?>

<html>
	<head>
		<title><?php echo htmlspecialchars($title,ENT_QUOTES,'UTF-8')?></title>
	</head>
	<body>
		<div><p><?php echo htmlspecialchars($item['title'],ENT_QUOTES,'UTF-8')?></p></div>
	</body>
</html>
<?php

/*  Returns:
<html>
	<head>
		<title>My website</title>
	</head>
	<body>
		<div><p>&lt;script&gt;alert(&quot;Hi!&quot;)&lt;/script&gt;</p></div>
	</body>
</html>


Perfect!
*/
?>
 [2012-08-06 18:27 UTC] phpmpan at mpan dot pl
When making general statements, first make sure that by writing "all people do" you don't mean "I do". Also please take a look at the calendar. Mine says 2012, not the end of XX century. Maybe 10 years ago it was acceptable, but it's no longer a good habit to mix business logic and presentation layer, virtually any bigger application is written in OOP (which doesn't mix well with exiting PHP mode) and the presentation layer is handled by template engines or frameworks.

As I said before: you're trying to solve a problem that doesn't really exist. If it can be observed anywhere, it's just a symptom of a different problem that lies between keyboard and chair, not in PHP.

Also it's not a good idea to call PHP devs ignorants and raging because your idea is not accepted. If you believe that it's really needed, try to convince people it is so! Insulting will not get you anywhere.
 [2012-08-06 18:59 UTC] kjelkenes at gmail dot com
Just stating the obvious.

OOP, MVC, Templating engine, you sir have greatly missed the point of this feature request.
 
Are you talking about OOP? OOP has _nothing_ to do with this question, of course you would use OOP: classes, namespaces and traits.. But this is not the place to talk about OOP design.
 
Are you talking about MVC? Because this addition will make every currently existing MVC frameworks such as Symfony 2 and Codeigniter more secure. 


You separate controller / business logic / presentation logic, but you are now starting a discussion of using a 3rdparty library against php itself as a templating-engine. Does not really make sense at all regarding this feature request. 

You don't USE a templating framework if you implement this change, this change will make it easier then never to CREATE the fastest templating engine on the market without having to parse code to php code and then use the php code to make php safe. Note, php is a language, you can also template with it because of it's easy syntax HTML<?php echo $var?>MORE_HTML.


In Symfony 2 you have to either use 

- TWIG syntax (Templating engine)
- echo $this->escape("<script></script"); ( Symfony way .. )


Now, this didn't have to be needed if this feature request was implemented.

- echo "<script>.."; ( This is not possible at this time )
 [2012-08-09 02:00 UTC] kjelkenes at gmail dot com
Before you blatantly ignore this bug report, please take your time to read the following posts:

- http://fabien.potencier.org/article/34/templating-engines-in-php ( Security )
- http://pkj.no/blog/2012/08/08/php-use-a-template-system-or-not


And the most important rule of XSS prevention (right now):

" Don't forget to add htmlspecialchars($var, ENT_QUOTES, 'utf-8') on every single echo statement "
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 19:01:29 2024 UTC