I've always been interested in writing web software like forums or blogs, things which take a limited markup to rewrite into HTML. But lately, I've noticed more and more that for PHP, try googling "PHP BBCode parser -PEAR" and test a few out, you either get an inefficient mess, or you get poor code with XSS holes here and there.
Taking my previously mentioned example, of the poor BBCode parsers out there, how would you avoid XSS? I'll now take your typical regular expression for handling a link, and you can mention how vulnerable it is and how to avoid it.
// Assume input has already been encoded by htmlspecialchars with ENT_QUOTES
$text = preg_replace('#\[url\](.*?)\[/url\]#i','<a href="\1">\1</a>', $text);
$text = preg_replace('#\[url=(.*?)\](.*?)\[/url\]#i','<a href="\1">\2</a>', $text);
Handling image tags are hardly more secure than this.
So I have several specific questions, mostly specific to PHP implementations.
- Is it better practice, in this example, to only match using a uri/url validation expression? Or, is it better to use
(.*?)
and a callback, then ascertain whether or not the input is a valid link? As would be obvious above, thejavascript:alert('XSS!')
would work in the above URL tags, but would fail if the uri-matching was done. - What about functions like
urlencode()
within a callback, would they be any deterrence or problem (as far as URI standards go)? - Would it be safer to write a full-stack parser? Or, is the time and processing power needed to develop and use such a thing too weighty for something handling several different entries per page?
I know my example is one of many, and is more specific than some. However, don't shirk from providing your own. So, I'm looking for principles and best practices, and general recommendations for XSS-protection in a text-parsing situation.