From e1a6e8f2fcd7c52549540821bb9fc821dff07216 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 26 Nov 2020 11:09:35 +0100 Subject: [PATCH] CSS Security: Add param to fight against Clickjacking attacks --- .travis.yml | 18 +------ htdocs/core/lib/admin.lib.php | 54 +++++++++---------- htdocs/core/website.inc.php | 4 +- htdocs/install/default.css | 4 +- htdocs/install/inc.php | 9 ++-- .../install/mysql/migration/12.0.0-13.0.0.sql | 1 + .../install/mysql/tables/llx_website_page.sql | 7 +-- htdocs/install/upgrade.php | 10 ++-- htdocs/install/upgrade2.php | 6 +-- htdocs/langs/en_US/website.lang | 3 +- htdocs/website/class/websitepage.class.php | 7 +++ htdocs/website/index.php | 42 +++++++++------ 12 files changed, 85 insertions(+), 80 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef57f908cdf..2479de608ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,31 +31,15 @@ addons: # We need pgloader for import mysql database into pgsql - pgloader -#php: -#- '5.6' -#- '7.4' -#- nightly - env: global: # Set to true for very verbose output - DEBUG=false - #jobs: - # MariaDB overrides MySQL installation so it's not possible to test both yet - #- DB=mariadb - #- DB=mysql - #- DB=postgresql - # See https://docs.travis-ci.com/user/languages/php/#Apache-%2B-PHP - #- WS=apache jobs: fast_finish: true allow_failures: - php: nightly - # We exclude some combinations not usefull to save Travis CPU - exclude: - - php: nightly - env: DB=postgresql include: - if: type = push php: '5.6' @@ -416,7 +400,7 @@ script: php step5.php 12.0.0 13.0.0 > $TRAVIS_BUILD_DIR/upgrade12001300-3.log # Enable modules not enabled into original dump - php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP > $TRAVIS_BUILD_DIR/enablemodule.log + php upgrade2.php 0.0.0 0.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL,MAIN_MODULE_WEBSITE,MAIN_MODULE_TICKET,MAIN_MODULE_ACCOUNTING,MAIN_MODULE_MRP,MAIN_MODULE_RECRUITMENT > $TRAVIS_BUILD_DIR/enablemodule.log echo $? cd - set +e diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 6cab3638eb5..a697fcdfdc5 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -402,36 +402,36 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle } } - if ($error == 0) - { - if (!$silent) { - print ''.$langs->trans("ProcessMigrateScript").''; - print ''.$langs->trans("OK"); - //if (! empty($conf->use_javascript_ajax)) { - print ''; - print ' - '.$langs->trans("ShowHideDetails").''; - //} - print ''."\n"; + if (!$silent) { + print ''.$langs->trans("ProcessMigrateScript").''; + print ''; + if ($error == 0) { + print ''.$langs->trans("OK").''; + } else { + print ''.$langs->trans("Error").''; } + //if (! empty($conf->use_javascript_ajax)) { + print ''; + print ' - '.$langs->trans("ShowHideDetails").''; + //} + print ''."\n"; + } + + if ($error == 0) { $ok = 1; } else { - if (!$silent) { - print ''.$langs->trans("ProcessMigrateScript").''; - print ''.$langs->trans("KO").''; - print ''."\n"; - } $ok = 0; } diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 1e94b690c8f..7fe59ad9903 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -82,11 +82,9 @@ if ($pageid > 0) if (!defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) { header("X-Content-Type-Options: nosniff"); - /* TODO Manage allow_frames flag on websitepage. - if (empty($websitepage->allow_frames) && empty($conf->global->WEBSITE_ALLOW_FRAMES_ON_ALL_PAGES)) { + if (empty($websitepage->allowed_in_frames) && empty($conf->global->WEBSITE_ALLOW_FRAMES_ON_ALL_PAGES)) { header("X-Frame-Options: SAMEORIGIN"); } - */ } // A lang was forced, so we change weblangs init diff --git a/htdocs/install/default.css b/htdocs/install/default.css index b7fd69d9ecb..ca397d1ca40 100644 --- a/htdocs/install/default.css +++ b/htdocs/install/default.css @@ -233,10 +233,10 @@ table.listofchoices, table.listofchoices tr, table.listofchoices td { /* OK */ div.ok { - color: #114466; + color: #009933; } span.ok { - color: #114466; + color: #009933; } /* Warning */ diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index e770e41e89c..a0890866b51 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -425,9 +425,7 @@ function pFooter($nonext = 0, $setuplang = '', $jscheckfunction = '', $withpleas { global $conf, $langs; - $langs->load("main"); - $langs->load("other"); - $langs->load("admin"); + $langs->loadLangs(array("main", "other", "admin")); print ''."\n"; print ''."\n"; @@ -437,7 +435,10 @@ function pFooter($nonext = 0, $setuplang = '', $jscheckfunction = '', $withpleas print '
'; if ($nonext == '2') { - print $langs->trans("ErrorFoundDuringMigration", isset($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"].'&ignoreerrors=1' : '').'

