From 53c312e3115797b2e3b3ff4339afbc845775c7e2 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 19:54:37 +0000 Subject: [PATCH 01/12] Add database column --- db.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db.sql b/db.sql index 1a649772..58fa1ae5 100644 --- a/db.sql +++ b/db.sql @@ -1166,6 +1166,7 @@ CREATE TABLE `users` ( `user_token` varchar(200) DEFAULT NULL, `user_avatar` varchar(200) DEFAULT NULL, `user_specific_encryption_ciphertext` varchar(200) DEFAULT NULL, + `user_extension_key` varchar(18) DEFAULT NULL, `user_created_at` datetime NOT NULL, `user_updated_at` datetime DEFAULT NULL, `user_archived_at` datetime DEFAULT NULL, From cee1faf0827a2c82ea49339f65c8a42cff2d1b5d Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 20:54:56 +0000 Subject: [PATCH 02/12] Add extension key cookie to login. Add support for storing the php session id in DB so we can access it (without passing the session ID over a cross-domain query). --- login.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/login.php b/login.php index 514def06..f0abe294 100644 --- a/login.php +++ b/login.php @@ -45,13 +45,24 @@ if(isset($_POST['login'])){ $user_name = $row['user_name']; $user_id = $row['user_id']; - //Setup encryption session key + // Setup encryption session key if(isset($row['user_specific_encryption_ciphertext'])){ $user_encryption_ciphertext = $row['user_specific_encryption_ciphertext']; $site_encryption_master_key = decryptUserSpecificKey($user_encryption_ciphertext, $password); generateUserSessionKey($site_encryption_master_key); } + // Setup extension + if(isset($row['user_extension_key']) && !empty($row['user_extension_key'])){ + // Extension cookie + setcookie("user_extension_key", "$row[user_extension_key]", ['path' => '/','secure' => true,'httponly' => true,'samesite' => 'None']); + + // Set PHP session in DB so we can access the session encryption data (above) + $user_php_session = session_id(); + mysqli_query($mysqli, "UPDATE users SET user_php_session = '$user_php_session' WHERE user_id = '$user_id'"); + + } + if(empty($token)){ $_SESSION['logged'] = TRUE; mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Success', log_description = '$user_name successfully logged in', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_user_id = $user_id"); From 272bf52d62b06e7d78190061caebfc4b697e2208 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 21:17:31 +0000 Subject: [PATCH 03/12] Note re https --- login.php | 1 + 1 file changed, 1 insertion(+) diff --git a/login.php b/login.php index f0abe294..2a924624 100644 --- a/login.php +++ b/login.php @@ -55,6 +55,7 @@ if(isset($_POST['login'])){ // Setup extension if(isset($row['user_extension_key']) && !empty($row['user_extension_key'])){ // Extension cookie + // Note: Browsers don't accept cookies with SameSite None if they are not HTTPS. setcookie("user_extension_key", "$row[user_extension_key]", ['path' => '/','secure' => true,'httponly' => true,'samesite' => 'None']); // Set PHP session in DB so we can access the session encryption data (above) From 2b3a7171b3a84240d3a82b99c709236fa4adb5af Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 21:26:22 +0000 Subject: [PATCH 04/12] Session management --- login.php | 5 +++-- post.php | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/login.php b/login.php index 2a924624..656c356c 100644 --- a/login.php +++ b/login.php @@ -24,9 +24,10 @@ if($config_https_only){ ini_set("session.cookie_secure", True); } -session_start(); - if(isset($_POST['login'])){ + + // Sessions should start after the user has POSTed data + session_start(); $email = strip_tags(mysqli_real_escape_string($mysqli,$_POST['email'])); $password = $_POST['password']; diff --git a/post.php b/post.php index 4b57a1a0..6aae84a1 100644 --- a/post.php +++ b/post.php @@ -6640,12 +6640,17 @@ if(isset($_GET['export_client_pdf'])){ if(isset($_GET['logout'])){ mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Logout', log_action = 'Success', log_description = '$session_name logged out', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_created_at = NOW(), log_user_id = $session_user_id"); + mysqli_query($mysqli, "UPDATE users SET user_php_session = '' WHERE user_id = '$session_user_id'"); - session_start(); + setcookie("PHPSESSID", '', time() - 3600, "/"); + unset($_COOKIE['PHPSESSID']); setcookie("user_encryption_session_key", '', time() - 3600, "/"); unset($_COOKIE['user_encryption_session_key']); + setcookie("user_extension_key", '', time() - 3600, "/"); + unset($_COOKIE['user_extension_key']); + session_unset(); session_destroy(); From 20a903324e5078c1e14ac953689d00b6a05056ab Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 21:27:36 +0000 Subject: [PATCH 05/12] Support for storing session ID in db --- db.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db.sql b/db.sql index 58fa1ae5..3a825397 100644 --- a/db.sql +++ b/db.sql @@ -1166,6 +1166,7 @@ CREATE TABLE `users` ( `user_token` varchar(200) DEFAULT NULL, `user_avatar` varchar(200) DEFAULT NULL, `user_specific_encryption_ciphertext` varchar(200) DEFAULT NULL, + `user_php_session` varchar(255) DEFAULT NULL, `user_extension_key` varchar(18) DEFAULT NULL, `user_created_at` datetime NOT NULL, `user_updated_at` datetime DEFAULT NULL, From 4ab28019c593e155fcf710c26379f89a354f7c20 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 21:35:59 +0000 Subject: [PATCH 06/12] Add logic for checking/getting extension key/php session id --- get_credential.php | 63 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/get_credential.php b/get_credential.php index fb1b8a84..03053f2b 100644 --- a/get_credential.php +++ b/get_credential.php @@ -1,5 +1,4 @@ Date: Sat, 15 Jan 2022 22:25:49 +0000 Subject: [PATCH 07/12] Adjust cookie setting to samesite none for encryption session key --- functions.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/functions.php b/functions.php index e38746b1..84266aca 100644 --- a/functions.php +++ b/functions.php @@ -368,10 +368,12 @@ function generateUserSessionKey($site_encryption_master_key){ $_SESSION['user_encryption_session_iv'] = $user_encryption_session_iv; //Give the user "their" key as a cookie - //By default, this should be HTTPS but we can change to HTTP for development via the config.php file + //By default, this should be HTTPS but we can change to HTTP for development via the config.php file (note that the extension won't work without HTTPS) include('config.php'); if($config_https_only){ - setcookie("user_encryption_session_key", $user_encryption_session_key, 0, "/", "", "true", "true"); + //setcookie("user_encryption_session_key", $user_encryption_session_key, 0, "/", "", "true", "true", ['samesite' => 'None']); + setcookie("user_encryption_session_key", "$user_encryption_session_key", ['path' => '/','secure' => true,'httponly' => true,'samesite' => 'None']); + } else{ setcookie("user_encryption_session_key", $user_encryption_session_key, 0, "/"); From 9c0cd254adb6f49b354f5293c90b4cd3971e0ef7 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 22:26:02 +0000 Subject: [PATCH 08/12] Fix user role display --- settings-user.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings-user.php b/settings-user.php index d3b8701a..621b47d1 100644 --- a/settings-user.php +++ b/settings-user.php @@ -30,7 +30,7 @@ $sql_recent_logs = mysqli_query($mysqli,"SELECT * FROM logs " class="img-circle img-fluid"> -

+


From c69fb5a7db56d28b75ec223438cc0a5175c3c10f Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 23:16:17 +0000 Subject: [PATCH 09/12] Add ability to turn on extension access (cookie) --- post.php | 20 ++++++++++++++++++++ settings-user.php | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/post.php b/post.php index 6aae84a1..76ecbae6 100644 --- a/post.php +++ b/post.php @@ -216,6 +216,9 @@ if(isset($_POST['edit_profile'])){ $existing_file_name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['existing_file_name']))); $logout = FALSE; + var_dump($_POST); + exit(); + //Check to see if a file is attached if($_FILES['file']['tmp_name'] != ''){ @@ -275,6 +278,23 @@ if(isset($_POST['edit_profile'])){ $logout = TRUE; } + // Enable extension access, only if it isn't already setup (user doesn't have cookie) + if(isset($_POST['extension']) && $_POST['extension'] == 'Yes'){ + if(!isset($_COOKIE['user_extension_key'])){ + $extension_key = keygen(); + mysqli_query($mysqli, "UPDATE users SET user_extension_key = '$extension_key' WHERE user_id = $user_id"); + + $extended_log_description .= ", extension access enabled"; + $logout = TRUE; + } + } + + // Disable extension access + if(!isset($_POST['extension'])){ + mysqli_query($mysqli, "UPDATE users SET user_extension_key = '' WHERE user_id = $user_id"); + $extended_log_description .= ", extension access disabled"; + } + //Logging mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'User Preferences', log_action = 'Modify', log_description = '$session_name modified their preferences$extended_log_description', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_created_at = NOW(), log_user_id = $session_user_id, company_id = $session_company_id"); diff --git a/settings-user.php b/settings-user.php index 621b47d1..32361bf4 100644 --- a/settings-user.php +++ b/settings-user.php @@ -72,6 +72,14 @@ $sql_recent_logs = mysqli_query($mysqli,"SELECT * FROM logs + +
+
+ > + +
+
+ From 24b5ffa09cbb008f73f0cf12a95ea5459a6bd5a7 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 23:19:09 +0000 Subject: [PATCH 10/12] Rem debugging --- post.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/post.php b/post.php index 76ecbae6..43ee26de 100644 --- a/post.php +++ b/post.php @@ -216,9 +216,6 @@ if(isset($_POST['edit_profile'])){ $existing_file_name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['existing_file_name']))); $logout = FALSE; - var_dump($_POST); - exit(); - //Check to see if a file is attached if($_FILES['file']['tmp_name'] != ''){ From 6e605a276e2b8247aca61cc704bade2dcfae6168 Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 23:39:30 +0000 Subject: [PATCH 11/12] Logging/extension related --- get_credential.php | 33 ++++++++++++++++++++++++++++++--- settings-user.php | 1 + 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/get_credential.php b/get_credential.php index 03053f2b..2e050c3f 100644 --- a/get_credential.php +++ b/get_credential.php @@ -10,17 +10,26 @@ if (isset($_SERVER['HTTP_ORIGIN'])) { header('Access-Control-Allow-Credentials: true'); } } -// Additionally, will require cookies set to SameSite None. include("config.php"); include("functions.php"); +//SESSION FINGERPRINT +$ip = strip_tags(mysqli_real_escape_string($mysqli,get_ip())); +$os = strip_tags(mysqli_real_escape_string($mysqli,get_os())); +$browser = strip_tags(mysqli_real_escape_string($mysqli,get_web_browser())); +$user_agent = "$os - $browser"; + // Check user is logged in & has extension access // We're not using the PHP session as we don't want to potentially expose the session cookie with SameSite None if(!isset($_COOKIE['user_extension_key'])){ $data['found'] = "FALSE"; $data['message'] = "ITFlow - You are not logged into ITFlow, do not have, or did not send the correct extension key cookie."; echo(json_encode($data)); + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Extension Failed', log_description = 'Failed login attempt using extension (get_credential.php)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW()"); + exit(); } @@ -28,10 +37,14 @@ if(!isset($_COOKIE['user_extension_key'])){ $user_extension_key = $_COOKIE['user_extension_key']; // Check the key isn't empty, less than 17 characters or the word "disabled". -if(empty($user_extension_key) OR strlen($user_extension_key) < 17 OR strtolower($user_extension_key) == "disabled"){ +if(empty($user_extension_key) OR strlen($user_extension_key) < 16 OR strtolower($user_extension_key) == "disabled"){ $data['found'] = "FALSE"; $data['message'] = "ITFlow - You are not logged into ITFlow, do not have, or did not send the correct extension key cookie."; echo(json_encode($data)); + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Extension Failed', log_description = 'Failed login attempt using extension (get_credential.php)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW()"); + exit(); } @@ -46,6 +59,10 @@ if(mysqli_num_rows($auth_user) < 1 OR !$auth_user){ $data['found'] = "FALSE"; $data['message'] = "ITFlow - You are not logged into ITFlow, do not have, or did not send the correct extension key cookie."; echo(json_encode($data)); + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Extension Failed', log_description = 'Failed login attempt using extension (get_credential.php)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW()"); + exit(); } @@ -54,6 +71,10 @@ if(hash('sha256', $row['user_extension_key']) !== hash('sha256', $_COOKIE['user_ $data['found'] = "FALSE"; $data['message'] = "ITFlow - Validation failed."; echo(json_encode($data)); + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Extension Failed', log_description = 'Failed login attempt using extension (get_credential.php)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW()"); + exit(); } @@ -89,6 +110,11 @@ if($session_user_role < 4){ $data['found'] = "FALSE"; $data['message'] = "ITFlow - You are not authorised to use this application."; echo(json_encode($data)); + + //Logging + $user_name = mysqli_real_escape_string($mysqli, $session_name); + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Extension Failed', log_description = '$user_name not authorised to use extension', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_user_id = $session_user_id"); + exit(); } @@ -110,7 +136,8 @@ if(isset($_GET['host'])){ // Logging $login_name = mysqli_real_escape_string($mysqli, $row['login_name']); - mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Extension requested', log_description = '$login_name' , log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); + $login_user = mysqli_real_escape_string($mysqli, $row['login_username']); + mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Extension requested', log_description = 'Credential $login_name, username $login_user' , log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); } } diff --git a/settings-user.php b/settings-user.php index 32361bf4..4a3e3f5b 100644 --- a/settings-user.php +++ b/settings-user.php @@ -77,6 +77,7 @@ $sql_recent_logs = mysqli_query($mysqli,"SELECT * FROM logs
> +

Note: You must log out and back in again for these changes take effect.

From 2dbf36bd5054d105c699627c9997f4d2a3e126ba Mon Sep 17 00:00:00 2001 From: Marcus Hill Date: Sat, 15 Jan 2022 23:43:29 +0000 Subject: [PATCH 12/12] Add IP / UA logging --- get_credential.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get_credential.php b/get_credential.php index 2e050c3f..ba71b562 100644 --- a/get_credential.php +++ b/get_credential.php @@ -137,7 +137,7 @@ if(isset($_GET['host'])){ // Logging $login_name = mysqli_real_escape_string($mysqli, $row['login_name']); $login_user = mysqli_real_escape_string($mysqli, $row['login_username']); - mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Extension requested', log_description = 'Credential $login_name, username $login_user' , log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); + mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Extension requested', log_description = 'Credential $login_name, username $login_user', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); } }