From 89cf4757ff069972b527dec6ed57d94c5183c5fd Mon Sep 17 00:00:00 2001 From: KuJoe <1040086+KuJoe@users.noreply.github.com> Date: Sun, 22 Mar 2026 21:25:36 -0400 Subject: [PATCH] Add a checkbox to create a 30 day session Give users the option to stay logged in for 30 days instead of having to authenticate every time the browser is closed. Users can enable binding the session to an IP address to prevent session hijacking/stealing (can be disabled for users who work on mobile networks). --- config/config.ini.example | 3 + lang/ar_AR.ini | 4 ++ lang/be_BY.ini | 4 ++ lang/cs_CZ.ini | 4 ++ lang/da_DK.ini | 4 ++ lang/de_DE.ini | 4 ++ lang/de_DE_gender_doppelpunkt.ini | 4 ++ lang/de_DE_gender_dudenkonform.ini | 4 ++ lang/el_GR.ini | 4 ++ lang/en_US.ini | 4 ++ lang/eo_EO.ini | 4 ++ lang/es_ES.ini | 4 ++ lang/fa_IR.ini | 4 ++ lang/fr_FR.ini | 4 ++ lang/gl_ES.ini | 4 ++ lang/gu_GU.ini | 4 ++ lang/hi_HI.ini | 4 ++ lang/hr_HR.ini | 4 ++ lang/hu_HU.ini | 4 ++ lang/id_ID.ini | 4 ++ lang/it_IT.ini | 4 ++ lang/ko_KO.ini | 4 ++ lang/ku_KU.ini | 4 ++ lang/ms_MY.ini | 4 ++ lang/nl_NL.ini | 4 ++ lang/pl_PL.ini | 4 ++ lang/pt_BR.ini | 4 ++ lang/ru_RU.ini | 4 ++ lang/sv_SE.ini | 4 ++ lang/tr_TR.ini | 4 ++ lang/uk_UA.ini | 4 ++ lang/zh_CN.ini | 4 ++ lang/zh_TW.ini | 4 ++ system/admin/admin.php | 8 ++- system/admin/views/config-security.html.php | 23 ++++++++ system/admin/views/login.html.php | 4 ++ system/admin/views/logout.html.php | 4 ++ system/configList.json | 1 + system/htmly.php | 12 ++-- system/includes/session.php | 62 +++++++++++++++++++++ 40 files changed, 240 insertions(+), 5 deletions(-) diff --git a/config/config.ini.example b/config/config.ini.example index 5dd8594c..72e81d9b 100644 --- a/config/config.ini.example +++ b/config/config.ini.example @@ -76,6 +76,9 @@ login.protect.private = "" ; Multi-factor authentication mfa.state = "false" +; Validate admin session against client IP address. Options "true" and "false" +session.ip.validation = "true" + ; Pagination, RSS, and JSON posts.perpage = "10" category.perpage = "10" diff --git a/lang/ar_AR.ini b/lang/ar_AR.ini index 7bad38e0..18665c61 100644 --- a/lang/ar_AR.ini +++ b/lang/ar_AR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/be_BY.ini b/lang/be_BY.ini index 7619234e..ac9e450c 100644 --- a/lang/be_BY.ini +++ b/lang/be_BY.ini @@ -341,3 +341,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/cs_CZ.ini b/lang/cs_CZ.ini index 0efb7edb..cd577c71 100644 --- a/lang/cs_CZ.ini +++ b/lang/cs_CZ.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/da_DK.ini b/lang/da_DK.ini index 0f741751..fde4da2c 100644 --- a/lang/da_DK.ini +++ b/lang/da_DK.ini @@ -351,3 +351,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/de_DE.ini b/lang/de_DE.ini index 7c082bb2..d5466d7d 100644 --- a/lang/de_DE.ini +++ b/lang/de_DE.ini @@ -340,3 +340,7 @@ subpages = "Unterseiten" getstarted = "Los geht's" onthispage = "Auf dieser Seite" backtotop = "Nach oben" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/de_DE_gender_doppelpunkt.ini b/lang/de_DE_gender_doppelpunkt.ini index 551734ee..b2875752 100644 --- a/lang/de_DE_gender_doppelpunkt.ini +++ b/lang/de_DE_gender_doppelpunkt.ini @@ -340,3 +340,7 @@ subpages = "Unterseiten" getstarted = "Los geht's" onthispage = "Auf dieser Seite" backtotop = "Nach oben" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/de_DE_gender_dudenkonform.ini b/lang/de_DE_gender_dudenkonform.ini index 18af8cb1..ce32a96e 100644 --- a/lang/de_DE_gender_dudenkonform.ini +++ b/lang/de_DE_gender_dudenkonform.ini @@ -340,3 +340,7 @@ subpages = "Unterseiten" getstarted = "Los geht's" onthispage = "Auf dieser Seite" backtotop = "Nach oben" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/el_GR.ini b/lang/el_GR.ini index 777c38fc..69c5261a 100644 --- a/lang/el_GR.ini +++ b/lang/el_GR.ini @@ -342,3 +342,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/en_US.ini b/lang/en_US.ini index e1c41ae8..4ff0e705 100644 --- a/lang/en_US.ini +++ b/lang/en_US.ini @@ -407,3 +407,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/eo_EO.ini b/lang/eo_EO.ini index 0eaf827c..fa974159 100644 --- a/lang/eo_EO.ini +++ b/lang/eo_EO.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/es_ES.ini b/lang/es_ES.ini index 5e9dcdc9..8d0a2bcb 100644 --- a/lang/es_ES.ini +++ b/lang/es_ES.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/fa_IR.ini b/lang/fa_IR.ini index bd573eef..d24dc1ae 100644 --- a/lang/fa_IR.ini +++ b/lang/fa_IR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/fr_FR.ini b/lang/fr_FR.ini index 56e2c49e..8518be41 100644 --- a/lang/fr_FR.ini +++ b/lang/fr_FR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/gl_ES.ini b/lang/gl_ES.ini index b2867a66..a6888fa6 100644 --- a/lang/gl_ES.ini +++ b/lang/gl_ES.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/gu_GU.ini b/lang/gu_GU.ini index 227c0754..c944d5b0 100644 --- a/lang/gu_GU.ini +++ b/lang/gu_GU.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/hi_HI.ini b/lang/hi_HI.ini index 4a35a652..fbbad421 100644 --- a/lang/hi_HI.ini +++ b/lang/hi_HI.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/hr_HR.ini b/lang/hr_HR.ini index 7fe76419..d8c4481f 100644 --- a/lang/hr_HR.ini +++ b/lang/hr_HR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/hu_HU.ini b/lang/hu_HU.ini index c37f2cc0..42141d5e 100644 --- a/lang/hu_HU.ini +++ b/lang/hu_HU.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/id_ID.ini b/lang/id_ID.ini index 837f63dd..b172c35a 100644 --- a/lang/id_ID.ini +++ b/lang/id_ID.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/it_IT.ini b/lang/it_IT.ini index 4c1ff3a7..f76ba4a4 100644 --- a/lang/it_IT.ini +++ b/lang/it_IT.ini @@ -407,3 +407,7 @@ backtotop = "Torna in cima" subpages = "Sottopagine" getstarted = "Per cominciare" onthispage = "Su questa pagina" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/ko_KO.ini b/lang/ko_KO.ini index f2ce9e42..8c532ae8 100644 --- a/lang/ko_KO.ini +++ b/lang/ko_KO.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/ku_KU.ini b/lang/ku_KU.ini index 40444a0f..8d605def 100644 --- a/lang/ku_KU.ini +++ b/lang/ku_KU.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/ms_MY.ini b/lang/ms_MY.ini index da727ae4..670026aa 100644 --- a/lang/ms_MY.ini +++ b/lang/ms_MY.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/nl_NL.ini b/lang/nl_NL.ini index 867b4a00..bf0fc679 100644 --- a/lang/nl_NL.ini +++ b/lang/nl_NL.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/pl_PL.ini b/lang/pl_PL.ini index 38857936..9dfecee2 100644 --- a/lang/pl_PL.ini +++ b/lang/pl_PL.ini @@ -341,3 +341,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/pt_BR.ini b/lang/pt_BR.ini index dd34ab7d..50c2f8c7 100644 --- a/lang/pt_BR.ini +++ b/lang/pt_BR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/ru_RU.ini b/lang/ru_RU.ini index f4e07156..8a70e4e2 100644 --- a/lang/ru_RU.ini +++ b/lang/ru_RU.ini @@ -341,3 +341,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/sv_SE.ini b/lang/sv_SE.ini index 33e2ed8b..62a0d4d0 100644 --- a/lang/sv_SE.ini +++ b/lang/sv_SE.ini @@ -352,3 +352,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/tr_TR.ini b/lang/tr_TR.ini index 40765140..f8279c27 100644 --- a/lang/tr_TR.ini +++ b/lang/tr_TR.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/uk_UA.ini b/lang/uk_UA.ini index 908ff05c..0936d58e 100644 --- a/lang/uk_UA.ini +++ b/lang/uk_UA.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/zh_CN.ini b/lang/zh_CN.ini index 7dd4c09a..99682b91 100644 --- a/lang/zh_CN.ini +++ b/lang/zh_CN.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/lang/zh_TW.ini b/lang/zh_TW.ini index 670821c1..12fc1c9e 100644 --- a/lang/zh_TW.ini +++ b/lang/zh_TW.ini @@ -340,3 +340,7 @@ backtotop = "Back to top" subpages = "Sub pages" getstarted = "Get started" onthispage = "On this page" +keep_me_logged_in = "Keep me logged in" +session_security = "Session security" +ip_session_validation = "IP session validation" +ip_session_validation_explain = "Keep this enabled for better security. Disable only for users whose IP changes frequently (for example, mobile networks)." diff --git a/system/admin/admin.php b/system/admin/admin.php index 1e4a09f5..8c5848d7 100644 --- a/system/admin/admin.php +++ b/system/admin/admin.php @@ -46,7 +46,7 @@ function create_user($userName, $password, $role) } // Create a session -function session($user, $pass) +function session($user, $pass, $remember = false) { $user_file = 'config/users/' . $user . '.ini'; if (!file_exists($user_file)) { @@ -65,18 +65,24 @@ function session($user, $pass) if ($user_enc == "password_hash") { if (password_verify($pass, $user_pass)) { if (session_status() == PHP_SESSION_NONE) session_start(); + session_regenerate_id(true); if (password_needs_rehash($user_pass, PASSWORD_DEFAULT)) { update_user($user, $pass, $user_role, $mfa); } $_SESSION[site_url()]['user'] = $user; + $_SESSION[site_url()]['ip'] = current_session_ip(); + set_session_cookie_lifetime($remember ? time() + (86400 * 30) : 0); header('location: admin'); } else { return $str = '
'; } } else if (old_password_verify($pass, $user_enc, $user_pass)) { if (session_status() == PHP_SESSION_NONE) session_start(); + session_regenerate_id(true); update_user($user, $pass, $user_role, $mfa); $_SESSION[site_url()]['user'] = $user; + $_SESSION[site_url()]['ip'] = current_session_ip(); + set_session_cookie_lifetime($remember ? time() + (86400 * 30) : 0); header('location: admin'); } else { return $str = '
'; diff --git a/system/admin/views/config-security.html.php b/system/admin/views/config-security.html.php index 55dfe003..d9526f07 100644 --- a/system/admin/views/config-security.html.php +++ b/system/admin/views/config-security.html.php @@ -80,6 +80,29 @@ +
+

