A better XSS trap (Feedback wanted)
| From: | Christopher Vogt | Date: | Thu, 28 Aug 2008 21:14:37 +0000 |
| Subject: | A better XSS trap (Feedback wanted) | ||
| Groups: | php.general | ||
| Request: | Send a blank email to php-general+get-278921@lists.php.net to get a copy of this message | ||
Hej everybody,
I built something I'd like to have feedback on. Looking at all the
template engines out there made me think.
I have two main requirements:
- use PHP as the template language
- effective XSS prevention without betting on discipline
Plain PHP only satisfies the first. I also couldn't find a PHP template
engine that satisfies both. (Savant doesn't.)
So here is my own minimal solution and I would like to know your
opinion. Also, if anybody has seen something like it out there, please
point me to it.
The Idea:
Automatically wrap every output string into a Decorator object, which
offers filtering methods like htmlentities. This also means intercepting
access to strings contained in Arrays and Objects in order to decorate them.
The code:
http://code.google.com/p/cvphplib/source/browse/trunk/cvphplib/
svn checkout http://cvphplib.googlecode.com/svn/trunk/cvphplib/
Example usage:
// first a simple string
<? $string = CV_OutputFilter::filter( '<marquee>evil</marquee>' ); ?>
<?=$string?> triggers an error
<?=$string->htmlentities()?> works fine
<?=$string->urlencode()?> works fine
<?=$string->raw()?> outputs the unfiltered value
// extracting a bunch of filtered variables into the local scope
<?php
$vars = array( 'x'=>5, 'o'=>new O(), 'array' =>
array('<i>'=>'<b>') );
extract( CV_OutputFilter::filter($vars)->toArray() );
?>
// access to object members
<?=$o->var?> triggers an error
<?=$o->method()?> triggers an error
<?=$o->var->htmlentities()?> works fine
<?=$o->method()->htmlentities()?> works fine
// access to array elements
<?=$array['<i>']?> triggers an error
<?=$array['<i>']->htmlentities()?> works fine
// Iterating over an array
<? foreach( $array as $value ){} ?> works fine
<? foreach( $array as $key => $value ){} ?> throws an exception, because
$key would not be filtered in this case
// decorating array keys requires some iterator magic
<? foreach( $array->key_as($key) as $value ): ?>
<?=$key->htmlentities()?>: <?=$value->htmlentities()?> <br/>
<? endforeach; ?>
Problems:
- potentially slow (due to many object instantiations and reflection)
Benefits:
- effective XSS prevention without betting on discipline
- template-engine-like variable extraction into local scope
- clean and short syntax
- very little to learn
Functionality already implemented, but not shown in the example:
- register custom filter methods
- enable __toString() with custom default filter
- use tuple array(key,value) for $value instead of 'key_as'-magic
- register custom filter applied on keys in ->toArray()
- decoration of multidimensional arrays and webs of object references
More example code:
http://code.google.com/p/cvphplib/source/browse/trunk/cvphplib/examples/exampleOutputFilter.php
http://code.google.com/p/cvphplib/source/browse/trunk/cvphplib/tests/CV/Test_OutputFilter.php
So what do you think?
Best regards
Christopher