diff --git a/html/main.php b/html/main.php index 856a64e6bc97dacbb263c7d086c997db46597529..1d03fbac5a31278d610d6027dddb3ff39cc13bf1 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 6c77f663c1bb307f367a83e07f6cdd6fa990bb02..70378bb11405d566f59b73b62813ab83318f46b2 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(); @@ -124,6 +126,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 d1061fe2821622203d72f5cd9a4e8a4f95ec1a95..ba6b98d155fff9cd70cbf57049f9705644410e85 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 0000000000000000000000000000000000000000..a2d8148889e33f720c0aeec3a188e0c898a7f6ac --- /dev/null +++ b/include/class_CSRFProtection.inc @@ -0,0 +1,69 @@ +<?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 FusionDirectoryException('CSRF protection token missing'); + } + + static::checkHeaders(); + + if ($_POST['CSRFtoken'] !== static::getToken()) { + throw new FusionDirectoryException('CSRF protection token invalid'); + } + } + + public static function getToken() + { + if (!session::is_set('CSRFtoken')) { + session::set('CSRFtoken', standAlonePage::generateRandomHash()); + } + 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 && !hash_equals($origin, $target)) { + throw new FusionDirectoryException('CSRF detected: origin and target are not matching ('.$origin.' != '.$target.')'); + } + } + } +} diff --git a/setup/setup_frame.tpl b/setup/setup_frame.tpl index 071f5365c7636c16143a1b124394f27cb7a7bd75..03dd16c5076b26a1e9a6be823a8c540a602b61a7 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>