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

variableFilter and preventing HTML injection

 
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 -> Smarty 3
View previous topic :: View next topic  
Author Message
stayclose
Smarty Rookie


Joined: 16 Feb 2010
Posts: 9

PostPosted: Tue Feb 16, 2010 3:37 pm    Post subject: variableFilter and preventing HTML injection Reply with quote

Hello,

I sent Monte a question about preventing HTML injection with Smarty and he told me to post it on the forum so others could benefit from it.

I think in most cases HTML injection is overlooked by the webdeveloper and perhaps even the programmer (sometimes the webdeveloper IS the programmer.). It could also be that one thinks the other will fix it or vice versa.

I know there is the escape modifier but it is really easy to forget.

Thus are two options:

1) prevent HTML injection by using htmlspecialchars() BEFORE assigning them to Smarty. Mistakes can be made at this point. Often someone needs an extra variable and it is quickly hacked in and the escaping forgotten.

Now, I agree with the following post here:

www . madcat . nl/martijn/archives/16-Using-smarty-to-prevent-HTML-injection..html (can't post links yet)

'Since HTML (and Javascript) injection is only present in the presentation layer I want my presentation layer to handle the filtering. I can't really be bothered at the logic layer, since the problem does not exists there.'

2) the web developer just uses the escape modifier. In my opinion this is really the worst you can do. Escaping will most of the time be forgotten and added only when there is a problem. I don't think something with so much implications should be left to someone whose daily routine has nothing to do with security. Ofcourse there are always exceptions to the rule and I am not talking about them.

We are all human and mistakes will be made.

But (and it appears to have been in Smarty 2 also in some other form) in Smarty3 there is a variable filter (thanks Monte).

I overlooked it while reading the readme (smarty-php . googlecode . com/svn/branches/Smarty3Dev/distribution/README) and it is really exactly what I was looking for and I think others can benefit from it too. Perhaps this has been already known to a lot of you and thus this post is not for you. It is for those that really didn't think about it before [HTML injection]. (NOTE: I don't know if this can be disabled for specific variables in the template (ie nofilter)). With the variable filter you can run any kind of filter over your variables, including htmlspecialchars() and thus removing the need for 1) and 2).

Now, I tried the following (and this is where something comes up what looks like a bug).

This works, but generates an error:

$smarty->loadFilter("variable", "htmlspecialchars");

PHP Warning: Parameter 2 to smarty_variablefilter_htmlspecialchars() expected to be a reference, value given in Smarty3/sysplugins/smarty_internal_filter_handler.php on line 55

smarty_internal_filter_handler.php line 55:
-------------------------------------------
$output = call_user_func_array($smarty->registered_filters[$type][$key], array($output, $smarty));

I changed this to the following to make the warning go away:

$output = call_user_func_array($smarty->registered_filters[$type][$key], array($output, &$smarty));

(NOTE: if this IS a bug, this needs to be changed in more places)

I also tried the register->variableFilter method but this didn't seem to work correctly or atleast not the way I was expecting.

$smarty->register->variableFilter("htmlspecialchars");

PHP Warning: htmlspecialchars() expects parameter 2 to be long, object given in Smarty3/sysplugins/smarty_internal_filter_handler.php on line 55

Now, I would have expected this method to figure out the function name (smarty_etc) itself and load the variablefilter file from the plugins dir. It is not doing that and is using the PHP htmlspecialchars() function hence the warning.

There doesn't seem to be any documentation about this, so I can't say for sure if this is a bug or something wrong on my side. Either way, I would like to know what is wrong.

I am using PHP 5.3.1 and Smarty 3 SVN revision 3497

Also, remember that this variable filter will affect performance. How much will depend on your situation (as always). As I told Monte, I'd rather be a tad slow and know things are a little bit more secure than fast and open to the world of abuse. These things WILL happen so better come prepared.

Cheers
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Tue Feb 16, 2010 8:36 pm    Post subject: Reply with quote

1. The bug is not in smarty_internal_filter_handler.php as you assumed.

The funtion definition in variablefilter.htmlspecialchars.php should have been

function smarty_variablefilter_htmlspecialchars($source, $smarty)

instead of

function smarty_variablefilter_htmlspecialchars($source, &$smarty)

as PHP5 is passing object always by reference.

A fix for this is in the SVN now.


2. $smarty->register->variableFilter(...) does exspect a function which is defined locally in your script as parameter.

The function must have the two parameters ($source, $smarty).
You can't use $smarty->register->variableFilter(...) to register the standard PHP function htmlspecialchars as the parameter don't match.
Back to top
View user's profile Send private message
emt
Smarty Regular


Joined: 10 Dec 2009
Posts: 43

PostPosted: Wed Feb 17, 2010 6:53 pm    Post subject: Reply with quote

Just for others who can't get it to work right away - if you want to load the smarty variable filter 'htmlspecialchars' I got it working with this:

