You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -194,6 +199,10 @@ public function isAuthenticated()
194
199
{
195
200
// Controllo autenticazione normale
196
201
if (!empty($this->user)) {
202
+
// Verifica il token di sessione
203
+
if (!$this->checkSessionToken()) {
204
+
returnfalse;
205
+
}
197
206
returntrue;
198
207
}
199
208
@@ -296,11 +305,11 @@ public function getFirstModule($first = null)
296
305
if (!$this->isAdmin()) {
297
306
$group = $this->getUser()['gruppo'];
298
307
299
-
$query .= ' AND `id` IN (SELECT `idmodule` FROM `zz_permissions` WHERE `idgruppo` = '.Group::where('nome', $group)->first()->id." AND `permessi` IN ('r', 'rw'))";
308
+
$query .= ' AND `id` IN (SELECT `idmodule` FROM `zz_permissions` WHERE `idgruppo` = ' . Group::where('nome', $group)->first()->id . " AND `permessi` IN ('r', 'rw'))";
300
309
}
301
310
302
311
$database = database();
303
-
$results = $database->fetchArray($query." AND `options` != '' AND `options` != 'menu' AND `options` IS NOT NULL ORDER BY `order` ASC", $parameters);
312
+
$results = $database->fetchArray($query . " AND `options` != '' AND `options` != 'menu' AND `options` IS NOT NULL ORDER BY `order` ASC", $parameters);
304
313
305
314
if (!empty($results)) {
306
315
$module = null;
@@ -430,7 +439,7 @@ public static function getBruteTimeout()
430
439
431
440
$database = database();
432
441
433
-
$results = $database->fetchArray('SELECT TIME_TO_SEC(TIMEDIFF(DATE_ADD(created_at, INTERVAL '.self::$brute_options['timeout'].' SECOND), NOW())) AS diff FROM zz_logs WHERE ip = :ip AND stato = :state AND DATE_ADD(created_at, INTERVAL :timeout SECOND) >= NOW() ORDER BY created_at DESC LIMIT 1', [
442
+
$results = $database->fetchArray('SELECT TIME_TO_SEC(TIMEDIFF(DATE_ADD(created_at, INTERVAL ' . self::$brute_options['timeout'] . ' SECOND), NOW())) AS diff FROM zz_logs WHERE ip = :ip AND stato = :state AND DATE_ADD(created_at, INTERVAL :timeout SECOND) >= NOW() ORDER BY created_at DESC LIMIT 1', [
434
443
':ip' => get_client_ip(),
435
444
':state' => self::getStatus()['failed']['code'],
436
445
':timeout' => self::$brute_options['timeout'],
@@ -545,7 +554,7 @@ public function attemptOTPLogin($token, $otp_code)
545
554
}
546
555
547
556
// Verifica token e OTP nel database
548
-
$token_record = $database->fetchOne('SELECT * FROM `zz_otp_tokens` WHERE `token` = '.prepare($token).' AND `enabled` = 1');
557
+
$token_record = $database->fetchOne('SELECT * FROM `zz_otp_tokens` WHERE `token` = ' . prepare($token) . ' AND `enabled` = 1');
549
558
550
559
if (empty($token_record)) {
551
560
return [
@@ -647,13 +656,13 @@ public function attemptOTPLogin($token, $otp_code)
647
656
}
648
657
649
658
// Pulisci l'OTP utilizzato
650
-
$database->query('UPDATE `zz_otp_tokens` SET `last_otp` = "" WHERE `id` = '.prepare($token_record['id']));
659
+
$database->query('UPDATE `zz_otp_tokens` SET `last_otp` = "" WHERE `id` = ' . prepare($token_record['id']));
@@ -962,7 +976,7 @@ protected function identifyUser($user_id)
962
976
$database = database();
963
977
964
978
try {
965
-
$results = $database->fetchArray('SELECT `id`, `idanagrafica`, `username`, (SELECT `title` FROM `zz_groups` LEFT JOIN `zz_groups_lang` ON `zz_groups`.`id`=`zz_groups_lang`.`id_record` AND `zz_groups_lang`.`id_lang`='.prepare(Models\Locale::getDefault()->id).' WHERE `zz_groups`.`id` = `zz_users`.`idgruppo`) AS gruppo FROM `zz_users` WHERE `id` = :user_id AND `enabled` = 1 LIMIT 1', [
979
+
$results = $database->fetchArray('SELECT `id`, `idanagrafica`, `username`, `session_token`, (SELECT `title` FROM `zz_groups` LEFT JOIN `zz_groups_lang` ON `zz_groups`.`id`=`zz_groups_lang`.`id_record` AND `zz_groups_lang`.`id_lang`=' . prepare(Models\Locale::getDefault()->id) . ' WHERE `zz_groups`.`id` = `zz_users`.`idgruppo`) AS gruppo FROM `zz_users` WHERE `id` = :user_id AND `enabled` = 1 LIMIT 1', [
966
980
':user_id' => $user_id,
967
981
]);
968
982
@@ -990,7 +1004,7 @@ protected function identifyByToken($token_record)
990
1004
// Crea un utente virtuale per la sessione
991
1005
$this->user = (object) [
992
1006
'id' => 0,
993
-
'username' => 'token_'.$token_record['id'],
1007
+
'username' => 'token_' . $token_record['id'],
994
1008
'nome' => 'Token Access',
995
1009
'cognome' => '',
996
1010
'email' => '',
@@ -1029,7 +1043,7 @@ protected function isTokenStillValid()
1029
1043
$database = database();
1030
1044
1031
1045
// Recupera il token dal database per verificare lo stato attuale
1032
-
$token_record = $database->fetchOne('SELECT * FROM `zz_otp_tokens` WHERE `id` = '.prepare($this->token_user['token_id']).' AND `enabled` = 1');
1046
+
$token_record = $database->fetchOne('SELECT * FROM `zz_otp_tokens` WHERE `id` = ' . prepare($this->token_user['token_id']) . ' AND `enabled` = 1');
1033
1047
1034
1048
if (empty($token_record)) {
1035
1049
// Token non trovato o disabilitato
@@ -1138,4 +1152,60 @@ private function isValidInternalUrl($url)
1138
1152
1139
1153
returnfalse;
1140
1154
}
1155
+
1156
+
/**
1157
+
* Genera un token di sessione sicuro e lo salva nel database.
1158
+
* Invalida automaticamente le sessioni precedenti.
1159
+
*
1160
+
* @param int $user_id ID dell'utente
1161
+
*/
1162
+
protectedfunctiongenerateSessionToken($user_id)
1163
+
{
1164
+
// Genera un token sicuro di 64 caratteri esadecimali
1165
+
$token = bin2hex(random_bytes(32));
1166
+
1167
+
$database = database();
1168
+
1169
+
// Salva il token nel database (invalida automaticamente le sessioni precedenti)
1170
+
$database->update('zz_users', [
1171
+
'session_token' => $token,
1172
+
], [
1173
+
'id' => $user_id,
1174
+
]);
1175
+
1176
+
// Salva il token nella sessione
1177
+
$_SESSION['auth_token'] = $token;
1178
+
1179
+
// Aggiorna anche l'oggetto user se già caricato
1180
+
if (!empty($this->user) && $this->user->id == $user_id) {
1181
+
$this->user->session_token = $token;
1182
+
}
1183
+
}
1184
+
1185
+
/**
1186
+
* Verifica che il token di sessione corrisponda a quello nel database.
1187
+
* Permette il login per utenti senza token (periodo di transizione).
1188
+
*
1189
+
* @return bool True se il token è valido o non presente, false altrimenti
1190
+
*/
1191
+
protectedfunctioncheckSessionToken()
1192
+
{
1193
+
// Se l'utente non è caricato, non possiamo verificare
1194
+
if (empty($this->user)) {
1195
+
returnfalse;
1196
+
}
1197
+
1198
+
// Periodo di transizione: se l'utente non ha ancora un token nel DB, permetti l'accesso
1199
+
if (empty($this->user->session_token)) {
1200
+
returntrue;
1201
+
}
1202
+
1203
+
// Se c'è un token nel DB ma non in sessione, invalida la sessione
1204
+
if (empty($_SESSION['auth_token'])) {
1205
+
returnfalse;
1206
+
}
1207
+
1208
+
// Confronta i token in modo sicuro contro timing attacks
0 commit comments