summaryrefslogtreecommitdiffstats
path: root/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
diff options
context:
space:
mode:
Diffstat (limited to 'core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php')
-rw-r--r--core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php32
1 files changed, 32 insertions, 0 deletions
diff --git a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
index 1a468f1..0573eea 100644
--- a/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/RedirectResponseSubscriber.php
@@ -10,6 +10,7 @@ namespace Drupal\Core\EventSubscriber;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Routing\RequestContext;
use Drupal\Core\Routing\UrlGeneratorInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
@@ -93,6 +94,36 @@ class RedirectResponseSubscriber implements EventSubscriberInterface {
}
/**
+ * Sanitize the destination parameter to prevent open redirect attacks.
+ *
+ * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
+ * The Event to process.
+ */
+ public function sanitizeDestination(GetResponseEvent $event) {
+ $request = $event->getRequest();
+ // Sanitize the destination parameter (which is often used for redirects) to
+ // prevent open redirect attacks leading to other domains. Sanitize both
+ // $_GET['destination'] and $_REQUEST['destination'] to protect code that
+ // relies on either, but do not sanitize $_POST to avoid interfering with
+ // unrelated form submissions. The sanitization happens here because
+ // url_is_external() requires the variable system to be available.
+ $query_info = $request->query;
+ $request_info = $request->request;
+ if ($query_info->has('destination') || $request_info->has('destination')) {
+ // If the destination is an external URL, remove it.
+ if ($query_info->has('destination') && UrlHelper::isExternal($query_info->get('destination'))) {
+ $query_info->remove('destination');
+ $request_info->remove('destination');
+ }
+ // If there's still something in $_REQUEST['destination'] that didn't come
+ // from $_GET, check it too.
+ if ($request_info->has('destination') && (!$query_info->has('destination') || $request_info->get('destination') != $query_info->get('destination')) && UrlHelper::isExternal($request_info->get('destination'))) {
+ $request_info->remove('destination');
+ }
+ }
+ }
+
+ /**
* Registers the methods in this class that should be listeners.
*
* @return array
@@ -100,6 +131,7 @@ class RedirectResponseSubscriber implements EventSubscriberInterface {
*/
static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = array('checkRedirectUrl');
+ $events[KernelEvents::REQUEST][] = array('sanitizeDestination', 100);
return $events;
}
}