diff --git a/application/loginwebpage.class.inc.php b/application/loginwebpage.class.inc.php index 79d499be0..23459f1c3 100644 --- a/application/loginwebpage.class.inc.php +++ b/application/loginwebpage.class.inc.php @@ -88,7 +88,7 @@ class LoginWebPage extends NiceWebPage parent::__construct($sTitle); $this->SetStyleSheet(); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); } public function SetStyleSheet() diff --git a/datamodels/2.x/itop-hub-connector/hubconnectorpage.class.inc.php b/datamodels/2.x/itop-hub-connector/hubconnectorpage.class.inc.php index 8e8a5100d..1ce54772d 100644 --- a/datamodels/2.x/itop-hub-connector/hubconnectorpage.class.inc.php +++ b/datamodels/2.x/itop-hub-connector/hubconnectorpage.class.inc.php @@ -8,7 +8,7 @@ class HubConnectorPage extends NiceWebPage parent::__construct($sTitle); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); $sImagesDir = utils::GetAbsoluteUrlAppRoot().'images'; $sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images'; diff --git a/pages/ajax.document.php b/pages/ajax.document.php index 9257b0a26..ae4f37ee3 100644 --- a/pages/ajax.document.php +++ b/pages/ajax.document.php @@ -61,7 +61,7 @@ try $oPage->set_cache($iCacheSec); // X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page // so we're resetting its value ! (see N°3416) - $oPage->add_xframe_options(''); + $oPage->add_http_headers(''); } } break; @@ -80,7 +80,7 @@ try // X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page // so we're resetting its value ! (see N°3416) - $oPage->add_xframe_options(''); + $oPage->add_http_headers(''); $oPage->add_header("Last-Modified: Wed, 15 Jun 2016 13:21:15 GMT"); // An arbitrary date in the past is ok } @@ -93,7 +93,7 @@ try // X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page // so we're resetting its value ! (see N°3416) - $oPage->add_xframe_options(''); + $oPage->add_http_headers(''); $oPage->add(file_get_contents(Utils::GetCachePath().$sSignature.'.js')); break; diff --git a/pages/ajax.render.php b/pages/ajax.render.php index f7514fae8..d261f21fb 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -783,9 +783,11 @@ try if (!empty($sClass) && ($sClass != 'InlineImage') && !empty($id) && !empty($sField)) { $oPage = new DownloadPage(''); + // X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page // so we're resetting its value ! (see N°3416) - $oPage->add_xframe_options(''); + $oPage->add_http_headers(''); + $iCacheSec = (int)utils::ReadParam('cache', 0); $oPage->set_cache($iCacheSec); diff --git a/setup/email.test.php b/setup/email.test.php index 8fe476987..c42723a39 100644 --- a/setup/email.test.php +++ b/setup/email.test.php @@ -38,7 +38,7 @@ $oP = new SetupPage('iTop email test utility'); // Although this page doesn't expose sensitive info, with it we can send multiple emails // So we're adding this http header to reduce CSRF exposure... -$oP->add_xframe_options('DENY'); +$oP->add_http_headers('DENY'); /** diff --git a/sources/application/TwigBase/Controller/Controller.php b/sources/application/TwigBase/Controller/Controller.php index 2eab21aed..11202658c 100644 --- a/sources/application/TwigBase/Controller/Controller.php +++ b/sources/application/TwigBase/Controller/Controller.php @@ -657,7 +657,7 @@ abstract class Controller { case self::ENUM_PAGE_TYPE_HTML: $this->m_oPage = new iTopWebPage($this->GetOperationTitle(), false); - $this->m_oPage->add_xframe_options(); + $this->m_oPage->add_http_headers(); if ($this->m_bIsBreadCrumbEnabled) { if (count($this->m_aBreadCrumbEntry) > 0) { diff --git a/sources/application/WebPage/AjaxPage.php b/sources/application/WebPage/AjaxPage.php index e046765d7..8e03b6e4a 100644 --- a/sources/application/WebPage/AjaxPage.php +++ b/sources/application/WebPage/AjaxPage.php @@ -46,7 +46,7 @@ class AjaxPage extends WebPage implements iTabbedPage parent::__construct($s_title, $bPrintable); //$this->add_header("Content-type: text/html; charset=utf-8"); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); $this->m_oTabs = new TabManager(); $this->sContentType = 'text/html'; $this->sContentDisposition = 'inline'; diff --git a/sources/application/WebPage/CSVPage.php b/sources/application/WebPage/CSVPage.php index ffcac5737..519ba4344 100644 --- a/sources/application/WebPage/CSVPage.php +++ b/sources/application/WebPage/CSVPage.php @@ -33,7 +33,7 @@ class CSVPage extends WebPage parent::__construct($s_title); $this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); //$this->add_header("Content-Transfer-Encoding: binary"); $oKpi->ComputeStats(get_class($this).' creation', 'CSVPage'); } diff --git a/sources/application/WebPage/WebPage.php b/sources/application/WebPage/WebPage.php index 0900f7822..a148b1956 100644 --- a/sources/application/WebPage/WebPage.php +++ b/sources/application/WebPage/WebPage.php @@ -1002,12 +1002,25 @@ JS; $this->a_headers[] = $s_header; } + /** + * @param string|null $sXFrameOptionsHeaderValue passed to {@see add_xframe_options} + * + * @return void + * @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation, replace {@see add_xframe_options} consumers call + */ + public function add_http_headers($sXFrameOptionsHeaderValue = null) + { + $this->add_xframe_options($sXFrameOptionsHeaderValue); + $this->add_xcontent_type_options(); + } + /** * @param string|null $sHeaderValue for example `SAMESITE`. If null will set the header using the config parameter value. * * @since 2.7.3 3.0.0 N°3416 * @uses security_header_xframe config parameter * @uses \utils::GetConfig() + * * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options */ public function add_xframe_options($sHeaderValue = null) @@ -1019,6 +1032,17 @@ JS; $this->add_header('X-Frame-Options: '.$sHeaderValue); } + /** + * @return void + * @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation + * + * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + */ + public function add_xcontent_type_options() + { + $this->add_header('X-Content-Type-Options: nosniff'); + } + /** * Add needed headers to the page so that it will no be cached */ diff --git a/sources/application/WebPage/XMLPage.php b/sources/application/WebPage/XMLPage.php index cab121254..ebdd2657b 100644 --- a/sources/application/WebPage/XMLPage.php +++ b/sources/application/WebPage/XMLPage.php @@ -43,7 +43,7 @@ class XMLPage extends WebPage $this->m_bHeaderSent = false; $this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); $this->add_header("Content-location: export.xml"); $oKpi->ComputeStats(get_class($this).' creation', 'XMLPage'); } diff --git a/sources/application/WebPage/iTopWebPage.php b/sources/application/WebPage/iTopWebPage.php index 16ec6c91e..2f68b2621 100644 --- a/sources/application/WebPage/iTopWebPage.php +++ b/sources/application/WebPage/iTopWebPage.php @@ -131,7 +131,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage $this->SetRootUrl(utils::GetAbsoluteUrlAppRoot()); $this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET); $this->no_cache(); - $this->add_xframe_options(); + $this->add_http_headers(); $this->PrepareLayout(); if ($this->IsPrintableVersion()) { $oPrintHeader = $this->OutputPrintable(); diff --git a/tests/php-unit-tests/legacy-tests/benchmark.php b/tests/php-unit-tests/legacy-tests/benchmark.php index 148007bb1..4d2bd5dd4 100644 --- a/tests/php-unit-tests/legacy-tests/benchmark.php +++ b/tests/php-unit-tests/legacy-tests/benchmark.php @@ -781,7 +781,7 @@ try case 'create_structure': $oP->no_cache(); - $oP->add_xframe_options('DENY'); + $oP->add_http_headers('DENY'); $iPlannedContacts = Utils::ReadParam('plannedcontacts'); $iPlannedContracts = Utils::ReadParam('plannedcontracts'); diff --git a/webservices/export-v2.php b/webservices/export-v2.php index aa77c31ad..1537214b8 100644 --- a/webservices/export-v2.php +++ b/webservices/export-v2.php @@ -41,7 +41,7 @@ function ReportErrorAndExit($sErrorMessage) else { $oP = new WebPage("iTop - Export"); - $oP->add_xframe_options(); + $oP->add_http_headers(); $oP->p('ERROR: '.utils::HtmlEntities($sErrorMessage)); $oP->output(); exit(EXIT_CODE_ERROR); @@ -60,7 +60,7 @@ function ReportErrorAndUsage($sErrorMessage) } else { $oP = new WebPage("iTop - Export"); - $oP->add_xframe_options(); + $oP->add_http_headers(); $oP->p('ERROR: '.$sErrorMessage); Usage($oP); $oP->output(); @@ -689,13 +689,13 @@ try // Note: Using NiceWebPage only for HTML export as it includes JS scripts & files, which makes no sense in other export formats. More over, it breaks Excel spreadsheet import. if ($oExporter instanceof HTMLBulkExport) { $oP = new NiceWebPage('iTop export'); - $oP->add_xframe_options(); + $oP->add_http_headers(); $oP->add_ready_script("$('table.listResults').tablesorter({widgets: ['MyZebra']});"); $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css'); $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/v4-shims.min.css'); } else { $oP = new WebPage('iTop export'); - $oP->add_xframe_options(); + $oP->add_http_headers(); $oP->add_style("table br { mso-data-placement:same-cell; }"); // Trick for Excel: keep line breaks inside the same cell ! } $oP->add_style("body { overflow: auto; }"); @@ -715,7 +715,7 @@ catch (BulkExportMissingParameterException $e) { } catch (Exception $e) { $oP = new WebPage('iTop Export'); - $oP->add_xframe_options(); + $oP->add_http_headers(); $oP->add('Error: '.utils::HtmlEntities($e->getMessage())); IssueLog::Error(utils::HtmlEntities($e->getMessage())."\n".$e->getTraceAsString()); $oP->output();