diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index dced1517be..b7fbe7475b 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -1496,6 +1496,7 @@ function DisplayGraph(WebPage $oP, $sRelation, ApplicationContext $oAppContext, 'excluded' => $aExcludedByClass, 'grouping_threshold' => $iGroupingThreshold, 'export_as_pdf' => array('url' => $sExportAsPdfURL, 'label' => Dict::S('UI:Relation:ExportAsPDF')), + 'transaction_id' => utils::GetNewTransactionId(), 'export_as_attachment' => array('url' => $sExportAsDocumentURL, 'label' => Dict::S('UI:Relation:ExportAsAttachment'), 'obj_class' => $sObjClass, 'obj_key' => $iObjKey), 'drill_down' => array('url' => $sDrillDownURL, 'label' => Dict::S('UI:Relation:DrillDown')), 'labels' => array( diff --git a/js/simple_graph.js b/js/simple_graph.js index 1e2980bc84..65ecedfe9b 100644 --- a/js/simple_graph.js +++ b/js/simple_graph.js @@ -19,6 +19,7 @@ $(function() sources: {}, excluded: {}, export_as_pdf: null, + transaction_id: null, page_format: { label: 'Page Format:', values: { A3: 'A3', A4: 'A4', Letter: 'Letter' }, 'default': 'A4'}, page_orientation: { label: 'Page Orientation:', values: { P: 'Portait', L: 'Landscape' }, 'default': 'L' }, labels: { @@ -590,6 +591,7 @@ $(function() var sHtmlForm = '
'; sHtmlForm += ''; sHtmlForm += ''; + sHtmlForm += ''; $('#'+sId+'_contexts').multiselect('getChecked').each(function() { sHtmlForm += ''; }); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 2a2ff05e6b..cff8991a6f 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -32,15 +32,6 @@ require_once(APPROOT.'/application/startup.inc.php'); require_once(APPROOT.'/application/user.preferences.class.inc.php'); - // check if header contains X-Combodo-Ajax for POST request (CSRF protection for ajax calls) - if (!isset($_SERVER['HTTP_X_COMBODO_AJAX']) && $_SERVER['REQUEST_METHOD'] !== 'GET') { - $sReferer = $_SERVER['HTTP_REFERER']; - $sErrorMsg = 'Unauthorized access. Please see https://www.itophub.io/wiki/page?id=3_2_0:release:developer#checking_for_the_presence_of_specific_header_in_the_post_to_enhance_protection_against_csrf_attacks'; - IssueLog::Error("Unprotected ajax call : $sErrorMsg", LogChannels::SECURITY, ['referer' => $sReferer]); - header('HTTP/1.1 401 Unauthorized'); - die($sErrorMsg); - } - IssueLog::Trace('----- Request: '.utils::GetRequestUri(), LogChannels::WEB_REQUEST); $oKPI = new ExecutionKPI(); $oKPI->ComputeAndReport('Data model loaded'); @@ -67,6 +58,20 @@ break; } LoginWebPage::DoLoginEx($sRequestedPortalId, false); + + // check if header contains X-Combodo-Ajax for POST request (CSRF protection for ajax calls) + // check must be performed after DoLoginEx to be logged in and to be able to check the token (based on the transaction id) + if (!isset($_SERVER['HTTP_X_COMBODO_AJAX']) && $_SERVER['REQUEST_METHOD'] !== 'GET') { + $sTransactionId = utils::ReadPostedParam("transaction_id"); + if (!utils::IsTransactionValid($sTransactionId, false)) { // if a form is submitted without header but contains a token... should be exceptional + $sReferer = $_SERVER['HTTP_REFERER']; + $sErrorMsg = 'Unauthorized access. Please see https://www.itophub.io/wiki/page?id=3_2_0:release:developer#checking_for_the_presence_of_specific_header_in_the_post_to_enhance_protection_against_csrf_attacks'; + IssueLog::Error("Unprotected ajax call : $sErrorMsg", LogChannels::SECURITY, ['referer' => $sReferer]); + header('HTTP/1.1 401 Unauthorized'); + die($sErrorMsg); + } + } + $oKPI->ComputeAndReport('User login'); // N°2780 Fix ContextTag for console