From c55c06882705604099ca8d1cd274838f42ba8761 Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Fri, 21 Dec 2012 12:19:21 +0100 Subject: [PATCH] [book, quick_tour, reference] updated documentation according to the recent CVE-2012-6431 security advisory regarding the Twig render tag and ESI management. --- book/http_cache.rst | 96 ++++++++++++++++-------------------- book/security.rst | 32 ++++++++---- book/templating.rst | 14 ++++-- quick_tour/the_view.rst | 64 +++++++++++++++++++++--- reference/twig_reference.rst | 2 +- 5 files changed, 134 insertions(+), 74 deletions(-) diff --git a/book/http_cache.rst b/book/http_cache.rst index f2f5c5e7f38..19e427b7685 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -878,17 +878,50 @@ matter), Symfony2 uses the standard ``render`` helper to configure ESI tags: .. code-block:: jinja - {% render '...:news' with {}, {'standalone': true} %} + {% render url('latest_news', { 'max': 5 }) with {}, {'standalone': true} %} .. code-block:: php - render('...:news', array(), array('standalone' => true)) ?> + render('...:news', array('max' => 5), array('standalone' => true)) ?> -By setting ``standalone`` to ``true``, you tell Symfony2 that the action -should be rendered as an ESI tag. You might be wondering why you would want to -use a helper instead of just writing the ESI tag yourself. That's because -using a helper makes your application work even if there is no gateway cache -installed. +.. note:: + + Since Symfony 2.0.20, the Twig ``render`` tag now takes an absolute url + instead of a controller logical path. This fixes an important security + issue (`CVE-2012-6431`_) reported on the official blog. If your application + uses an older version of Symfony or still uses the previous ``render`` tag + syntax, we highly advise you to upgrade as soon as possible. + +The ``render`` tag takes the absolute url of the embedded action. The latter has +to be defined somewhere in one of the application's or bundles' routing +configuration files: + +.. code-block:: yaml + + # app/config/routing.yml + latest_news: + pattern: /esi/latest-news/{max} + defaults: { _controller: AcmeNewsBundle:News:news } + requirements: { max: \d+ } + +.. tip:: + + The best practice is to mount all your ESI urls on a single prefix of your + choice. This has two main advantages. First, it eases the management of + ESI urls as you can easily identify the routes used to handle ESIs. + Secondly, it eases security management. Since an ESI route allows an action + to be accessed via a URL, you might want to protect it by using the Symfony2 + firewall feature (by allowing access to your reverse proxy's IP range). + Securing all urls starting with the same prefix is easier than securing each + single url. See the :ref:`Securing by IP` section + of the :doc:`Security Chapter ` for more information on how + to do this. + +By setting ``standalone`` to ``true`` in the ``render`` Twig tag, you tell +Symfony2 that the action should be rendered as an ESI tag. You might be +wondering why you would want to use a helper instead of just writing the ESI tag +yourself. That's because using a helper makes your application work even if +there is no gateway cache installed. When standalone is ``false`` (the default), Symfony2 merges the included page content within the main one before sending the response to the client. But @@ -909,7 +942,7 @@ of the master page. .. code-block:: php - public function newsAction() + public function newsAction($max) { // ... @@ -919,52 +952,6 @@ of the master page. With ESI, the full page cache will be valid for 600 seconds, but the news component cache will only last for 60 seconds. -A requirement of ESI, however, is that the embedded action be accessible -via a URL so the gateway cache can fetch it independently of the rest of -the page. Of course, an action can't be accessed via a URL unless it has -a route that points to it. Symfony2 takes care of this via a generic route -and controller. For the ESI include tag to work properly, you must define -the ``_internal`` route: - -.. configuration-block:: - - .. code-block:: yaml - - # app/config/routing.yml - _internal: - resource: "@FrameworkBundle/Resources/config/routing/internal.xml" - prefix: /_internal - - .. code-block:: xml - - - - - - - - - - .. code-block:: php - - // app/config/routing.php - use Symfony\Component\Routing\RouteCollection; - use Symfony\Component\Routing\Route; - - $collection->addCollection($loader->import('@FrameworkBundle/Resources/config/routing/internal.xml', '/_internal')); - - return $collection; - -.. tip:: - - Since this route allows all actions to be accessed via a URL, you might - want to protect it by using the Symfony2 firewall feature (by allowing - access to your reverse proxy's IP range). See the :ref:`Securing by IP` - section of the :doc:`Security Chapter ` for more information - on how to do this. - One great advantage of this caching strategy is that you can make your application as dynamic as needed and at the same time, hit the application as little as possible. @@ -1071,3 +1058,4 @@ Learn more from the Cookbook .. _`P4 - Conditional Requests`: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-12 .. _`P6 - Caching: Browser and intermediary caches`: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12 .. _`ESI`: http://www.w3.org/TR/esi-lang +.. _`CVE-2012-6431`: http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released diff --git a/book/security.rst b/book/security.rst index a9f5f53c9bc..a5210a41686 100644 --- a/book/security.rst +++ b/book/security.rst @@ -746,14 +746,16 @@ Securing by IP ~~~~~~~~~~~~~~ Certain situations may arise when you may need to restrict access to a given -route based on IP. This is particularly relevant in the case of :ref:`Edge Side Includes` -(ESI), for example, which utilize a route named "_internal". When -ESI is used, the _internal route is required by the gateway cache to enable -different caching options for subsections within a given page. This route -comes with the ^/_internal prefix by default in the standard edition (assuming -you've uncommented those lines from the routing file). +route based on IP. This is particularly relevant in the case of +:ref:`Edge Side Includes` (ESI), for example. When ESI is +enabled, it's recommended to secure access to ESI URLs. Indeed, some ESI may +contain some private contents like the current logged in user's information. To +prevent any direct access to these resources from a web browser by guessing the +URL pattern, the ESI route must be secured to be only visible from the trusted +reverse proxy cache. -Here is an example of how you might secure this route from outside access: +Here is an example of how you might secure all ESI routes that start with a +given prefix, ``/esi``, from outside access: .. configuration-block:: @@ -763,22 +765,31 @@ Here is an example of how you might secure this route from outside access: security: # ... access_control: - - { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } + - { path: ^/esi, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } .. code-block:: xml - + .. code-block:: php 'access_control' => array( - array('path' => '^/_internal', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'ip' => '127.0.0.1'), + array('path' => '^/esi', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'ip' => '127.0.0.1'), ), .. _book-security-securing-channel: +.. note:: + + The Symfony 2.0.20 fixes an important security issue regarding ESI + routes. In the previous versions of Symfony, ESI URLs where handled by a + single route call ``_internal`` and defined in the main + ``app/config/routing.yml`` file. If your application handles ESI with the + ``_internal`` route, we highly advise you to upgrade your code by following + the guidelines of the `CVE-2012-6431 security advisory`_. + Securing by Channel ~~~~~~~~~~~~~~~~~~~ @@ -1784,3 +1795,4 @@ Learn more from the Cookbook .. _`FOSUserBundle`: https://github.com/FriendsOfSymfony/FOSUserBundle .. _`implement the \Serializable interface`: http://php.net/manual/en/class.serializable.php .. _`functions-online.com`: http://www.functions-online.com/sha1.html +.. _`CVE-2012-6431 security advisory`: http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released diff --git a/book/templating.rst b/book/templating.rst index 5463cf7ac5f..4e8efb860b1 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -623,8 +623,7 @@ The ``recentList`` template is perfectly straightforward: (e.g. ``/article/*slug*``). This is a bad practice. In the next section, you'll learn how to do this correctly. -To include the controller, you'll need to refer to it using the standard string -syntax for controllers (i.e. **bundle**:**controller**:**action**): +To include the controller, you'll need to refer to it using an absolute url: .. configuration-block:: @@ -634,7 +633,7 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**): {# ... #} .. code-block:: html+php @@ -646,6 +645,14 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**): render('AcmeArticleBundle:Article:recentArticles', array('max' => 3)) ?> +.. note:: + + Since Symfony 2.0.20, the Twig ``render`` tag now takes an absolute url + instead of a controller logical path. This fixes an important security + issue (`CVE-2012-6431`_) reported on the official blog. If your application + uses an older version of Symfony or still uses the previous ``render`` tag + syntax, we highly advise you to upgrade as soon as possible. + Whenever you find that you need a variable or a piece of information that you don't have access to in a template, consider rendering a controller. Controllers are fast to execute and promote good code organization and reuse. @@ -1372,3 +1379,4 @@ Learn more from the Cookbook .. _`tags`: http://twig.sensiolabs.org/doc/tags/index.html .. _`filters`: http://twig.sensiolabs.org/doc/filters/index.html .. _`add your own extensions`: http://twig.sensiolabs.org/doc/advanced.html#creating-an-extension +.. _`CVE-2012-6431`: http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released diff --git a/quick_tour/the_view.rst b/quick_tour/the_view.rst index 6fb4ea22257..7dec05523ce 100644 --- a/quick_tour/the_view.rst +++ b/quick_tour/the_view.rst @@ -186,12 +186,60 @@ the ``index`` template. To do this, use the ``render`` tag: .. code-block:: jinja {# src/Acme/DemoBundle/Resources/views/Demo/index.html.twig #} - {% render "AcmeDemoBundle:Demo:fancy" with {'name': name, 'color': 'green'} %} + {% render url('fancy', { 'name': name, 'color': 'green'}) %} -Here, the ``AcmeDemoBundle:Demo:fancy`` string refers to the ``fancy`` action -of the ``Demo`` controller. The arguments (``name`` and ``color``) act like -simulated request variables (as if the ``fancyAction`` were handling a whole -new request) and are made available to the controller:: +.. note:: + + Since Symfony 2.0.20, the Twig ``render`` tag now takes an absolute url + instead of a controller logical path. This fixes an important security + issue (`CVE-2012-6431`_) reported on the official blog. If your application + uses an older version of Symfony or still uses the previous ``render`` tag + syntax, we highly advise you to upgrade as soon as possible. + +Here, the ``render`` tag takes the url of the ``fancy`` route. This route has to +be defined in one of your application's routing configuration files. + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/routing.yml + fancy: + pattern: /included/fancy/{name}/{color} + defaults: { _controller: AcmeDemoBundle:Demo:fancy } + + .. code-block:: xml + + + + + + + AcmeDemoBundle:Demo:fancy + + + + .. code-block:: php + + // app/config/routing.php + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + $collection->add('fancy', new Route('/included/fancy/{name}/{color}', array( + '_controller' => 'AcmeDemoBundle:Demo:fancy', + ))); + + return $collection; + + +The ``fancy`` route maps the ``/included/fancy/{name}/{color}`` pattern to a +``fancyAction`` method in the ``DemoController`` class of an ``AcmeDemoBundle`` +bundle. The arguments (``name`` and ``color``) act like simulated request +variables (as if the ``fancyAction`` were handling a whole new request) and are +made available to the controller:: // src/Acme/DemoBundle/Controller/DemoController.php @@ -202,7 +250,10 @@ new request) and are made available to the controller:: // create some object, based on the $color variable $object = ...; - return $this->render('AcmeDemoBundle:Demo:fancy.html.twig', array('name' => $name, 'object' => $object)); + return $this->render('AcmeDemoBundle:Demo:fancy.html.twig', array( + 'name' => $name, + 'object' => $object + )); } // ... @@ -288,3 +339,4 @@ Ready for another 10 minutes with Symfony2? .. _Twig: http://twig.sensiolabs.org/ .. _documentation: http://twig.sensiolabs.org/documentation +.. _`CVE-2012-6431`: http://symfony.com/blog/security-release-symfony-2-0-20-and-2-1-5-released diff --git a/reference/twig_reference.rst b/reference/twig_reference.rst index a662d98e8ea..1a3d6222666 100644 --- a/reference/twig_reference.rst +++ b/reference/twig_reference.rst @@ -101,7 +101,7 @@ Tags +---------------------------------------------------+-------------------------------------------------------------------+ | Tag Syntax | Usage | +===================================================+===================================================================+ -| ``{% render 'controller' with {parameters} %}`` | This will render the Response Content for the given controller, | +| ``{% render url('route', {parameters}) %}`` | This will render the Response Content for the given controller, | | | more information in :ref:`templating-embedding-controller`. | +---------------------------------------------------+-------------------------------------------------------------------+ | ``{% form_theme form 'file' %}`` | This will look inside the given file for overridden form blocks, |