Merged in feature/MAPG-133-csrf-protection (pull request #107)

Feature/MAPG-133 csrf protection
This commit is contained in:
Bence Pőcze 2020-06-13 20:41:49 +00:00
commit 6d68f247e6
7 changed files with 58 additions and 55 deletions

View File

@ -26,6 +26,12 @@ if ($match !== null) {
$authorized = true;
}
if ($method === 'post' && $request->post('anti_csrf_token') !== $request->session()->get('anti_csrf_token')) {
header('Content-Type: text/html; charset=UTF-8', true, 403);
echo json_encode(['error' => 'no_valid_anti_csrf_token']);
return;
}
if ($authorized) {
$response = call_user_func([$controller, $handler[1]]);

View File

@ -25,9 +25,7 @@
});
Game.map.fitBounds(mapBounds);
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('GET', '/game/' + mapId + '/newPlace.json', function () {
document.getElementById('loading').style.visibility = 'hidden';
document.getElementById('cover').style.visibility = 'hidden';
@ -51,10 +49,7 @@
}
Game.startNewRound();
};
xhr.open('GET', '/game/' + mapId + '/newPlace.json', true);
xhr.send();
});
},
reset: function () {
@ -127,16 +122,11 @@
handleErrorResponse: function (error) {
// for the time being we only handle the "no_session_found" error and reset the game
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('GET', '/game/' + mapId + '/json', function () {
mapBounds = this.response.bounds;
Game.reset();
};
xhr.open('GET', '/game/' + mapId + '/json', true);
xhr.send();
});
},
loadPano: function (panoId) {
@ -168,9 +158,7 @@
data.append('lat', String(guessPosition.lat));
data.append('lng', String(guessPosition.lng));
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('POST', '/game/' + mapId + '/guess.json', function () {
if (this.response.error) {
Game.handleErrorResponse(this.response.error);
return;
@ -211,10 +199,7 @@
}
Game.panoId = this.response.panoId;
};
xhr.open('POST', '/game/' + mapId + '/guess.json', true);
xhr.send(data);
}, data);
},
addRealGuessPair: function (position, guessPosition, hidden) {

View File

@ -8,9 +8,7 @@
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('POST', form.action, function () {
if (this.response.error) {
var errorText;
switch (this.response.error) {
@ -34,9 +32,6 @@
}
window.location.replace('/');
};
xhr.open('POST', form.action, true);
xhr.send(formData);
}, formData);
};
})();

View File

@ -28,9 +28,7 @@
},
getPlace: function (placeId, marker) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('GET', '/admin/place.json/' + placeId, function () {
document.getElementById('loading').style.visibility = 'hidden';
if (!this.response.panoId) {
@ -46,10 +44,7 @@
places[marker.placeId].noPano = false;
MapEditor.loadPano(this.response.panoId, places[marker.placeId].pov);
};
xhr.open('GET', '/admin/place.json/' + placeId, true);
xhr.send();
});
},
loadPano: function (panoId, pov) {
@ -284,9 +279,7 @@
data.append('deleted[]', JSON.stringify(MapEditor.deleted[placeId]));
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = function () {
MapGuesser.httpRequest('POST', '/admin/saveMap/' + mapId + '/json', function () {
document.getElementById('loading').style.visibility = 'hidden';
if (this.response.error) {
@ -310,10 +303,7 @@
document.getElementById('deleted').innerHTML = '0';
document.getElementById('saveButton').disabled = true;
};
xhr.open('POST', '/admin/saveMap/' + mapId + '/json', true);
xhr.send(data);
}, data);
},
replacePlaceIdsToReal: function (addedPlaces) {

View File

@ -0,0 +1,34 @@
var MapGuesser = {
httpRequest: function (method, url, callback, data) {
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.onload = callback;
xhr.open(method, url, true);
if (method === 'POST') {
if (typeof data === 'undefined') {
data = new FormData();
}
data.append('anti_csrf_token', ANTI_CSRF_TOKEN);
xhr.send(data);
} else {
xhr.send();
}
}
};
(function () {
var anchors = document.getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
var a = anchors[i];
if (a.href !== 'javascript:;' && a.target !== '_blank') {
a.onclick = function () {
document.getElementById('loading').style.visibility = 'visible';
}
}
}
})();

View File

@ -1,7 +1,9 @@
<script>
const STATIC_ROOT = '<?= $_ENV['STATIC_ROOT'] ?>';
const REVISION = '<?= REVISION ?>';
const ANTI_CSRF_TOKEN = '<?= $_SESSION['anti_csrf_token'] ?>';
</script>
<script src="<?= $_ENV['STATIC_ROOT'] ?>/js/mapguesser.js?rev=<?= REVISION ?>"></script>
<?php if (isset($jsFiles)) : ?>
<?php foreach ($jsFiles as $jsFile) : ?>
<?php
@ -12,18 +14,5 @@
<script src="<?= $jsFile ?>"></script>
<?php endforeach; ?>
<?php endif; ?>
<script>
(function () {
var anchors = document.getElementsByTagName('a');
for (var i = 0; i < anchors.length; i++) {
var a = anchors[i];
if (a.href !== 'javascript:;' && a.target !== '_blank') {
a.onclick = function () {
document.getElementById('loading').style.visibility = 'visible';
}
}
}
})();
</script>
</body>
</html>

View File

@ -38,3 +38,7 @@ session_start([
'cookie_httponly' => true,
'cookie_samesite' => 'Lax'
]);
if (!isset($_SESSION['anti_csrf_token'])) {
$_SESSION['anti_csrf_token'] = hash('sha256', random_bytes(10) . microtime());
}