From 6e31f4861930c83e41fd1566d312e078b1f47ed0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be>
Date: Mon, 4 Jun 2018 16:42:44 +0200
Subject: [PATCH] :sparkles: feat(core) Reject CSRF based on HEADER values

issue #5840
---
 include/class_CSRFProtection.inc | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/class_CSRFProtection.inc b/include/class_CSRFProtection.inc
index 3c6992ab5..7c3f6954a 100644
--- a/include/class_CSRFProtection.inc
+++ b/include/class_CSRFProtection.inc
@@ -29,6 +29,8 @@ class CSRFProtection
       throw new Exception('CSRF protection token missing');
     }
 
+    static::checkHeaders();
+
     $validToken = static::getToken();
     if ($_POST['CSRFtoken'] !== static::getToken()) {
       throw new Exception('CSRF protection token invalid');
@@ -42,4 +44,29 @@ class CSRFProtection
     }
     return session::get('CSRFtoken');
   }
+
+  public static function checkHeaders()
+  {
+    $origin = FALSE;
+    if (!empty($_SERVER['HTTP_ORIGIN'])) {
+      $origin = $_SERVER['HTTP_ORIGIN'];
+    } elseif (!empty($_SERVER['HTTP_REFERER'])) {
+      $origin = $_SERVER['HTTP_REFERER'];
+    }
+    if ($origin) {
+      $origin = preg_replace('|^[^/]+://([^/]+)(/.*)?$|', '\1', $origin);
+      $target = FALSE;
+      if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
+        $target = $_SERVER['HTTP_X_FORWARDED_HOST'];
+      } else
+      if (!empty($_SERVER['HTTP_HOST'])) {
+        $target = $_SERVER['HTTP_HOST'];
+      }
+      if ($target) {
+        if (!hash_equals($origin, $target)) {
+          throw new Exception('CSRF detected: origin and target are not matching ('.$origin.' != '.$target.')');
+        }
+      }
+    }
+  }
 }
-- 
GitLab