Code:
$smarty->loadFilter("variable", "htmlspecialchars");
$smarty->register->variableFilter('smarty_variablefilter_htmlspecialchars');


If you don't want it to apply to a particular variable, just add 'nofilter':

Code:
{$record.CONTACT_NAME nofilter}
Back to top
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Wed Feb 17, 2010 7:25 pm    Post subject: Reply with quote

emt

You just need
Code:
$smarty->loadFilter("variable", "htmlspecialchars");

to load the variable filter plugin.

$smarty->register->variableFilter(...) is used to register a function which is defined in your script as filter. In your example it did not create an error because the previous $smarty->loadFilter("variable", "htmlspecialchars") did load the plugin into the context of your script so that a function of name smarty_variablefilter_htmlspecialchars was definied by that.
Back to top
View user's profile Send private message
emt
Smarty Regular


Joined: 10 Dec 2009
Posts: 43

PostPosted: Wed Feb 17, 2010 7:47 pm    Post subject: Reply with quote

Aaaaaargggghhhh!

I was able to reproduce why just having the single line didn't work for me. It helps when you put $smarty->force_compile = true; into your code as templates cannot detect when your source code changes...

Sorry, having the single line works perfectly!
Back to top
View user's profile Send private message
Aryos
Smarty Rookie


Joined: 12 Jan 2010
Posts: 8

PostPosted: Thu Feb 18, 2010 2:46 pm    Post subject: Reply with quote

stayclose,
The Web developer usually "doesn't care" about HTML injection, because his main focus is on:
- Not allowing execution of code which could inject content to the SQL database.
- Not allowing execution of code which could permanently inject code to .php files, template files or any file on the website's pubic directory.
-Not allowing execution of code which could grant him access to the database.
- Not allowing execution of code which grant him access to the website's public directory.
- Not allowing execution of code which could raise permissions, in order to grant him access to any directory over the website's public directory, reaching up to the entire server root file-system or to the public directory of other users.
- Not allowing execution of code which could permanently change the permissions of files and folders, thus being able to modify or delete files and folders.
- Not allowing execution of code (eg uploading of images with "concatenated" script code), which could allow a malicious user to get information of other users, eg reading their session data or their cookies.
- Not allowing execution of code which could change the PHP code layer or the presentation layer for all users of the website, in any way.

The way you are speaking of "HTML injection" I am not quite sure by what you mean, and YES, this means I am not well-informed on this topic. What I understand is that a user may potentially be able to inject HTML code in the presentation layer, by using POST OR REQUEST data, but having this injected code being reproduced only in run-time, thus this code/exploit being visible ONLY to him and NOT affecting the presentation layer for ALL the users (thus NOT permanently injecting code to a template file or to a cached template file). In such a case, even if a user does this, this should not be able to affect the presentation nor the code layer for other users and, IF the developer has good security techniques, it would not further result in facilitating a potential SQL injection, file manipulation etc problem, since the user would not be able to get advantage by this exploit, since the back-end PHP code will take care of it. I rest my case if this could create issues on the malicious user being able to read/see sensitive data from files or from the database.
We could really use an example here, if not technical, even descriptive.
Back to top
View user's profile Send private message
mohrt
Administrator


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

PostPosted: Thu Feb 18, 2010 2:56 pm    Post subject: Reply with quote

usually the problem arises with cross-site scripting in user-submitted content, such as a public commenting system. If all of the variables are always escaped, you can be certain that no string of text in a given variable can create an scripting exploit.

You can provide a global blanketed escapement with a variable filter. Of course this could be done manually in PHP before assignment too, so it's a matter of how you decide to handle variable escapement.
Back to top
View user's profile Send private message Visit poster's website
emt
Smarty Regular


Joined: 10 Dec 2009
Posts: 43

PostPosted: Thu Feb 18, 2010 6:37 pm    Post subject: Reply with quote

You can also use HTMLPurifier with a modifier, like this:

Code:
function smarty_modifier_purify($string) {
  static $purifier;

  if (!isset($purifier)) {
    require_once('J:/wamp/www/library/HTMLPurifier.standalone.php');
    $config = HTMLPurifier_Config::createDefault();
    $config->set('Core.Encoding', 'ISO-8859-1');
    $config->set('HTML.Allowed', 'p,b,i,br,blockquote,em,li,ol,ul,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,u');
    $config->set('AutoFormat.AutoParagraph', true);
    $purifier = new HTMLPurifier($config);
  }

  return $purifier->purify($string);
}


Note you may want to change the encoding, or remove it for UTF-8. I use an opcade cache (APC) so I have a standalone version of the HTML Purifier library.

Then cleaning user input becomes as easy as using:
Code:
{$userOutput|purify}


The library is available here: http://htmlpurifier.org/
Back to top
View user's profile Send private message
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 -> Smarty 3 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