34
votes

I need my users to enter the URI of their personal website in their profile so that other users can see and click on it. I am worried that this could lead to XSS attacks if the output is not sanitized properly.

Like in this very simplistic schema below:


enter image description here


I am using the full stack symfony2 framework, Doctrine as ORM and Twig as a template engine. I know that Symfony provides some amazing Validation tools, and that TWIG provides automatic output escaping (which is not necessary in this particular case) as well as some filters for output sanitizing.

I've read the following about how symfony2 and twig handle sanitization:

Doctrine comes with sanitization for database (SQL) injections. Apart from this, there is no recommended / provided input sanitization at controller level in Symfony2. However, using Twig in the view, output sanitization is available.

As an example, in CakePHP however:

Data sanitization is implemented as a Utility which can be accessed from anywhere (controller, component, model .. even view). It follows a sanitize-all-input approach with a fixed set of predefined sanitization filters. Sanitizing specific inputs with dedicated rules is possible, but seems not to be encouraged.The existing rules concentrate on SQL and HTML injections and filtering out general suspicious unicode characters.

1 How do symfony2 + twig users handle input sanitization? Do they discard input sanitization totally and for example rely on validation only? Or do they write their own utility function to filter user inputs? or maybe use a library like owasp-esapi-php?

2 How do symfony2 + twig users handle output sanitization? Do they rely on the filters provided by the twig engine only? For example, are there already any tools that one can use to sanitize a user-entered URI, something similar to this?

3 In this situarion, how would you handle database storage and display of a user-entered URI like in the example above, would you care about input sanitization at all? or would you use output sanitization only and store the URI as is?

4
Maybe I don't get it right but in the cakephp doc, it is written that: For sanitization against XSS it’s generally better to save raw HTML in database without modification and sanitize at the time of output/display. So you should save the input as it is. You can then use a twig filter to prevent XSS attacks. Id do believe {{ user.website|e('url') }} would do the job. If not, it is always possible to create a new filter.cheesemacfly
One of the ways is to make a request(example with curl) to the inputed url passed through the Url validator. If successful, you can display this address, or escape it and output as text.Alexey B.
After a little research, I believe it all comes down to CakePHP using htmlentities vs symfony/twig using htmlspecialchars, so I am not sure if the CakePHP example was really relevant here.cheesemacfly
That's very nice to open a bounty @rufinus! Thanks!Mick
im very intrested in the answer. currently it seems the favored method is output sanitzing.. but to be honest i see no point in storing potential dangerous JS code in my Database, only to filter it out when outputing. this makes just no sense.Rufinus

4 Answers

3
votes
  1. You should not worry at all about input sanitization, Doctrine is immune to sql injection

  2. By default, all output is escaped. So even if $text has script tags, it will be escaped; visible as text but not executed by browser. And if you want to have http://example.com clickable, there are jquery plugins that can do that for you.

  3. I would only put validation, there is

    new Symfony\Component\Validator\Constraints\Url() ;
    

available for you

3
votes

There is also a nice symfony2 bundle that allow users to implement input filtering in entities using Annotations. Like this :

/**
* @Filter\StripTags()
* @Filter\Trim()
* @Filter\StripNewlines()
*
* @var string
*/
public $email;

The bundle : dms-filter-bundle

0
votes

I think Symfony and CakePHP are frameworks and the save process can't correctly know the input context and what it will save into DB. Developer knowns the context, if it's URL, HTML, SQL, etc, , even when outputting data, so output sanitization is often chosen, and if the developer wants to implement input sanitization, he always can and uses some existing tools.

You can use HTML Purifier to "purify" all user inputs.

https://github.com/Exercise/HTMLPurifierBundle

0
votes

Using the form validators provided by Symfony verifies the integrity of the data supplied to your application's database.

You should consider adding a test for a url-pattern, there are various

Other users already pointed out you are safe against various attax using components (csrf, type/property validation (symfony-form), sql-injection(Doctrine) and xss (twig) and of course various access authentification)

So for the specific attack you ask about it is necessary for bad user to submit a script-tag and some poor user get this displayed and executed, you could easily avoid getting this into your application with a simple regex of them

preg_replace('/(<' .'script'. '>)(.*)(</' .'script'. '>)/g', '', $text);

So i think it is safe not to rely on the sanitation of the output, there are many reasons, for example you do not use twig because your application is endpoint driven or for some reason you need to call |raw filter on text fields or maybe you dont even have influence on the display because thirds are displaying the data each on their way.