Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Auto-HTML-escaping variables and templates

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Wed Mar 02, 2011 5:19 pm    Post subject: Auto-HTML-escaping variables and templates Reply with quote

NOTE: Smarty 3.1 now has an automated html-escape mode. http://www.smarty.net/docs/en/variable.escape.html.tpl

It is easy to selectively HTML-escape template variables with the {$foo|escape} modifier. However, sometimes it is advantageous to have everything assigned to Smarty automatically HTML-escaped to reduce the risks of XSS (cross-site scripting) vulnerabilities.

Smarty currently does not do this out of the box, nor does it offer a flag to enable this, but it is quite trivial to implement with a variable filter. Here is how it is done:

First, somewhere in your code make a function to do the escapement:

Code:
function escFilter($content,$smarty) {
   return htmlspecialchars($content,ENT_QUOTES,UTF-8);
}


Now register the variable filter with Smarty:

Code:
$smarty->registerFilter('variable','escFilter');


Now any variable assigned to Smarty will be HTML escaped:

PHP:
Code:
$smarty->assign('foo','This is <some> content');


Template:
Code:
{$foo}


Output:
Code:
This is &lt;some&gt; content


You can also selectively "unescape" variables by skipping the filter:

Template:
Code:
{$foo}   {* this gets filtered *}
{$foo nofilter}  {* this does not *}


Output:

Code:
This is &lt;some&gt; content
This is <some> content


To go one step further, lets say you would like to mark blocks of template content that also get HTML-escaped. You can do this with a block plugin:

First make a PHP function for the plugin:

Code:
function escPlugin($params,$content,$smarty,&$repeat) {
  return htmlspecialchars($content,ENT_QUOTES,UTF-8);
}


Now register the block plugin with Smarty:
Code:
$smarty->registerPlugin('block','escape','escPlugin');


And now you can use this in your templates:


Code:
{escape}
This is some text I want <> escaped.
{/escape}

This not <> escaped.


Output:
Code:
This is some text I want &lt;&gt; escaped.


This not <> escaped.


Be warned, block plugins act on the output of template variables inside the block. Therefore, variables inside the block are also escaped. If you have the escape filter on a variable and put it inside the escape block, it will get double escaped!

Template:
Code:
{$foo} {* escaped by filter *}
{escape}
This is <some> text to escape.
{$foo} {* double-escaped! *}
{$foo nofilter} {* still escaped by the block *}
{/escape}


If you want *everything* escaped on the page you could implement an output filter in the same manner as above. This would probably not be a common case as most pages contain some legitimate HTML. So, I'll leave that as an exercise to the reader Smile

And that should do it!


Last edited by mohrt on Thu Dec 01, 2011 5:51 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
thelem
Smarty n00b


Joined: 10 Apr 2011
Posts: 1

PostPosted: Sun Apr 10, 2011 10:27 am    Post subject: Reply with quote

Isn't this basically the same as PHP's Magic Quotes feature, which was generally agreed to be a bad idea and subsequently removed?

http://php.net/manual/en/security.magicquotes.php

Having said that, this does seem to be implemented at the correct layer which magic quotes wasn't (it applied the same escaping algorithm whether you were using the data in SQL, HTML or whatever) and having to explictly mark certain variables as allowing HTML (using nofilter) does seem a safer default.
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Sun Apr 10, 2011 3:06 pm    Post subject: Reply with quote

thelem wrote:
Isn't this basically the same as PHP's Magic Quotes feature, which was generally agreed to be a bad idea and subsequently removed?

http://php.net/manual/en/security.magicquotes.php

Having said that, this does seem to be implemented at the correct layer which magic quotes wasn't (it applied the same escaping algorithm whether you were using the data in SQL, HTML or whatever) and having to explictly mark certain variables as allowing HTML (using nofilter) does seem a safer default.


Yes applying an escapement filter on the template layer is the correct implementation for its purpose. This isn't exactly like magic quotes either, it doesn't try to SQL escape.
Back to top
View user's profile Send private message Visit poster's website
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Sun Apr 10, 2011 3:30 pm    Post subject: Re: Auto-HTML-escaping variables and templates Reply with quote

mohrt wrote:
[...] Be warned, block plugins act on the output of template variables inside the block. Therefore, variables inside the block are also escaped. If you have the escape filter on a variable and put it inside the escape block, it will get double escaped!


As of PHP 5.2.3 htmlspecialchars() features the $double_encode argument. If set to true, entities are not escaped again. Smarty (as of 3.1) already has an internal function to deal with a fallback for PHP < 5.2.3. This allows for

Code:
require_once SMARTY_DIR . 'plugins/shared.escape_special_chars.php';
$smarty->registerFilter('variable','smarty_function_escape_special_chars');
and
Code:
function escPlugin($params,$content,$smarty,&$repeat) {
  return smarty_function_escape_special_chars($content);
}
$smarty->registerPlugin('block','escape','escPlugin');
Back to top
View user's profile Send private message Visit poster's website
Adi21
Smarty n00b


Joined: 15 Sep 2011
Posts: 1

PostPosted: Thu Sep 15, 2011 4:40 am    Post subject: Reply with quote

Autoescape is a very cool option. I would like to see it turned on by default, or at the very least let it be an (optional) argument to the constructor of the Dwoo main class, so I don't have to use a couple of lines of boiler plate code, each time a new Dwoo instance is created.

Escaping html-characters is something a lot of developers don't get right. In most cases, the strings you insert into a template, should be escaped. So I think it's a very sane choice the Django folks made, by making autoescape default and I think you would do well by following the same standard for Dwoo. Otherwise a very nice template engine.

-----------------------------------------
tools parts & accessories
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Thu Sep 15, 2011 7:01 am    Post subject: Reply with quote

Adi21 wrote:
Autoescape is a very cool option. I would like to see it turned on by default, or at the very least let it be an (optional) argument to the constructor of the Dwoo main class, so I don't have to use a couple of lines of boiler plate code, each time a new Dwoo instance is created.


You know that this is the Smarty forum, not Dwoo, right?
Smarty 3.1 also sports a new flag $escape_html, which would run all your output through htmlspecialchars().
_________________
Twitter
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP