diff --git a/Admin/admin.php b/Admin/admin.php index 19f1a1f0..54eb60a7 100644 --- a/Admin/admin.php +++ b/Admin/admin.php @@ -17,19 +17,156 @@ ## ## ################################################################################# -session_start(); +// ─── SESSION ───────────────────────────────────────────────────────────────── +// Harden session cookie before session_start() — has no effect after. +if (session_status() === PHP_SESSION_NONE) { + session_set_cookie_params([ + 'lifetime' => 0, + 'path' => '/', + 'secure' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off', + 'httponly' => true, + 'samesite' => 'Strict', + ]); + session_start(); +} + +// ─── CSRF TOKEN ─────────────────────────────────────────────────────────────── +// Generat o singură dată per sesiune și stocat în $_SESSION. +// Toate request-urile POST trebuie să trimită acest token în câmpul _csrf_token. +if (empty($_SESSION['_csrf_token'])) { + $_SESSION['_csrf_token'] = bin2hex(random_bytes(32)); +} + +// ─── CORE INCLUDES ─────────────────────────────────────────────────────────── include_once("../GameEngine/config.php"); include_once("../GameEngine/Database.php"); -include_once ("../GameEngine/Lang/" . LANG . ".php"); +include_once("../GameEngine/Lang/" . LANG . ".php"); include_once("../GameEngine/Admin/database.php"); include_once("../GameEngine/Data/buidata.php"); include_once("../GameEngine/Artifacts.php"); -$subpage = 'Login'; +// ─── SECURITY HELPERS ──────────────────────────────────────────────────────── + +/** + * Return a sanitised integer from a superglobal key, or null if missing/invalid. + * Replaces direct (int) casts on $_GET inside switch — ensures 0 is treated as + * absent (IDs are always >= 1 in TravianZ). + */ +function admin_input_id(array $source, string $key): ?int +{ + if (!isset($source[$key]) || !ctype_digit((string)$source[$key])) { + return null; + } + $v = (int)$source[$key]; + return $v > 0 ? $v : null; +} + +/** + * HTML-escape a value for safe output inside HTML attributes or text nodes. + */ +function e(string $value): string +{ + return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); +} + +/** + * Whitelist-validate the ?p= parameter. + * Returns the validated page string, or '' if not in the whitelist. + * + * SECURITY: This is the primary defence against path-traversal in the + * include('Templates/'.$p.'.tpl') call below. Only values present in this + * array are ever passed to include(). + */ +function admin_validated_page(string $raw): string +{ + static $whitelist = [ + 'server_info', 'online', 'notregistered', 'inactive', 'report', + 'message', 'massmessage', 'sysmessage', 'map', 'map_tile', 'natars', + 'search', 'ban', 'maintenance', 'cleanban', 'gold', 'usergold', + 'maintenenceResetGold', 'delmedal', 'delallymedal', 'givePlus', + 'maintenenceResetPlus', 'givePlusRes', 'maintenenceResetPlusBonus', + 'addUsers', 'users', 'admin_log', 'config', 'debug_log', + 'editServerSet', 'editPlusSet', 'editLogSet', 'editNewsboxSet', + 'editExtraSet', 'editAdminInfo', 'resetServer', 'player', 'editUser', + 'deletion', 'Newmessage', 'editPlus', 'editSitter', 'editOverall', + 'editWeek', 'userlogin', 'userillegallog', 'editHero', 'editAdditional', + 'village', 'editResources', 'addTroops', 'addABTroops', 'editVillage', + 'villagelog', 'techlog', 'msg', + ]; + + return in_array($raw, $whitelist, true) ? $raw : ''; +} + +/** + * Returnează token-ul CSRF curent ca string hex. + * Folosit pentru injectare în câmpuri ascunse sau header-e AJAX. + */ +function csrf_token(): string +{ + return $_SESSION['_csrf_token'] ?? ''; +} + +/** + * Emite un gata de pus în orice