mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Merge branch 'refs/heads/feature/N°7124-CSRF-in-several-iTop-pages' into support/3.2
This commit is contained in:
@@ -87,6 +87,7 @@
|
|||||||
|
|
||||||
{% block pPageScripts %}
|
{% block pPageScripts %}
|
||||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'node_modules/jquery/dist/jquery.min.js'|add_itop_version }}"></script>
|
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'node_modules/jquery/dist/jquery.min.js'|add_itop_version }}"></script>
|
||||||
|
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'js/ajax_hook.js'|add_itop_version }}"></script>
|
||||||
{% if is_development_environment() %}
|
{% if is_development_environment() %}
|
||||||
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'node_modules/jquery-migrate/dist/jquery-migrate.js'|add_itop_version }}"></script>
|
<script type="text/javascript" src="{{ app['combodo.absolute_url'] ~ 'node_modules/jquery-migrate/dist/jquery-migrate.js'|add_itop_version }}"></script>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
5
js/ajax_hook.js
Normal file
5
js/ajax_hook.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// add X-Combodo-Ajax for all request (just after jaquery is loaded)
|
||||||
|
// mandatory for ajax requests with JQuery (CSRF protection)
|
||||||
|
$(document).ajaxSend(function (event, jqxhr, options) {
|
||||||
|
jqxhr.setRequestHeader('X-Combodo-Ajax', 'true');
|
||||||
|
});
|
||||||
@@ -16,11 +16,7 @@ const CombodoCKEditorFeeds = {
|
|||||||
return async function(queryText) {
|
return async function(queryText) {
|
||||||
return new Promise( resolve => {
|
return new Promise( resolve => {
|
||||||
setTimeout( () => {
|
setTimeout( () => {
|
||||||
fetch(options.url + queryText, {
|
CombodoHTTP.Fetch(options.url + queryText)
|
||||||
headers: {
|
|
||||||
'X-Combodo-Ajax': true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(response => {
|
.then(response => {
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -112,12 +112,9 @@ const CombodoCKEditorHandler = {
|
|||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('upload', file);
|
formData.append('upload', file);
|
||||||
|
|
||||||
fetch(uploadUrl, {
|
CombodoHTTP.Fetch(uploadUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData
|
||||||
headers: {
|
|
||||||
'X-Combodo-Ajax': true
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(responseData => {
|
.then(responseData => {
|
||||||
|
|||||||
@@ -247,12 +247,8 @@ $(function()
|
|||||||
var file = event.target.files[0];
|
var file = event.target.files[0];
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
|
CombodoHTTP.Fetch(this.options.post_upload_to, {
|
||||||
fetch(this.options.post_upload_to, {
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
|
||||||
'X-Combodo-Ajax': true
|
|
||||||
},
|
|
||||||
body: formData
|
body: formData
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
|||||||
@@ -8,11 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// AJAX calls handling
|
|
||||||
// - Custom headers
|
|
||||||
$(document).ajaxSend(function (event, jqxhr, options) {
|
|
||||||
jqxhr.setRequestHeader('X-Combodo-Ajax', 'true');
|
|
||||||
});
|
|
||||||
// - Error messages regarding the error code
|
// - Error messages regarding the error code
|
||||||
$(document).ajaxError(function (event, jqxhr, options) {
|
$(document).ajaxError(function (event, jqxhr, options) {
|
||||||
// User is not logged in
|
// User is not logged in
|
||||||
|
|||||||
17
js/utils.js
17
js/utils.js
@@ -1296,6 +1296,23 @@ const CombodoInlineImage = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Fetch API wrapper to manage AJAX requests in iTop.
|
||||||
|
*/
|
||||||
|
const CombodoHTTP = {
|
||||||
|
/**
|
||||||
|
* @param {string} sUrl URL to fetch
|
||||||
|
* @param {Object} oOptions Fetch options
|
||||||
|
* @return {Promise<Response>}
|
||||||
|
*/
|
||||||
|
Fetch: function(sUrl, oOptions) {
|
||||||
|
oOptions = oOptions || {};
|
||||||
|
oOptions.headers = oOptions.headers || {};
|
||||||
|
oOptions.headers['X-Combodo-Ajax'] = true;
|
||||||
|
return fetch(sUrl, oOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract wrapper to manage modal dialogs in iTop.
|
* Abstract wrapper to manage modal dialogs in iTop.
|
||||||
* Implementations for the various GUIs may vary but APIs are the same.
|
* Implementations for the various GUIs may vary but APIs are the same.
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ require_once('../approot.inc.php');
|
|||||||
|
|
||||||
|
|
||||||
// check if header contains X-Combodo-Ajax for POST request (CSRF protection for ajax calls)
|
// 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'] === 'POST') {
|
if (!isset($_SERVER['HTTP_X_COMBODO_AJAX']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$sReferer = utils::HtmlEntities($_SERVER['HTTP_REFERER']);
|
$sReferer = utils::HtmlEntities($_SERVER['HTTP_REFERER']);
|
||||||
IssueLog::Error("Unprotected ajax call from: $sReferer", 'SECURITY');
|
IssueLog::Error("Unprotected ajax call from: $sReferer", 'SECURITY');
|
||||||
header('HTTP/1.1 401 Unauthorized');
|
header('HTTP/1.1 401 Unauthorized');
|
||||||
die('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');
|
die('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');
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
|
||||||
function LogErrorMessage($sMsgPrefix, $aContextInfo) {
|
function LogErrorMessage($sMsgPrefix, $aContextInfo) {
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ JS
|
|||||||
|
|
||||||
// Used throughout the app.
|
// Used throughout the app.
|
||||||
$this->LinkScriptFromAppRoot('node_modules/jquery/dist/jquery.min.js');
|
$this->LinkScriptFromAppRoot('node_modules/jquery/dist/jquery.min.js');
|
||||||
|
$this->LinkScriptFromAppRoot('js/ajax_hook.js');
|
||||||
$this->LinkScriptFromAppRoot('js/jquery.blockUI.js');
|
$this->LinkScriptFromAppRoot('js/jquery.blockUI.js');
|
||||||
if (utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
|
if (utils::IsDevelopmentEnvironment()) // Needed since many other plugins still rely on oldies like $.browser
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class OAuthLandingController extends Controller
|
|||||||
public function OperationLanding()
|
public function OperationLanding()
|
||||||
{
|
{
|
||||||
$this->AddLinkedScript(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery/dist/jquery.min.js');
|
$this->AddLinkedScript(utils::GetAbsoluteUrlAppRoot().'node_modules/jquery/dist/jquery.min.js');
|
||||||
|
$this->AddLinkedScript(utils::GetAbsoluteUrlAppRoot().'js/ajax_hook.js');
|
||||||
$this->DisplayPage([], null, static::ENUM_PAGE_TYPE_BASIC_HTML);
|
$this->DisplayPage([], null, static::ENUM_PAGE_TYPE_BASIC_HTML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user