From d8dbd130d0d8e61340ad7a71e4bdd240bb236473 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be>
Date: Mon, 4 Jun 2018 14:36:59 +0200
Subject: [PATCH] :sparkels: feat(core) Add CSRF protection token

issue #5840
---
 html/main.php                     |  8 +++---
 html/setup.php                    |  3 +++
 ihtml/themes/breezy/framework.tpl |  1 +
 include/class_CSRFProtection.inc  | 45 +++++++++++++++++++++++++++++++
 setup/setup_frame.tpl             |  1 +
 5 files changed, 55 insertions(+), 3 deletions(-)
 create mode 100644 include/class_CSRFProtection.inc

diff --git a/html/main.php b/html/main.php
index 33ee1bfe8..78f6e0cdd 100644
--- a/html/main.php
+++ b/html/main.php
@@ -1,9 +1,8 @@
 <?php
-
 /*
   This code is part of FusionDirectory (http://www.fusiondirectory.org/)
   Copyright (C) 2003-2010  Cajus Pollmeier
-  Copyright (C) 2011-2016  FusionDirectory
+  Copyright (C) 2011-2018  FusionDirectory
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -54,6 +53,8 @@ if (!session::global_is_set('connected')) {
   exit;
 }
 
+CSRFProtection::check();
+
 $ui     = session::global_get('ui');
 $config = session::global_get('config');
 
@@ -324,7 +325,8 @@ if (session::is_set('errors') && session::get('errors') != "") {
 $focus = '<script type="text/javascript">';
 $focus .= 'next_msg_dialog();';
 $focus .= '</script>';
-$smarty->assign("focus", $focus);
+$smarty->assign('focus',      $focus);
+$smarty->assign('CSRFtoken',  CSRFProtection::getToken());
 
 /* Set channel if needed */
 //TODO: * move all global session calls to global_
diff --git a/html/setup.php b/html/setup.php
index 183840d0c..5a0e39c1f 100644
--- a/html/setup.php
+++ b/html/setup.php
@@ -49,6 +49,8 @@ session::start();
 session::global_set('DEBUGLEVEL', 0);
 session::set('errorsAlreadyPosted', array());
 
+CSRFProtection::check();
+
 /* Attribute initialization, reset errors */
 reset_errors();
 
@@ -123,6 +125,7 @@ $smarty->assign("navigation",     $setup->get_navigation_html());
 $smarty->assign("headline_image", $setup->get_header_image());
 $smarty->assign("headline",       $setup->get_header_text());
 $smarty->assign("focus",          $focus);
+$smarty->assign('CSRFtoken',      CSRFProtection::getToken());
 $smarty->assign("msg_dialogs",    msg_dialog::get_dialogs());
 
 if ($error_collector != "") {
diff --git a/ihtml/themes/breezy/framework.tpl b/ihtml/themes/breezy/framework.tpl
index d1061fe28..ba6b98d15 100644
--- a/ihtml/themes/breezy/framework.tpl
+++ b/ihtml/themes/breezy/framework.tpl
@@ -55,6 +55,7 @@
     {$errors}
     {$focus}
     <input type="hidden" name="php_c_check" value="1"/>
+    <input type="hidden" name="CSRFtoken" value="{$CSRFtoken}"/>
   </form>
 
 
diff --git a/include/class_CSRFProtection.inc b/include/class_CSRFProtection.inc
new file mode 100644
index 000000000..3c6992ab5
--- /dev/null
+++ b/include/class_CSRFProtection.inc
@@ -0,0 +1,45 @@
+<?php
+/*
+  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
+  Copyright (C) 2017-2018 FusionDirectory
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+class CSRFProtection
+{
+  public static function check()
+  {
+    if (empty($_POST)) {
+      return;
+    }
+    if (empty($_POST['CSRFtoken'])) {
+      throw new Exception('CSRF protection token missing');
+    }
+
+    $validToken = static::getToken();
+    if ($_POST['CSRFtoken'] !== static::getToken()) {
+      throw new Exception('CSRF protection token invalid');
+    }
+  }
+
+  public static function getToken()
+  {
+    if (!session::is_set('CSRFtoken')) {
+      session::set('CSRFtoken', standAlonePage::generateRandomHash());
+    }
+    return session::get('CSRFtoken');
+  }
+}
diff --git a/setup/setup_frame.tpl b/setup/setup_frame.tpl
index 071f5365c..03dd16c50 100644
--- a/setup/setup_frame.tpl
+++ b/setup/setup_frame.tpl
@@ -39,6 +39,7 @@
     {$errors}
     {$focus}
     <input type="hidden" name="setup_goto_step" value=""/>
+    <input type="hidden" name="CSRFtoken" value="{$CSRFtoken}"/>
   </form>
 
 </body>
-- 
GitLab