+
+
+ +
+
+
+ checked> + +
+
+ checked> + +
+
+ +
+
diff --git a/system/admin/views/login.html.php b/system/admin/views/login.html.php index 7bd42e07..3f4ee650 100644 --- a/system/admin/views/login.html.php +++ b/system/admin/views/login.html.php @@ -20,6 +20,10 @@ } } ?>" name="password" placeholder=""/>
+
+ > + +
diff --git a/system/admin/views/logout.html.php b/system/admin/views/logout.html.php index 19ab5c8c..f15c8d9f 100644 --- a/system/admin/views/logout.html.php +++ b/system/admin/views/logout.html.php @@ -2,6 +2,10 @@ generate_meta(null, null), 'username' => $user, 'password' => $pass, + 'remember' => $remember, 'type' => 'is_login', 'is_login' => true, 'bodyclass' => 'in-login', 'breadcrumb' => '' . config('breadcrumb.home') . ' » ' . i18n('Login') )); } else { - session($user, $pass); - $log = session($user, $pass); + $log = session($user, $pass, $remember); if (!empty($log)) { @@ -180,6 +182,7 @@ 'canonical' => site_url(), 'metatags' => generate_meta(null, null), 'error' => '', + 'remember' => $remember, 'type' => 'is_login', 'is_login' => true, 'bodyclass' => 'in-login', @@ -212,6 +215,7 @@ 'error' => '', 'username' => $user, 'password' => $pass, + 'remember' => $remember, 'type' => 'is_login', 'is_login' => true, 'bodyclass' => 'in-login', @@ -226,12 +230,12 @@ $proper = is_csrf_proper(from($_REQUEST, 'csrf_token')); $user = $_SESSION["mfa_uid"]; $pass = $_SESSION["mfa_pwd"]; + $remember = isset($_SESSION['mfa_remember']) && $_SESSION['mfa_remember'] === '1'; $mfacode = from($_REQUEST, 'mfacode'); $mfa_secret = user('mfa_secret', $user); $google2fa = new Google2FA(); if ($proper && $google2fa->verifyKey($mfa_secret, $mfacode, '1')) { - session($user, $pass); - $log = session($user, $pass); + $log = session($user, $pass, $remember); if (!empty($log)) { diff --git a/system/includes/session.php b/system/includes/session.php index 826294a8..27f8d23d 100644 --- a/system/includes/session.php +++ b/system/includes/session.php @@ -8,10 +8,71 @@ session_start(); +function current_session_ip() +{ + return isset($_SERVER['REMOTE_ADDR']) ? (string) $_SERVER['REMOTE_ADDR'] : ''; +} + +function is_session_ip_validation_enabled() +{ + $setting = config('session.ip.validation'); + return is_null($setting) || $setting === 'true'; +} + +function invalidate_auth_session() +{ + unset($_SESSION[site_url()]); + + if (session_status() === PHP_SESSION_ACTIVE) { + set_session_cookie_lifetime(time() - 3600); + } +} + +function set_session_cookie_lifetime($lifetime = 0) +{ + if (session_status() == PHP_SESSION_NONE || headers_sent()) { + return; + } + + $params = session_get_cookie_params(); + if (PHP_VERSION_ID < 70300) { + $path = isset($params['path']) ? $params['path'] : '/'; + $path .= '; samesite=' . $GLOBALS['samesite']; + setcookie(session_name(), session_id(), $lifetime, $path, $params['domain'], $params['secure'], $params['httponly']); + } else { + setcookie(session_name(), session_id(), array( + 'expires' => $lifetime, + 'path' => $params['path'], + 'domain' => $params['domain'], + 'secure' => $params['secure'], + 'httponly' => $params['httponly'], + 'samesite' => isset($params['samesite']) ? $params['samesite'] : 'strict' + )); + } +} + function login() { if (session_status() == PHP_SESSION_NONE) return false; if (isset($_SESSION[site_url()]['user']) && !empty($_SESSION[site_url()]['user'])) { + if (!is_session_ip_validation_enabled()) { + return true; + } + + $storedIp = isset($_SESSION[site_url()]['ip']) ? (string) $_SESSION[site_url()]['ip'] : ''; + $currentIp = current_session_ip(); + + // Backward compatibility for older sessions created before IP binding existed. + if ($storedIp === '' && $currentIp !== '') { + $_SESSION[site_url()]['ip'] = $currentIp; + return true; + } + + if ($storedIp !== '' && $currentIp !== '' && $storedIp !== $currentIp) { + invalidate_auth_session(); + return false; + } + return true; } else { return false; @@ -22,5 +83,6 @@ function login() if (isset($_SESSION['mfa_pwd']) && isset($_SESSION['mfa_uid'])) { unset($_SESSION['mfa_pwd']); unset($_SESSION['mfa_uid']); + unset($_SESSION['mfa_remember']); } }