Vulnerability: Server Side Twig Template Injection PrestaShop is an Open Source e-commerce platform. Starting with version 1.7.0.0 and ending with version 1.7.8.3, an attacker is able to inject twig code inside the back office when using the legacy layout. The problem is fixed in version 1.7.8.3. There are no known workarounds.
Vulnerability ID: GHSA-mrq4-7ch7-2465
CWE: CWE-94
Severity score: 9
Project: https://github.com/PrestaShop/PrestaShop
Published: 2022-01-27
File: src/PrestaShopBundle/Twig/LayoutExtension.php
Commit message: Merge pull request from GHSA-mrq4-7ch7-2465

Properly escape smarty output for twig
Commit author: GoT

Vulnerable version (before fix):
 public function getLegacyLayout(             throw new Exception('PrestaShopBundle\Twig\LayoutExtension cannot find the {$content} string in legacy layout template', 1);         }          $content = str_replace(             [                 '{$content}',                 'var currentIndex = \'index.php\';',                 '</head>',                 '</body>',             ],             [                 '{% block content_header %}{% endblock %}                  {% block content %}{% endblock %}                  {% block content_footer %}{% endblock %}                  {% block sidebar_right %}{% endblock %}',                 'var currentIndex = \'' . $this->context->getAdminLink($controllerName) . '\';',                 '{% block stylesheets %}{% endblock %}{% block extra_stylesheets %}{% endblock %}</head>',                 '{% block javascripts %}{% endblock %}{% block extra_javascripts %}{% endblock %}{% block translate_javascripts %}{% endblock %}</body>',             ],             $layout         );          return $content;     }      /**

Fixed version (after fix):
 public function getLegacyLayout(             throw new Exception('PrestaShopBundle\Twig\LayoutExtension cannot find the {$content} string in legacy layout template', 1);         }          $explodedLayout = explode('{$content}', $layout);         $header = explode('</head>', $explodedLayout[0]);         $footer = explode('</body>', $explodedLayout[1]);          return $this->escapeSmarty(str_replace('var currentIndex = \'index.php\';', 'var currentIndex = \'' . $this->context->getAdminLink($controllerName) . '\';', $header[0]))             . '{% block stylesheets %}{% endblock %}{% block extra_stylesheets %}{% endblock %}</head>'             . $this->escapeSmarty($header[1])             . '{% block content_header %}{% endblock %}'             . '{% block content %}{% endblock %}'             . '{% block content_footer %}{% endblock %}'             . '{% block sidebar_right %}{% endblock %}'             . $this->escapeSmarty($footer[0])             . '{% block javascripts %}{% endblock %}{% block extra_javascripts %}{% endblock %}{% block translate_javascripts %}{% endblock %}</body>'             . $this->escapeSmarty($footer[1]);     }      private function escapeSmarty(string $template): string     {         return '{{ \'' . addslashes($template) . '\' | raw }}';     }      /**

Patch:
patch: @@ -218,26 +218,25 @@ public function getLegacyLayout(
             throw new Exception('PrestaShopBundle\Twig\LayoutExtension cannot find the {$content} string in legacy layout template', 1);
         }
 
-        $content = str_replace(
-            [
-                '{$content}',
-                'var currentIndex = \'index.php\';',
-                '</head>',
-                '</body>',
-            ],
-            [
-                '{% block content_header %}{% endblock %}
-                 {% block content %}{% endblock %}
-                 {% block content_footer %}{% endblock %}
-                 {% block sidebar_right %}{% endblock %}',
-                'var currentIndex = \'' . $this->context->getAdminLink($controllerName) . '\';',
-                '{% block stylesheets %}{% endblock %}{% block extra_stylesheets %}{% endblock %}</head>',
-                '{% block javascripts %}{% endblock %}{% block extra_javascripts %}{% endblock %}{% block translate_javascripts %}{% endblock %}</body>',
-            ],
-            $layout
-        );
+        $explodedLayout = explode('{$content}', $layout);
+        $header = explode('</head>', $explodedLayout[0]);
+        $footer = explode('</body>', $explodedLayout[1]);
+
+        return $this->escapeSmarty(str_replace('var currentIndex = \'index.php\';', 'var currentIndex = \'' . $this->context->getAdminLink($controllerName) . '\';', $header[0]))
+            . '{% block stylesheets %}{% endblock %}{% block extra_stylesheets %}{% endblock %}</head>'
+            . $this->escapeSmarty($header[1])
+            . '{% block content_header %}{% endblock %}'
+            . '{% block content %}{% endblock %}'
+            . '{% block content_footer %}{% endblock %}'
+            . '{% block sidebar_right %}{% endblock %}'
+            . $this->escapeSmarty($footer[0])
+            . '{% block javascripts %}{% endblock %}{% block extra_javascripts %}{% endblock %}{% block translate_javascripts %}{% endblock %}</body>'
+            . $this->escapeSmarty($footer[1]);
+    }
 
-        return $content;
+    private function escapeSmarty(string $template): string
+    {
+        return '{{ \'' . addslashes($template) . '\' | raw }}';
     }
 
     /**
path: src/PrestaShopBundle/Twig/LayoutExtension.php