strip_tags not a complete protection against XSS” was originally written by Dan Guido when he was a student in the ISIS Lab.
On August 13th .mario, a high-profile member of the sla.ckers.org forum, alerted me to a XSS issue on the CSAW registration form. I had previously looked through the code and concluded it was safe based on this block of filtering code included at the top of the page:
Additionally, the registration script limits sources of user controllable input by only ever using the POST and COOKIE superglobals.
This script eliminates potential SQL injections by calling mysqli_real_escape_string on all user input. The *_real_escape_string functions in PHP are the only safe way to prevent SQL injection attacks as there are ways to sneak attacks by the [deprecated] *_escape_string and addslashes functions, for example, with different character encodings.
" onwhatever=alert(1) a="
I asked .mario if he would be kind enough to provide us with a proof of concept that would work specifically in the context of the CSAW registration page. He did not disappoint and PM’d me the following attack string:
** This has been URL decoded. ** For the original, please see http://preview.tinyurl.com/csawxss
After verifying the PoC, I made a small addition to our filtering script to prevent this attack by adding an htmlentities function call to each iteration of the two loops. This isn’t the best solution as it escapes input more than is necessary and I didn’t have a chance to bug test it much at all. A better solution can be found in the same sla.ckers.org forum post I found the attack string in:
…the best practice is IMHO: Input -> Validate -> Filter (CRLF, Ctrl-Chars) -> Escape -> Store -> Encode (Just the characters you need to encode) -> Output Validation can be done via type check or regex, for filtering the ord() method does a great job, escaping is done by mysql_(real)_escape_string() and encoding is done by correctly parametrized htmlentities().
We’ll be looking into ways to rewrite our filtering script according to this advice, and also at PHP-IDS, as a way to prevent these types of issues in the future.
EDIT 08/17/2008: I incorrectly attributed the name.xss bridge to mario. It is actually the creation of Giorgio Maone.