'; + print ''; + print $langs->trans("ErrorFoundDuringMigration", isset($_SERVER["REQUEST_URI"]) ? $_SERVER["REQUEST_URI"].'&ignoreerrors=1' : ''); + print ''; + print '

'; } print '"'; diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index 9951375677c..c83755009ae 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -407,6 +407,7 @@ CREATE TABLE llx_ecm_directories_extrafields ) ENGINE=innodb; ALTER TABLE llx_ecm_directories_extrafields ADD INDEX idx_ecm_directories_extrafields (fk_object); +ALTER TABLE llx_website_page ADD COLUMN allowed_in_frames integer DEFAULT 0; ALTER TABLE llx_website_page ADD COLUMN object_type varchar(255); ALTER TABLE llx_website_page ADD COLUMN fk_object varchar(255); diff --git a/htdocs/install/mysql/tables/llx_website_page.sql b/htdocs/install/mysql/tables/llx_website_page.sql index 4b1b3045d6b..499bf23d1f5 100644 --- a/htdocs/install/mysql/tables/llx_website_page.sql +++ b/htdocs/install/mysql/tables/llx_website_page.sql @@ -29,7 +29,8 @@ CREATE TABLE llx_website_page image varchar(255), keywords varchar(255), lang varchar(6), - fk_page integer, + fk_page integer, + allowed_in_frames integer DEFAULT 0, htmlheader text, content mediumtext, -- text is not enough in size status integer DEFAULT 1, @@ -40,6 +41,6 @@ CREATE TABLE llx_website_page date_creation datetime, tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, import_key varchar(14), -- import key - object_type varchar(255), - fk_object varchar(255) + object_type varchar(255), -- To link page to an object + fk_object varchar(255) -- To link page to an object ) ENGINE=innodb; diff --git a/htdocs/install/upgrade.php b/htdocs/install/upgrade.php index a7addd98547..29b51746a14 100644 --- a/htdocs/install/upgrade.php +++ b/htdocs/install/upgrade.php @@ -146,11 +146,11 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ if ($db->connected) { print ''; - print $langs->trans("ServerConnection")." : ".$dolibarr_main_db_host.''.$langs->trans("OK").''."\n"; + print $langs->trans("ServerConnection")." : ".$dolibarr_main_db_host.''.$langs->trans("OK").''."\n"; dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ServerConnection").": $dolibarr_main_db_host ".$langs->transnoentities("OK")); $ok = 1; } else { - print "".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).''.$langs->transnoentities("Error")."\n"; + print "".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).''.$langs->transnoentities("Error")."\n"; dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)); $ok = 0; } @@ -160,11 +160,11 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ if ($db->database_selected) { print ''; - print $langs->trans("DatabaseConnection")." : ".$dolibarr_main_db_name.''.$langs->trans("OK")."\n"; + print $langs->trans("DatabaseConnection")." : ".$dolibarr_main_db_name.''.$langs->trans("OK")."\n"; dolibarr_install_syslog("upgrade: Database connection successful: ".$dolibarr_main_db_name); $ok = 1; } else { - print "".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).''.$langs->trans("Error")."\n"; + print "".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name).''.$langs->trans("Error")."\n"; dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)); $ok = 0; } @@ -196,7 +196,7 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ && versioncompare($versionarray, $versionmindb) < 0) { // Warning: database version too low. - print "".$langs->trans("ErrorDatabaseVersionTooLow", join('.', $versionarray), join('.', $versionmindb))."".$langs->trans("Error")."\n"; + print "".$langs->trans("ErrorDatabaseVersionTooLow", join('.', $versionarray), join('.', $versionmindb)).''.$langs->trans("Error")."\n"; dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorDatabaseVersionTooLow", join('.', $versionarray), join('.', $versionmindb))); $ok = 0; } diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index a77606abb3f..2d84e234cf2 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -531,7 +531,7 @@ if (!GETPOST('action', 'aZ09') || preg_match('/upgrade/i', GETPOST('action', 'aZ print ''; } else { print ''; - print ''.$langs->trans('UpgradeExternalModule').': OK'; + print ''.$langs->trans('UpgradeExternalModule').': OK'; print ""; print ''; } @@ -1353,9 +1353,9 @@ function migrate_paiementfourn_facturefourn($db, $langs, $conf) if ($insert_resql) { $nb++; - print ''.$langs->trans("OK").''; + print ''.$langs->trans("OK").''; } else { - print 'Error on insert'; + print 'Error on insert'; $error++; } print ''; diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index c32fcd06f09..1d62d1c07f8 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -135,4 +135,5 @@ ReplacementDoneInXPages=Replacement done in %s pages or containers RSSFeed=RSS Feed RSSFeedDesc=You can get a RSS feed of latest articles with type 'blogpost' using this URL PagesRegenerated=%s page(s)/container(s) regenerated -RegenerateWebsiteContent=Regenerate web site cache files \ No newline at end of file +RegenerateWebsiteContent=Regenerate web site cache files +AllowedInFrames=Allowed in Frames \ No newline at end of file diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 5108fe4c25b..ff072827423 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -81,6 +81,7 @@ class WebsitePage extends CommonObject */ public $lang; + public $allowed_in_frames; public $htmlheader; public $content; public $grabbed_from; @@ -160,6 +161,7 @@ class WebsitePage extends CommonObject //'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), 'fk_website' =>array('type'=>'integer', 'label'=>'WebsiteId', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'position'=>40, 'searchall'=>0, 'foreignkey'=>'websitepage.rowid'), 'fk_page' =>array('type'=>'integer', 'label'=>'ParentPageId', 'enabled'=>1, 'visible'=>1, 'notnull'=>-1, 'position'=>45, 'searchall'=>0, 'foreignkey'=>'website.rowid'), + 'allowed_in_frames' =>array('type'=>'integer', 'label'=>'AllowedInFrames', 'enabled'=>1, 'visible'=>-1, 'position'=>48, 'searchall'=>0), 'htmlheader' =>array('type'=>'text', 'label'=>'HtmlHeader', 'enabled'=>1, 'visible'=>0, 'position'=>50, 'searchall'=>0), 'content' =>array('type'=>'mediumtext', 'label'=>'Content', 'enabled'=>1, 'visible'=>0, 'position'=>51, 'searchall'=>0), 'grabbed_from' =>array('type'=>'varchar(255)', 'label'=>'GrabbedFrom', 'enabled'=>1, 'visible'=>1, 'index'=>1, 'position'=>400, 'comment'=>'URL page content was grabbed from'), @@ -265,6 +267,7 @@ class WebsitePage extends CommonObject $sql .= " t.content,"; $sql .= " t.lang,"; $sql .= " t.fk_page,"; + $sql .= " t.allowed_in_frames,"; $sql .= " t.status,"; $sql .= " t.grabbed_from,"; $sql .= " t.date_creation,"; @@ -325,6 +328,7 @@ class WebsitePage extends CommonObject $this->content = $obj->content; $this->lang = $obj->lang; $this->fk_page = $obj->fk_page; + $this->allowed_in_frames = $obj->allowed_in_frames; $this->status = $obj->status; $this->grabbed_from = $obj->grabbed_from; $this->date_creation = $this->db->jdate($obj->date_creation); @@ -383,6 +387,7 @@ class WebsitePage extends CommonObject $sql .= " t.content,"; $sql .= " t.lang,"; $sql .= " t.fk_page,"; + $sql .= " t.allowed_in_frames,"; $sql .= " t.status,"; $sql .= " t.grabbed_from,"; $sql .= " t.date_creation,"; @@ -453,6 +458,7 @@ class WebsitePage extends CommonObject $record->content = $obj->content; $record->lang = $obj->lang; $record->fk_page = $obj->fk_page; + $record->allowed_in_frames = $obj->allowed_in_frames; $record->status = $obj->status; $record->grabbed_from = $obj->grabbed_from; $record->date_creation = $this->db->jdate($obj->date_creation); @@ -839,6 +845,7 @@ class WebsitePage extends CommonObject $this->description = 'This is my page'; $this->image = ''; $this->keywords = 'keyword1, keyword2'; + $this->allowed_in_frames = 1; $this->htmlheader = ''; $this->content = 'This is a html content'; $this->status = ''; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 2a073aded73..d8f93da3ba1 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -940,6 +940,7 @@ if ($action == 'addcontainer') $objectpage->otherlang = GETPOST('WEBSITE_OTHERLANG', 'aZ09comma'); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); + $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); $objectpage->htmlheader = GETPOST('htmlheader', 'none'); $objectpage->author_alias = GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml'); $objectpage->object_type = GETPOST('WEBSITE_OBJECTCLASS'); @@ -1562,7 +1563,7 @@ if ($action == 'setashome') } } -// Update page (meta) +// Update page properties (meta) if ($action == 'updatemeta') { $db->begin(); @@ -1656,6 +1657,7 @@ if ($action == 'updatemeta') $objectpage->description = str_replace(array('<', '>'), '', GETPOST('WEBSITE_DESCRIPTION', 'alphanohtml')); $objectpage->image = GETPOST('WEBSITE_IMAGE', 'alpha'); $objectpage->keywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); + $objectpage->allowed_in_frames = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); $objectpage->htmlheader = trim(GETPOST('htmlheader', 'none')); $objectpage->fk_page = (GETPOST('pageidfortranslation', 'int') > 0 ? GETPOST('pageidfortranslation', 'int') : 0); $objectpage->author_alias = trim(GETPOST('WEBSITE_AUTHORALIAS', 'alphanohtml')); @@ -2831,7 +2833,6 @@ if (!GETPOST('hide_websitemenu')) print ''; // end websitehelp - if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') { // Adding jquery code to change on the fly url of preview ext @@ -2887,7 +2888,6 @@ if (!GETPOST('hide_websitemenu')) } - $head = array(); @@ -3279,7 +3279,7 @@ if ($action == 'importsite') print '
'; } -if ($action == 'editmeta' || $action == 'createcontainer') +if ($action == 'editmeta' || $action == 'createcontainer') // Edit properties of a web site OR properties of a web page { print '
'; @@ -3366,6 +3366,7 @@ if ($action == 'editmeta' || $action == 'createcontainer') $pageimage = $objectpage->image; $pagekeywords = $objectpage->keywords; $pagelang = $objectpage->lang; + $pageallowedinframes = $objectpage->allowed_in_frames; $pagehtmlheader = $objectpage->htmlheader; $pagedatecreation = $objectpage->date_creation; $pagedatemodification = $objectpage->date_modification; @@ -3389,6 +3390,7 @@ if ($action == 'editmeta' || $action == 'createcontainer') if (GETPOST('WEBSITE_IMAGE', 'alpha')) $pageimage = GETPOST('WEBSITE_IMAGE', 'alpha'); if (GETPOST('WEBSITE_KEYWORDS', 'alpha')) $pagekeywords = str_replace(array('<', '>'), '', GETPOST('WEBSITE_KEYWORDS', 'alphanohtml')); if (GETPOST('WEBSITE_LANG', 'aZ09')) $pagelang = GETPOST('WEBSITE_LANG', 'aZ09'); + if (GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09')) $pageallowedinframes = GETPOST('WEBSITE_ALLOWED_IN_FRAMES', 'aZ09'); if (GETPOST('htmlheader', 'none')) $pagehtmlheader = GETPOST('htmlheader', 'none'); if ($action != 'createcontainer') @@ -3542,6 +3544,15 @@ if ($action == 'editmeta' || $action == 'createcontainer') } print ''; + // Allowed in frames + print ''; + print $langs->trans('AllowedInFrames'); + //$htmlhelp = $langs->trans("AllowedInFramesDesc"); + //print $form->textwithpicto($langs->trans('AllowedInFrames'), $htmlhelp, 1, 'help', '', 0, 2, 'allowedinframestooltip'); + print ''; + print ''; + print ''; + // Categories if (!empty($conf->categorie->enabled) && !empty($user->rights->categorie->lire)) { @@ -3566,18 +3577,19 @@ if ($action == 'editmeta' || $action == 'createcontainer') print ""; } - print ''; - print 'ObjectClass'; - print ''; - print ''; - print ''; - - print ''; - print 'ObjectID'; - print ''; - print ''; - print ''; + if (!empty($conf->global->WEBSITE_PAGE_SHOW_INTERNAL_LINKS_TO_OBJECT)) { + print ''; + print 'ObjectClass'; + print ''; + print ''; + print ''; + print ''; + print 'ObjectID'; + print ''; + print ''; + print ''; + } $fuser = new User($db);