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; $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) { if ($authorized) {
$response = call_user_func([$controller, $handler[1]]); $response = call_user_func([$controller, $handler[1]]);

View File

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

View File

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

View File

@ -28,9 +28,7 @@
}, },
getPlace: function (placeId, marker) { getPlace: function (placeId, marker) {
var xhr = new XMLHttpRequest(); MapGuesser.httpRequest('GET', '/admin/place.json/' + placeId, function () {
xhr.responseType = 'json';
xhr.onload = function () {
document.getElementById('loading').style.visibility = 'hidden'; document.getElementById('loading').style.visibility = 'hidden';
if (!this.response.panoId) { if (!this.response.panoId) {
@ -46,10 +44,7 @@
places[marker.placeId].noPano = false; places[marker.placeId].noPano = false;
MapEditor.loadPano(this.response.panoId, places[marker.placeId].pov); MapEditor.loadPano(this.response.panoId, places[marker.placeId].pov);
}; });
xhr.open('GET', '/admin/place.json/' + placeId, true);
xhr.send();
}, },
loadPano: function (panoId, pov) { loadPano: function (panoId, pov) {
@ -284,9 +279,7 @@
data.append('deleted[]', JSON.stringify(MapEditor.deleted[placeId])); data.append('deleted[]', JSON.stringify(MapEditor.deleted[placeId]));
} }
var xhr = new XMLHttpRequest(); MapGuesser.httpRequest('POST', '/admin/saveMap/' + mapId + '/json', function () {
xhr.responseType = 'json';
xhr.onload = function () {
document.getElementById('loading').style.visibility = 'hidden'; document.getElementById('loading').style.visibility = 'hidden';
if (this.response.error) { if (this.response.error) {
@ -310,10 +303,7 @@
document.getElementById('deleted').innerHTML = '0'; document.getElementById('deleted').innerHTML = '0';
document.getElementById('saveButton').disabled = true; document.getElementById('saveButton').disabled = true;
}; }, data);
xhr.open('POST', '/admin/saveMap/' + mapId + '/json', true);
xhr.send(data);
}, },
replacePlaceIdsToReal: function (addedPlaces) { 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> <script>
const STATIC_ROOT = '<?= $_ENV['STATIC_ROOT'] ?>'; const STATIC_ROOT = '<?= $_ENV['STATIC_ROOT'] ?>';
const REVISION = '<?= REVISION ?>'; const REVISION = '<?= REVISION ?>';
const ANTI_CSRF_TOKEN = '<?= $_SESSION['anti_csrf_token'] ?>';
</script> </script>
<script src="<?= $_ENV['STATIC_ROOT'] ?>/js/mapguesser.js?rev=<?= REVISION ?>"></script>
<?php if (isset($jsFiles)) : ?> <?php if (isset($jsFiles)) : ?>
<?php foreach ($jsFiles as $jsFile) : ?> <?php foreach ($jsFiles as $jsFile) : ?>
<?php <?php
@ -12,18 +14,5 @@
<script src="<?= $jsFile ?>"></script> <script src="<?= $jsFile ?>"></script>
<?php endforeach; ?> <?php endforeach; ?>
<?php endif; ?> <?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> </body>
</html> </html>

View File

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