Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock

Please unblock package symfony

It cherry-picks to security fixes from upstrem:

symfony (2.3.21+dfsg-4) unstable; urgency=medium

  * Backport security fixes from 2.3.27:
    - Esi Code Injection [CVE-2015-2308]
    - Unsafe methods in the Request class [CVE-2015-2309]

 -- David Prévot <taf...@debian.org>  Wed, 01 Apr 2015 16:53:00 -0400

unblock symfony/2.3.21+dfsg-4

Thanks in advance.

Regards

David
diff -Nru symfony-2.3.21+dfsg/debian/changelog symfony-2.3.21+dfsg/debian/changelog
--- symfony-2.3.21+dfsg/debian/changelog	2015-01-30 09:22:17.000000000 -0400
+++ symfony-2.3.21+dfsg/debian/changelog	2015-04-01 16:53:36.000000000 -0400
@@ -1,3 +1,11 @@
+symfony (2.3.21+dfsg-4) unstable; urgency=medium
+
+  * Backport security fixes from 2.3.27:
+    - Esi Code Injection [CVE-2015-2308]
+    - Unsafe methods in the Request class [CVE-2015-2309]
+
+ -- David Prévot <taf...@debian.org>  Wed, 01 Apr 2015 16:53:00 -0400
+
 symfony (2.3.21+dfsg-3) unstable; urgency=medium
 
   [ Daniel Beyer ]
