[SECURITY] Validate complete referring request
[Packages/TYPO3.CMS.git] / typo3 / sysext / fluid / Classes / ViewHelpers / FormViewHelper.php
index a0ad3e4..ea757f5 100644 (file)
@@ -71,6 +71,11 @@ class FormViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewH
      */
     protected $formActionUriArguments;
 
+    /**
+     * @var bool
+     */
+    private $securedReferrerFieldRendered = false;
+
     /**
      * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService
      */
@@ -159,6 +164,7 @@ class FormViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewH
         $content .= $this->renderHiddenIdentityField($this->arguments['object'], $this->getFormObjectName());
         $content .= $this->renderAdditionalIdentityFields();
         $content .= $this->renderHiddenReferrerFields();
+        $content .= $this->renderHiddenSecuredReferrerField();
 
         // Render the trusted list of all properties after everything else has been rendered
         $content .= $this->renderTrustedPropertiesField();
@@ -232,7 +238,38 @@ class FormViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormViewH
         $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@controller]') . '" value="' . $controllerName . '" />' . LF;
         $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@action]') . '" value="' . $actionName . '" />' . LF;
         $result .= '<input type="hidden" name="' . $this->prefixFieldName('__referrer[arguments]') . '" value="' . htmlspecialchars($this->hashService->appendHmac(base64_encode(serialize($request->getArguments())))) . '" />' . LF;
+        $result .= $this->renderHiddenSecuredReferrerField();
+
+        return $result;
+    }
 
+    /**
+     * Renders hidden form field for secured referrer information about the current controller and action.
+     *
+     * This method is called twice, to deal with subclasses of this class in a most compatible way
+     *
+     * @return string Hidden field with secured referrer information
+     */
+    protected function renderHiddenSecuredReferrerField()
+    {
+        if ($this->securedReferrerFieldRendered) {
+            return '';
+        }
+        $request = $this->renderingContext->getControllerContext()->getRequest();
+        $extensionName = $request->getControllerExtensionName();
+        $vendorName = $request->getControllerVendorName();
+        $controllerName = $request->getControllerName();
+        $actionName = $request->getControllerActionName();
+        $actionRequest = [
+            '@extension' => $extensionName,
+            '@controller' => $controllerName,
+            '@action' => $actionName,
+        ];
+        if ($vendorName !== null) {
+            $actionRequest['@vendor'] = $vendorName;
+        }
+        $result = '<input type="hidden" name="' . $this->prefixFieldName('__referrer[@request]') . '" value="' . htmlspecialchars($this->hashService->appendHmac(serialize($actionRequest))) . '" />' . LF;
+        $this->securedReferrerFieldRendered = true;
         return $result;
     }