Sun, 11 Mar 2007


Since PHP 5.2.0 there is a new filtering extension in PHP that is on the one hand supposed to be used by applications to filter user input and on the other hand able to enforce site wide filtering.

When the FILTER_SANITIZE_STRING filter is used in combination with the flag FILTER_FLAG_STRIP_LOW it is possible to bypass the HTML tag filtering by placing a low ASCII whitspace char after the HTML tag opening bracket.

Affected versions

Affected is PHP 5.2.0

Detailed information

The FILTER_SANITIZE_STRING filter of ext/filter violates one simple rule: If you want to strip out multiple different entities from another string you must either ensure that stripping is performed in an order that one stripping operation cannot influence the result of the next ones or the stripping must be repeated until nothing is replaced anymore.

In ext/filter first HTML tags are stripped from the input with the exception that opening tag brackets followed by whitespace characters are not stripped. They are considered safe to not be stripped.

The tag stripping is followed by a low ASCII char stripping process. Because several whitespace characters are below ASCII value 32, they also will get stripped from the input when FILTER_FLAG_STRIP_LOW is selected, which will repair invalid tags that were not stripped. This completely bypasses the whole HTML tag stripping.

Proof of concept, exploit or instructions to reproduce

To reproduce the problem save the following example code and call it with something like var=<%0bscript>alert(/XSS/);<%0b/script>

  $var = filter_input(INPUT_GET, "var", FILTER_SANITIZE_STRING,
                      array("flags" => FILTER_FLAG_STRIP_LOW));
  echo $var;

When you are running one of the vulnerable ext/filter versions this will result in an XSS vulnerability.


This bug shows one of the weaknesses behind the ext/filter idea. Whenever there is a bug in the filter implementation all applications that make use of it are vulnerable and can only be fixed by upgrading the PHP version (because the filter extension is static by default). However new PHP versions do not come out that often and therefore applications might be exposed to those problems for months.

It is our believe that input filtering (and input validation and output escaping) belongs into user space libraries where they can be fixed without the trouble of recompiling PHP. Later in 2007 the Hardened-PHP Project is planning to host the development of such libraries.