diff -Nru symfony-2.3.21+dfsg/debian/patches/0007-isFromTrustedProxy-to-confirm-request-came-from-a-tr.patch symfony-2.3.21+dfsg/debian/patches/0007-isFromTrustedProxy-to-confirm-request-came-from-a-tr.patch
--- symfony-2.3.21+dfsg/debian/patches/0007-isFromTrustedProxy-to-confirm-request-came-from-a-tr.patch	1969-12-31 20:00:00.000000000 -0400
+++ symfony-2.3.21+dfsg/debian/patches/0007-isFromTrustedProxy-to-confirm-request-came-from-a-tr.patch	2015-04-01 16:44:25.000000000 -0400
@@ -0,0 +1,140 @@
+From: James Gilliland <jgillil...@apqc.org>
+Date: Tue, 17 Feb 2015 11:56:59 -0600
+Subject: isFromTrustedProxy to confirm request came from a trusted proxy.
+
+Origin: upstream, https://github.com/symfony/symfony/commit/6c73f0ce9302a0091bbfbb96f317e400ce16ef84
+---
+ src/Symfony/Component/HttpFoundation/Request.php   | 13 +++++---
+ .../Component/HttpFoundation/Tests/RequestTest.php | 38 ++++++++++++++--------
+ 2 files changed, 34 insertions(+), 17 deletions(-)
+
+diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php
+index 9fd02cc..00fdbc4 100644
+--- a/src/Symfony/Component/HttpFoundation/Request.php
++++ b/src/Symfony/Component/HttpFoundation/Request.php
+@@ -763,7 +763,7 @@ class Request
+     {
+         $ip = $this->server->get('REMOTE_ADDR');
+ 
+-        if (!self::$trustedProxies) {
++        if (!$this->isFromTrustedProxy()) {
+             return array($ip);
+         }
+ 
+@@ -924,7 +924,7 @@ class Request
+      */
+     public function getPort()
+     {
+-        if (self::$trustedProxies) {
++        if ($this->isFromTrustedProxy()) {
+             if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && $port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT])) {
+                 return $port;
+             }
+@@ -1105,7 +1105,7 @@ class Request
+      */
+     public function isSecure()
+     {
+-        if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
++        if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
+             return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
+         }
+ 
+@@ -1133,7 +1133,7 @@ class Request
+      */
+     public function getHost()
+     {
+-        if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
++        if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && $host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST])) {
+             $elements = explode(',', $host);
+ 
+             $host = $elements[count($elements) - 1];
+@@ -1819,4 +1819,9 @@ class Request
+ 
+         return false;
+     }
++
++    private function isFromTrustedProxy()
++    {
++        return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies);
++    }
+ }
+diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
+index 6059969..e57f702 100644
+--- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
++++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
+@@ -707,35 +707,37 @@ class RequestTest extends \PHPUnit_Framework_TestCase
+             'HTTP_X_FORWARDED_PROTO' => 'https',
+             'HTTP_X_FORWARDED_PORT'  => '8443',
+         ));
+-        $port = $request->getPort();
+-
+-        $this->assertEquals(8443, $port, 'With PROTO and PORT set PORT takes precedence.');
++        $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.');
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
++        $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.');
+ 
+         $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
+             'HTTP_X_FORWARDED_PROTO' => 'https',
+         ));
+-        $port = $request->getPort();
+-
+-        $this->assertEquals(443, $port, 'With only PROTO set getPort() defaults to 443.');
++        $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.');
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
++        $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.');
+ 
+         $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
+             'HTTP_X_FORWARDED_PROTO' => 'http',
+         ));
+-        $port = $request->getPort();
+-
+-        $this->assertEquals(80, $port, 'If X_FORWARDED_PROTO is set to HTTP return 80.');
++        $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.');
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
++        $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.');
+ 
+         $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
+             'HTTP_X_FORWARDED_PROTO' => 'On',
+         ));
+-        $port = $request->getPort();
+-        $this->assertEquals(443, $port, 'With only PROTO set and value is On, getPort() defaults to 443.');
++        $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.');
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
++        $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.');
+ 
+         $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
+             'HTTP_X_FORWARDED_PROTO' => '1',
+         ));
+-        $port = $request->getPort();
+-        $this->assertEquals(443, $port, 'With only PROTO set and value is 1, getPort() defaults to 443.');
++        $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.');
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
++        $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.');
+ 
+         $request = Request::create('http://example.com', 'GET', array(), array(), array(), array(
+             'HTTP_X_FORWARDED_PROTO' => 'something-else',
+@@ -1002,6 +1004,8 @@ class RequestTest extends \PHPUnit_Framework_TestCase
+         $request->headers->set('X_FORWARDED_PROTO', 'https');
+ 
+         Request::setTrustedProxies(array('1.1.1.1'));
++        $this->assertFalse($request->isSecure());
++        $request->server->set('REMOTE_ADDR', '1.1.1.1');
+         $this->assertTrue($request->isSecure());
+         Request::setTrustedProxies(array());
+ 
+@@ -1437,7 +1441,15 @@ class RequestTest extends \PHPUnit_Framework_TestCase
+         $this->assertEquals(443, $request->getPort());
+         $this->assertTrue($request->isSecure());
+ 
++        // trusted proxy via setTrustedProxies()
++        Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'));
++        $this->assertEquals('3.3.3.3', $request->getClientIp());
++        $this->assertEquals('example.com', $request->getHost());
++        $this->assertEquals(80, $request->getPort());
++        $this->assertFalse($request->isSecure());
++
+         // check various X_FORWARDED_PROTO header values
++        Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'));
+         $request->headers->set('X_FORWARDED_PROTO', 'ssl');
+         $this->assertTrue($request->isSecure());
+ 
diff -Nru symfony-2.3.21+dfsg/debian/patches/0008-Safe-escaping-of-fragments-for-eval.patch symfony-2.3.21+dfsg/debian/patches/0008-Safe-escaping-of-fragments-for-eval.patch
--- symfony-2.3.21+dfsg/debian/patches/0008-Safe-escaping-of-fragments-for-eval.patch	1969-12-31 20:00:00.000000000 -0400
+++ symfony-2.3.21+dfsg/debian/patches/0008-Safe-escaping-of-fragments-for-eval.patch	2015-04-01 16:44:25.000000000 -0400
@@ -0,0 +1,113 @@
+From: Nicolas Grekas <nicolas.gre...@gmail.com>
+Date: Mon, 16 Mar 2015 15:12:02 +0100
+Subject: Safe escaping of fragments for eval()
+
+https://github.com/symfony/symfony/commit/195c57e1f50765aff33137689b16e126a689056a
+---
+ src/Symfony/Component/HttpKernel/HttpCache/Esi.php | 62 +++++++++++-----------
+ .../HttpKernel/Tests/HttpCache/EsiTest.php         |  4 +-
+ 2 files changed, 33 insertions(+), 33 deletions(-)
+
+diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
+index 9dd99d6..ad63267 100644
+--- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
++++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php
+@@ -29,6 +29,10 @@ use Symfony\Component\HttpKernel\HttpKernelInterface;
+ class Esi
+ {
+     private $contentTypes;
++    private $phpEscapeMap = array(
++        array('<?', '<%', '<s', '<S'),
++        array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
++    );
+ 
+     /**
+      * Constructor.
+@@ -158,10 +162,34 @@ class Esi
+ 
+         // we don't use a proper XML parser here as we can have ESI tags in a plain text response
+         $content = $response->getContent();
+-        $content = str_replace(array('<?', '<%'), array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>'), $content);
+-        $content = preg_replace_callback('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', array($this, 'handleEsiIncludeTag'), $content);
+-        $content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
+         $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#', '', $content);
++        $content = preg_replace('#<esi\:comment[^>]*(?:/|</esi\:comment)>#', '', $content);
++
++        $chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
++        $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
++
++        $i = 1;
++        while (isset($chunks[$i])) {
++            $options = array();
++            preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
++            foreach ($matches as $set) {
++                $options[$set[1]] = $set[2];
++            }
++
++            if (!isset($options['src'])) {
++                throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
++            }
++
++            $chunks[$i] = sprintf('<?php echo $this->esi->handle($this, %s, %s, %s) ?>'."\n",
++                var_export($options['src'], true),
++                var_export(isset($options['alt']) ? $options['alt'] : '', true),
++                isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
++            );
++            ++$i;
++            $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
++            ++$i;
++        }
++        $content = implode('', $chunks);
+ 
+         $response->setContent($content);
+         $response->headers->set('X-Body-Eval', 'ESI');
+@@ -214,32 +242,4 @@ class Esi
+             }
+         }
+     }
+-
+-    /**
+-     * Handles an ESI include tag (called internally).
+-     *
+-     * @param array $attributes An array containing the attributes.
+-     *
+-     * @return string The response content for the include.
+-     *
+-     * @throws \RuntimeException
+-     */
+-    private function handleEsiIncludeTag($attributes)
+-    {
+-        $options = array();
+-        preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $attributes[1], $matches, PREG_SET_ORDER);
+-        foreach ($matches as $set) {
+-            $options[$set[1]] = $set[2];
+-        }
+-
+-        if (!isset($options['src'])) {
+-            throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
+-        }
+-
+-        return sprintf('<?php echo $this->esi->handle($this, %s, %s, %s) ?>'."\n",
+-            var_export($options['src'], true),
+-            var_export(isset($options['alt']) ? $options['alt'] : '', true),
+-            isset($options['onerror']) && 'continue' == $options['onerror'] ? 'true' : 'false'
+-        );
+-    }
+ }
+diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
+index 23e256e..8ab3d47 100644
+--- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
++++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/EsiTest.php
+@@ -131,10 +131,10 @@ class EsiTest extends \PHPUnit_Framework_TestCase
+         $esi = new Esi();
+ 
+         $request = Request::create('/');
+-        $response = new Response('foo <?php die("foo"); ?><%= "lala" %>');
++        $response = new Response('<?php <? <% <script language=php>');
+         $esi->process($request, $response);
+ 
+-        $this->assertEquals('foo <?php echo "<?"; ?>php die("foo"); ?><?php echo "<%"; ?>= "lala" %>', $response->getContent());
++        $this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent());
+     }
+ 
+     /**
diff -Nru symfony-2.3.21+dfsg/debian/patches/series symfony-2.3.21+dfsg/debian/patches/series
--- symfony-2.3.21+dfsg/debian/patches/series	2015-01-30 09:17:03.000000000 -0400
+++ symfony-2.3.21+dfsg/debian/patches/series	2015-04-01 16:44:25.000000000 -0400
@@ -4,3 +4,5 @@
 0004-Add-more-tests-to-group-tty.patch
 0005-Process-Make-test-AbstractProcessTest-testStartAfter.patch
 0006-Increasing-timeout-in-test-AbstractProcessTest-testS.patch
+0007-isFromTrustedProxy-to-confirm-request-came-from-a-tr.patch
+0008-Safe-escaping-of-fragments-for-eval.patch

Attachment: signature.asc
Description: Digital signature

Reply via email to