FE: Hardening

This commit is contained in:
jokob-sk committed 2026-10-09 09:41:50 +11:00
1 parent f37f2c7df7
commit d88e46b713
3 files changed
+48 -8

No files matched your search

+18 -8
View File
@@ -16,17 +16,26 @@ require dirname(__FILE__).'/../templates/skinUI.php';
// check if authenticated
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
$FUNCTION = [];
$SETTINGS = [];
$FUNCTION = '';
$SETTINGS = '';
// savesettings is state-changing and must never be reachable via GET - a GET
// URL can be triggered cross-site by a simple top-level navigation, which
// still carries the session cookie under default SameSite=Lax behavior.
if (($_GET['function'] ?? '') === 'savesettings') {
http_response_code(405);
header('Allow: POST');
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
exit();
}
// init request params
if(array_key_exists('function', $_REQUEST) != FALSE)
{
$FUNCTION = $_REQUEST['function'];
if (array_key_exists('function', $_POST)) {
$FUNCTION = $_POST['function'];
}
if(array_key_exists('settings', $_REQUEST) != FALSE)
{
$SETTINGS = $_REQUEST['settings'];
if (array_key_exists('settings', $_POST)) {
$SETTINGS = $_POST['settings'];
}
@@ -35,6 +44,7 @@ switch ($FUNCTION) {
case 'savesettings':
requireCsrfToken();
saveSettings();
break;
+29
View File
@@ -5,6 +5,35 @@ if (session_status() == PHP_SESSION_NONE) {
session_start();
}
/**
* Return this session's CSRF token, generating one on first use.
*/
function getCsrfToken(): string {
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
/**
* Halt the request with a 403 JSON response unless $_POST['csrf_token']
* matches this session's token. Guards every state-changing PHP endpoint
* that relies on the ambient session cookie rather than a request body
* credential - without this, a cross-site POST can reuse a logged-in
* operator's session to trigger the same action (CWE-352).
*/
function requireCsrfToken(): void {
$submittedToken = $_POST['csrf_token'] ?? '';
if (!is_string($submittedToken) || !hash_equals(getCsrfToken(), $submittedToken)) {
http_response_code(403);
header('Content-Type: application/json');
echo json_encode(['success' => false, 'error' => 'Invalid CSRF token']);
exit();
}
}
// Constants
$configFolderPath = rtrim(getenv('NETALERTX_CONFIG') ?: '/data/config', '/');
$legacyConfigPath = $_SERVER['DOCUMENT_ROOT'] . "/../config/app.conf";
+1
View File
@@ -620,6 +620,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX
url: "php/server/util.php",
data: {
function: 'savesettings',
csrf_token: <?= json_encode(getCsrfToken()) ?>,
settings: JSON.stringify(settingsArray) },
success: function(data, textStatus) {