mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-10-28 03:51:08 -04:00
FE: Hardening
This commit is contained in:
1 parent
f37f2c7df7
commit
d88e46b713
3 files changed
+48
-8
No files matched your search
@@ -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;
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
Reference in new issue
Block a user