FIEO with PHP 5 Interceptors

Note: Before getting into this, it may be easier to just download the file, run the code, then read this post.

Thanks to the efforts of Chris Shiflett and other PHP security experts, Filter Input/Escape Output (FIEO) is now a commonplace technique to increase web application security.

The idea itself is simple. When data comes into your application, it must be filtered prior to it actually being used for any reason. This means all data. Form values, URL values, and yes, even the values in the forever useful $_SERVER superglobal. If you expect an integer, cast it as such. Maybe you are expecting plain text, anything that looks like HTML should obviously be removed. Whitelists also apply here, too.

Before leaving your application, data should be properly escaped with the specific output medium in mind. For example, if you are passing it off to a MySQL database, make sure quotes (or any other tricky character) is prefixed with a slash. Another example would be if you are rendering data out to a web page, htmlentities() (or something similar) should be used to transform html-specific characters into their proper entities.

In my last post I showed how PHP 5′s interceptor methods can be used to build collections of data. That same technique can be applied to FIEO. This is what it looks like implemented:

[code lang="php"] 'Someone & Someone Else',
    'content' => 'Someone said to someone else, "Hello, World!"'
);

$sampleContexts = array(
    'html' => 'MikeG_HtmlFilter',
    'sql' => 'MikeG_SqlFilter'
);

$Filter = new Panda_DataFilter($sampleData, $sampleContexts);
$Filter->html->setCharset('ISO-8859-1');

?>

html->title ?>

html->content ?> sql->content ?> [/code]

And the output is:

[code]
<h1>Someone &amp; Someone Else</h1>
<p>Someone said to someone else, &quot;Hello, World!&quot;</p>
<p>Someone said to someone else, "Hello, World!"</p>
[/code]

Pretty neat huh? I think so too.

The idea is simple: Instances of Panda_DataFilter contains the tainted data. You load contexts into Panda_DataFilter and they govern the input and output of the tainted data. In the example above, I output data using the html and sql contexts. Whenever you set a variable inside of one of the loaded contexts, __set will intercept the assignment operation and run it’s specific input filtering routine. Likewise, whenver you read a value from one of the contexts, __get intercepts the retrieval operation and runs its specific output escaping routine.

Here’s the actual code:

[code lang="php"]data = $data;

        foreach ($contexts as $contextName => $context) {
            $this->{$contextName} = new $context($this->data);
        }
    }
}

abstract class Panda_DataFilter_Context
{
    protected $data = array();

    public function __construct(array $data)
    {
        foreach ($data as $key => $value) {
            $this->{$key} = $value;
        }
    }

    abstract public function __get($name);
    abstract public function __set($name, $value);
}

?>[/code]

And the html and sql contexts:

[code lang="php"]data[$name], $this->quotes, $this->charset);
    }

    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }

    public function setCharset($charset)
    {
        $this->charset = $charset;
    }

    public function setQuoteStyle($quoteStyle)
    {
        $this->quotes = $quoteStyle;
    }
}

class MikeG_SqlFilter extends Panda_DataFilter_Context
{
    public function __get($name)
    {
        return mysql_escape_string($this->data[$name]);
    }

    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }
}

?>[/code]

Hopefully someone finds this useful :)

This entry was posted in Code, Design Patterns, PHP. Bookmark the permalink.

8 Responses to FIEO with PHP 5 Interceptors

  1. Pingback: PHPDeveloper.org

  2. Pingback: developercast.com » Michael Girouard’s Blog: FIEO with PHP 5 Interceptors

  3. daaku says:

    Current versions of PHP (>5.2.0) have the filter extension: http://php.net/filter – it only deals with input, and htmlentities can be used for output.

  4. Pingback: Pro::PHP Newscast (Nov 8, 2007) | PHP Podcasts

  5. Pingback: Michael Girouard’s Blog: FIEO with PHP 5 Interceptors | MT-Soft Website Development

  6. Pingback: Rolling Your Own MVC: The Page Load Scenario :: Love Mike G.

  7. James Morris says:

    This is a nice little method of filtering – I will be refering to it most likely in the future, cheers for the post.

  8. Current versions of PHP (>5.2.0) have the filter extension: http://php.net/filter – it only deals with input, and htmlentities can be used for output.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>