diff --git a/client_assets.php b/client_assets.php index cb7c389a..ef0fef63 100644 --- a/client_assets.php +++ b/client_assets.php @@ -39,7 +39,7 @@ if(isset($_GET['o'])){ //Rebuild URL $url_query_strings_sb = http_build_query(array_merge($_GET,array('sb' => $sb, 'o' => $o))); -$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM assets LEFT JOIN contacts ON asset_contact_id = contact_id LEFT JOIN locations ON asset_location_id = location_id LEFT JOIN logins ON login_asset_id = asset_id +$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM assets LEFT JOIN contacts ON asset_contact_id = contact_id LEFT JOIN locations ON asset_location_id = location_id LEFT JOIN logins ON login_asset_id = asset_id WHERE asset_client_id = $client_id AND (asset_name LIKE '%$q%' OR asset_type LIKE '%$q%' OR asset_ip LIKE '%$q%' OR asset_make LIKE '%$q%' OR asset_model LIKE '%$q%' OR asset_serial LIKE '%$q%' OR asset_os LIKE '%$q%' OR contact_name LIKE '%$q%' OR location_name LIKE '%$q%') ORDER BY $sb $o LIMIT $record_from, $record_to"); @@ -178,7 +178,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli,"SELECT FOUND_ROWS()")); $login_id = $row['login_id']; $login_username = $row['login_username']; - $login_password = $row['login_password']; + $login_password = decryptLoginEntry($row['login_password']); ?> diff --git a/client_logins.php b/client_logins.php index d56f2468..448f5c29 100644 --- a/client_logins.php +++ b/client_logins.php @@ -41,7 +41,7 @@ if(isset($_GET['o'])){ //Rebuild URL $url_query_strings_sb = http_build_query(array_merge($_GET,array('sb' => $sb, 'o' => $o))); -$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM logins +$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM logins WHERE login_client_id = $client_id AND (login_name LIKE '%$q%' OR login_username LIKE '%$q%' OR login_uri LIKE '%$q%') ORDER BY $sb $o LIMIT $record_from, $record_to"); @@ -112,7 +112,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli,"SELECT FOUND_ROWS()")); }else{ $login_username_display = "$login_username"; } - $login_password = htmlentities($row['login_password']); + $login_password = htmlentities(decryptLoginEntry($row['login_password'])); $login_otp_secret = $row['login_otp_secret']; if(empty($login_otp_secret)){ $otp_display = "-"; diff --git a/client_software.php b/client_software.php index 53eb432a..313bc27b 100644 --- a/client_software.php +++ b/client_software.php @@ -39,7 +39,7 @@ if(isset($_GET['o'])){ //Rebuild URL $url_query_strings_sb = http_build_query(array_merge($_GET,array('sb' => $sb, 'o' => $o))); -$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM software LEFT JOIN logins ON login_software_id = software_id +$sql = mysqli_query($mysqli,"SELECT SQL_CALC_FOUND_ROWS * FROM software LEFT JOIN logins ON login_software_id = software_id WHERE software_client_id = $client_id AND (software_name LIKE '%$q%' OR software_type LIKE '%$q%' OR software_license LIKE '%$q%') ORDER BY $sb $o LIMIT $record_from, $record_to"); @@ -107,7 +107,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli,"SELECT FOUND_ROWS()")); $login_id = $row['login_id']; $login_username = $row['login_username']; - $login_password = $row['login_password']; + $login_password = decryptLoginEntry($row['login_password']); ?> diff --git a/db.sql b/db.sql index 2e05140e..d94d0451 100644 --- a/db.sql +++ b/db.sql @@ -889,7 +889,7 @@ DROP TABLE IF EXISTS `settings`; CREATE TABLE `settings` ( `company_id` int(11) NOT NULL, `config_api_key` varchar(200) DEFAULT NULL, - `config_aes_key` varchar(250) DEFAULT NULL, + `config_aes_key` varchar(250) DEFAULT NULL COMMENT 'Legacy', `config_base_url` varchar(200) DEFAULT NULL, `config_smtp_host` varchar(200) DEFAULT NULL, `config_smtp_port` int(5) DEFAULT NULL, @@ -1163,6 +1163,7 @@ CREATE TABLE `users` ( `user_email` varchar(200) NOT NULL, `user_password` varchar(200) NOT NULL, `user_token` varchar(200) DEFAULT NULL, + `user_specific_encryption_ciphertext` varchar(200) DEFAULT NULL, `user_avatar` varchar(200) DEFAULT NULL, `user_created_at` datetime NOT NULL, `user_updated_at` datetime DEFAULT NULL, diff --git a/functions.php b/functions.php index 0bac4894..e38746b1 100644 --- a/functions.php +++ b/functions.php @@ -159,15 +159,15 @@ function get_device(){ } } if ($tablet_browser > 0) { - // do something for tablet devices + //do something for tablet devices return 'Tablet'; } else if ($mobile_browser > 0) { - // do something for mobile devices + //do something for mobile devices return 'Mobile'; } else { - // do something for everything else + //do something for everything else return 'Computer'; } } @@ -287,4 +287,148 @@ function mkdir_missing($dir) { } } +//Called during initial setup +//Encrypts the master key with the user's password +function setupFirstUserSpecificKey($user_password, $site_encryption_master_key){ + $iv = keygen(); + $salt = keygen(); + + //Generate 128-bit (16 byte/char) kdhash of the users password + $user_password_kdhash = hash_pbkdf2('sha256', $user_password, $salt, 100000, 16); + + //Encrypt the master key with the users kdf'd hash and the IV + $ciphertext = openssl_encrypt($site_encryption_master_key, 'aes-128-cbc', $user_password_kdhash, 0, $iv); + + $user_encryption_ciphertext = $salt . $iv . $ciphertext; + + return $user_encryption_ciphertext; +} + +/* +For additional users / password changes +New Users: Requires the admin setting up their account have the their own Specific/Session key configured +Password Changes: Will use the current info in the session. +*/ +function encryptUserSpecificKey($user_password){ + $iv = keygen(); + $salt = keygen(); + + //Get the session info. + $user_encryption_session_ciphertext = $_SESSION['user_encryption_session_ciphertext']; + $user_encryption_session_iv = $_SESSION['user_encryption_session_iv']; + $user_encryption_session_key = $_COOKIE['user_encryption_session_key']; + + //Decrypt the session key to get the master key + $site_encryption_master_key = openssl_decrypt($user_encryption_session_ciphertext, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv); + + //Generate 128-bit (16 byte/char) kdhash of the users (new) password + $user_password_kdhash = hash_pbkdf2('sha256', $user_password, $salt, 100000, 16); + + //Encrypt the master key with the users kdf'd hash and the IV + $ciphertext = openssl_encrypt($site_encryption_master_key, 'aes-128-cbc', $user_password_kdhash, 0, $iv); + + $user_encryption_ciphertext = $salt . $iv . $ciphertext; + + return $user_encryption_ciphertext; + +} + +//Given a ciphertext (incl. IV) and the user's password, returns the site master key +//Ran at login, to facilitate generateUserSessionKey +function decryptUserSpecificKey($user_encryption_ciphertext, $user_password){ + //Get the IV, salt and ciphertext + $salt = substr($user_encryption_ciphertext, 0, 16); + $iv = substr($user_encryption_ciphertext, 16, 16); + $ciphertext = substr($user_encryption_ciphertext, 32); + + //Generate 128-bit (16 byte/char) kdhash of the users password + $user_password_kdhash = hash_pbkdf2('sha256', $user_password, $salt, 100000, 16); + + //Use this hash to get the original/master key + $site_encryption_master_key = openssl_decrypt($ciphertext, 'aes-128-cbc', $user_password_kdhash, 0, $iv); + return $site_encryption_master_key; +} + +/* +Generates what is probably best described as an session key (ephemeral-ish) +- Allows us to store the master key on the server whilst the user is using the application, without prompting to type their password everytime they want to decrypt a credential +- Ciphertext/IV is stored on the server in the users session, encryption key is controlled/provided by the user as a cookie +- Only the user can decrypt their session ciphertext to get the master key +- Encryption key never hits the disk in cleartext +*/ +function generateUserSessionKey($site_encryption_master_key){ + + //Generate both of these using keygen() + $user_encryption_session_key = keygen(); + $user_encryption_session_iv = keygen(); + $user_encryption_session_ciphertext = openssl_encrypt($site_encryption_master_key, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv); + + //Store ciphertext in the user's session + $_SESSION['user_encryption_session_ciphertext'] = $user_encryption_session_ciphertext; + $_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 + include('config.php'); + if($config_https_only){ + setcookie("user_encryption_session_key", $user_encryption_session_key, 0, "/", "", "true", "true"); + } + else{ + setcookie("user_encryption_session_key", $user_encryption_session_key, 0, "/"); + $_SESSION['alert_message'] = "Unencrypted connection flag set: Using non-secure cookies."; + } +} + +//Decrypts an encrypted password (website/asset login), returns it as a string +function decryptLoginEntry($login_password_ciphertext){ + + //Split the login into IV and Ciphertext + $login_iv = substr($login_password_ciphertext, 0, 16); + $login_ciphertext = $salt = substr($login_password_ciphertext, 16); + + //Get the user session info. + $user_encryption_session_ciphertext = $_SESSION['user_encryption_session_ciphertext']; + $user_encryption_session_iv = $_SESSION['user_encryption_session_iv']; + $user_encryption_session_key = $_COOKIE['user_encryption_session_key']; + + //Decrypt the session key to get the master key + $site_encryption_master_key = openssl_decrypt($user_encryption_session_ciphertext, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv); + + //Decrypt the login password using the master key + $login_password_cleartext = openssl_decrypt($login_ciphertext, 'aes-128-cbc', $site_encryption_master_key, 0, $login_iv); + return $login_password_cleartext; + +} + +//Encrypts a website/asset login password +function encryptLoginEntry($login_password_cleartext){ + $iv = keygen(); + + //Get the user session info. + $user_encryption_session_ciphertext = $_SESSION['user_encryption_session_ciphertext']; + $user_encryption_session_iv = $_SESSION['user_encryption_session_iv']; + $user_encryption_session_key = $_COOKIE['user_encryption_session_key']; + + //Decrypt the session key to get the master key + $site_encryption_master_key = openssl_decrypt($user_encryption_session_ciphertext, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv); + + //Encrypt the website/asset login using the master key + $ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $site_encryption_master_key, 0, $iv); + + $login_password_ciphertext = $iv . $ciphertext; + return $login_password_ciphertext; +} + +//For migrating/upgrading to the new encryption scheme +//Have to supply the master key as the cookie might not be set properly (generally requires a refresh) +function encryptUpgradeLoginEntry($login_password_cleartext, $site_encryption_master_key){ + $iv = keygen(); + + //Encrypt the website/asset login using the master key + $ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $site_encryption_master_key, 0, $iv); + + $login_password_ciphertext = $iv . $ciphertext; + return $login_password_ciphertext; +} + ?> \ No newline at end of file diff --git a/get_settings.php b/get_settings.php index 0e3d32a7..aae75a6d 100644 --- a/get_settings.php +++ b/get_settings.php @@ -6,7 +6,7 @@ $row = mysqli_fetch_array($sql_settings); //General $config_api_key = $row['config_api_key']; -$config_aes_key = $row['config_aes_key']; +$config_aes_key = $row['config_aes_key']; //Legacy $config_base_url = $row['config_base_url']; //Mail diff --git a/login.php b/login.php index 4eeadd03..514def06 100644 --- a/login.php +++ b/login.php @@ -45,6 +45,13 @@ if(isset($_POST['login'])){ $user_name = $row['user_name']; $user_id = $row['user_id']; + //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); + } + 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"); diff --git a/post.php b/post.php index 31919d47..bcf9459d 100644 --- a/post.php +++ b/post.php @@ -53,10 +53,11 @@ if(isset($_POST['add_user'])){ $name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['name']))); $email = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['email']))); $password = password_hash($_POST['password'], PASSWORD_DEFAULT); + $user_specific_encryption_ciphertext = encryptUserSpecificKey($_POST['password']); //TODO: Consider this users role - if they don't need access to logins, potentially don't set this -- just know it's a pain to add afterwards (you'd need to reset their password). $default_company = intval($_POST['default_company']); $role = intval($_POST['role']); - mysqli_query($mysqli,"INSERT INTO users SET user_name = '$name', user_email = '$email', user_password = '$password', user_created_at = NOW()"); + mysqli_query($mysqli,"INSERT INTO users SET user_name = '$name', user_email = '$email', user_password = '$password', user_specific_encryption_ciphertext = '$user_specific_encryption_ciphertext', user_created_at = NOW()"); $user_id = mysqli_insert_id($mysqli); @@ -188,7 +189,8 @@ if(isset($_POST['edit_user'])){ if(!empty($new_password)){ $new_password = password_hash($new_password, PASSWORD_DEFAULT); - mysqli_query($mysqli,"UPDATE users SET user_password = '$new_password' WHERE user_id = $user_id"); + $user_specific_encryption_ciphertext = encryptUserSpecificKey($_POST['new_password']); + mysqli_query($mysqli,"UPDATE users SET user_password = '$new_password', user_specific_encryption_ciphertext = '$user_specific_encryption_ciphertext' WHERE user_id = $user_id"); //Extended Logging $extended_log_description .= ", password changed"; } @@ -212,6 +214,7 @@ if(isset($_POST['edit_profile'])){ $email = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['email']))); $new_password = trim($_POST['new_password']); $existing_file_name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['existing_file_name']))); + $logout = FALSE; //Check to see if a file is attached if($_FILES['file']['tmp_name'] != ''){ @@ -265,18 +268,24 @@ if(isset($_POST['edit_profile'])){ if(!empty($new_password)){ $new_password = password_hash($new_password, PASSWORD_DEFAULT); - mysqli_query($mysqli,"UPDATE users SET user_password = '$new_password' WHERE user_id = $user_id"); + $user_specific_encryption_ciphertext = encryptUserSpecificKey($_POST['new_password']); + mysqli_query($mysqli,"UPDATE users SET user_password = '$new_password', user_specific_encryption_ciphertext = '$user_specific_encryption_ciphertext' WHERE user_id = $user_id"); $extended_log_description .= ", password changed"; + $logout = TRUE; } //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"); $_SESSION['alert_message'] = "User preferences updated"; - - header("Location: " . $_SERVER["HTTP_REFERER"]); + if ($logout){ + header('Location: post.php?logout'); + } + else{ + header("Location: " . $_SERVER["HTTP_REFERER"]); + } } if(isset($_POST['edit_user_companies'])){ @@ -390,7 +399,6 @@ if(isset($_POST['add_company'])){ $company_id = mysqli_insert_id($mysqli); $config_base_url = $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']); $config_api_key = keygen(); - $config_aes_key = keygen(); mkdir("uploads/clients/$company_id"); mkdir("uploads/expenses/$company_id"); @@ -442,7 +450,7 @@ if(isset($_POST['add_company'])){ //Set User Company Permissions mysqli_query($mysqli,"INSERT INTO user_companies SET user_id = $session_user_id, company_id = $company_id"); - mysqli_query($mysqli,"INSERT INTO settings SET company_id = $company_id, config_invoice_prefix = 'INV-', config_invoice_next_number = 1, config_recurring_prefix = 'REC-', config_recurring_next_number = 1, config_invoice_overdue_reminders = '1,3,7', config_quote_prefix = 'QUO-', config_quote_next_number = 1, config_api_key = '$config_api_key', config_aes_key = '$config_aes_key', config_recurring_auto_send_invoice = 1, config_default_net_terms = 7, config_send_invoice_reminders = 1, config_enable_cron = 0, config_ticket_next_number = 1, config_base_url = '$config_base_url'"); + mysqli_query($mysqli,"INSERT INTO settings SET company_id = $company_id, config_invoice_prefix = 'INV-', config_invoice_next_number = 1, config_recurring_prefix = 'REC-', config_recurring_next_number = 1, config_invoice_overdue_reminders = '1,3,7', config_quote_prefix = 'QUO-', config_quote_next_number = 1, config_api_key = '$config_api_key', config_recurring_auto_send_invoice = 1, config_default_net_terms = 7, config_send_invoice_reminders = 1, config_enable_cron = 0, config_ticket_next_number = 1, config_base_url = '$config_base_url'"); //Create Some Data @@ -655,24 +663,24 @@ if(isset($_POST['verify'])){ if(isset($_POST['edit_general_settings'])){ $config_api_key = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['config_api_key']))); - $old_aes_key = $config_aes_key; - $config_aes_key = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['config_aes_key']))); + //$old_aes_key = $config_aes_key; + //$config_aes_key = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['config_aes_key']))); $config_base_url = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['config_base_url']))); - mysqli_query($mysqli,"UPDATE settings SET config_api_key = '$config_api_key', config_aes_key = '$config_aes_key', config_base_url = '$config_base_url' WHERE company_id = $session_company_id"); + mysqli_query($mysqli,"UPDATE settings SET config_api_key = '$config_api_key', config_base_url = '$config_base_url' WHERE company_id = $session_company_id"); - //Update AES key on client_logins if changed - if($old_aes_key != $config_aes_key){ - $sql = mysqli_query($mysqli,"SELECT login_id, AES_DECRYPT(login_password, '$old_aes_key') AS old_login_password FROM logins - WHERE company_id = $session_company_id"); - - while($row = mysqli_fetch_array($sql)){ - $login_id = $row['login_id']; - $old_login_password = $row['old_login_password']; - - mysqli_query($mysqli,"UPDATE logins SET login_password = AES_ENCRYPT('$old_login_password','$config_aes_key') WHERE login_id = $login_id"); - } - } +// //Update AES key on client_logins if changed +// if($old_aes_key != $config_aes_key){ +// $sql = mysqli_query($mysqli,"SELECT login_id, AES_DECRYPT(login_password, '$old_aes_key') AS old_login_password FROM logins +// WHERE company_id = $session_company_id"); +// +// while($row = mysqli_fetch_array($sql)){ +// $login_id = $row['login_id']; +// $old_login_password = $row['old_login_password']; +// +// mysqli_query($mysqli,"UPDATE logins SET login_password = AES_ENCRYPT('$old_login_password','$config_aes_key') WHERE login_id = $login_id"); +// } +// } //Logging mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Settings', log_action = 'Modify', log_description = '$session_name modified general settings', 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"); @@ -939,6 +947,38 @@ if(isset($_GET['download_database'])){ $_SESSION['alert_message'] = "Database downloaded"; } +if(isset($_POST['backup_master_key'])){ + + //TODO: Verify the user is authorised to view the key? + + $password = $_POST['password']; + + $sql = mysqli_query($mysqli, "SELECT * FROM users WHERE user_id = '$session_user_id'"); + $userRow = mysqli_fetch_array($sql); + + if(password_verify($password, $userRow['user_password'])) { + $site_encryption_master_key = decryptUserSpecificKey($userRow['user_specific_encryption_ciphertext'], $password); + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Settings', log_action = 'Download', log_description = '$session_name retrieved the master encryption key', 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"); + mysqli_query($mysqli,"INSERT INTO alerts SET alert_type = 'Settings', alert_message = '$session_name retrieved the master encryption key', alert_date = NOW(), company_id = $session_company_id"); + + + echo "=============================="; + echo "
Master encryption key:
"; + echo "$site_encryption_master_key"; + echo "
=============================="; + } + + else { + //Log the failure + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Settings', log_action = 'Download', log_description = '$session_name attempted to retrieve the master encryption key (failure)', 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"); + + $_SESSION['alert_message'] = "Incorrect password."; + header("Location: " . $_SERVER["HTTP_REFERER"]); + } +} + if(isset($_GET['update'])){ //also check to make sure someone has admin before running this function exec("git pull"); @@ -988,6 +1028,83 @@ if(isset($_GET['update_db'])){ header("Location: " . $_SERVER["HTTP_REFERER"]); } +if(isset($_POST['encryption_update'])){ + $password = $_POST['password']; + + //Get user details + $sql = mysqli_query($mysqli,"SELECT * FROM users WHERE user_id = '$session_user_id'"); + $row = mysqli_fetch_array($sql); + + //Verify the users password + if(!password_verify($password, $row['user_password'])){ + $_SESSION['alert_message'] = "User password incorrect."; + header("Location: " . $_SERVER["HTTP_REFERER"]); + exit(); + } + + //First, check if this user is setup for the new encryption setup + if(isset($row['user_specific_encryption_ciphertext'])){ + echo "Ciphertext data already exists, using it.
"; + $user_encryption_ciphertext = $row['user_specific_encryption_ciphertext']; + $site_encryption_master_key = decryptUserSpecificKey($user_encryption_ciphertext, $password); + } + else{ + echo "User ciphertext data not found, attempting to add it.
"; + $update_table = mysqli_query($mysqli, "ALTER TABLE `users` ADD `user_specific_encryption_ciphertext` VARCHAR(200) NULL AFTER `user_avatar`; "); + + if(!$update_table){ + echo "Error adding ciphertext column (user_specific_encryption_ciphertext) to users table.
"; + echo "Either there was a connection/permissions issue or the column already exists (due to a upgrade already taking place?)
"; + echo "Quitting to prevent compromising data integrity. Delete the column if you are sure you need to upgrade (presuming it contains no data).
"; + exit(); + } + + echo "Ciphertext column added successfully!
"; + + echo "Generating new master key.
"; + $site_encryption_master_key = keygen(); + echo "New master key is: $site_encryption_master_key
"; + $user_encryption_ciphertext = setupFirstUserSpecificKey($password, $site_encryption_master_key); + + $set_user_specific_key = mysqli_query($mysqli, "UPDATE users SET user_specific_encryption_ciphertext = '$user_encryption_ciphertext' WHERE user_id = '$session_user_id'"); + if(!$set_user_specific_key){ + echo "Something went wrong adding your user specific key.
"; + exit(); + } + + //Setup the user session key + generateUserSessionKey($site_encryption_master_key); + + //Invalidate user passwords + //If we don't do this, users won't be able to see the new passwords properly, and could potentially add passwords that can never be decrypted + mysqli_query($mysqli, "UPDATE users SET user_password = 'Invalid due to upgrade' WHERE user_id NOT IN ($session_user_id)"); + $extended_log_description = ", invalidated all user passwords"; + echo "Invalidated all user passwords. You must re-set them from this user account.
"; + } + + //Either way, if we got here we now have the master key as $site_encryption_master_key + + //Get & upgrade user login encryption + $sql_logins = mysqli_query($mysqli,"SELECT *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM logins WHERE (company_id = '$session_company_id' AND login_password IS NOT NULL)"); + $count = 0; + foreach ($sql_logins as $row){ + $login_id = $row['login_id']; + $new_encrypted_password = encryptUpgradeLoginEntry($row['login_password'], $site_encryption_master_key); + mysqli_query($mysqli, "UPDATE logins SET login_password = '$new_encrypted_password' WHERE login_id = '$login_id'"); + $count++; + } + echo "Upgraded $count records.
"; + + //Logging + mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Settings', log_action = 'Migrate', log_description = '$session_name upgraded company ID $session_company_id logins ($count total) to the new encryption scheme$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"); + + echo "Migration for company successful.
"; + $_SESSION['alert_message'] = "Migration for company successful."; + + echo "Back to settings."; + +} + if(isset($_POST['add_client'])){ $name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['name']))); @@ -4117,9 +4234,9 @@ if(isset($_POST['add_asset'])){ if(!empty($_POST['username'])) { $asset_id = mysqli_insert_id($mysqli); $username = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['username']))); - $password = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['password']))); + $password = trim(mysqli_real_escape_string($mysqli,encryptLoginEntry($_POST['password']))); - mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_created_at = NOW(), login_asset_id = $asset_id, login_client_id = $client_id, company_id = $session_company_id"); + mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_created_at = NOW(), login_asset_id = $asset_id, login_client_id = $client_id, company_id = $session_company_id"); } @@ -4242,12 +4359,12 @@ if(isset($_POST['edit_asset'])){ //If login exists then update the login if($login_id > 0){ - mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_updated_at = NOW() WHERE login_id = $login_id AND company_id = $session_company_id"); + mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_updated_at = NOW() WHERE login_id = $login_id AND company_id = $session_company_id"); }else{ //If Username is filled in then add a login if(!empty($username)) { - mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_created_at = NOW(), login_asset_id = $asset_id, login_client_id = $client_id, company_id = $session_company_id"); + mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_created_at = NOW(), login_asset_id = $asset_id, login_client_id = $client_id, company_id = $session_company_id"); } } @@ -4329,9 +4446,9 @@ if(isset($_POST['add_software'])){ if(!empty($_POST['username'])) { $software_id = mysqli_insert_id($mysqli); $username = strip_tags(mysqli_real_escape_string($mysqli,$_POST['username'])); - $password = strip_tags(mysqli_real_escape_string($mysqli,$_POST['password'])); + $password = trim(mysqli_real_escape_string($mysqli,encryptLoginEntry($_POST['password']))); - mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_software_id = $software_id, login_created_at = NOW(), login_client_id = $client_id, company_id = $session_company_id"); + mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_software_id = $software_id, login_created_at = NOW(), login_client_id = $client_id, company_id = $session_company_id"); } @@ -4353,18 +4470,18 @@ if(isset($_POST['edit_software'])){ $license = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['license']))); $notes = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['notes']))); $username = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['username']))); - $password = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['password']))); + $password = trim(mysqli_real_escape_string($mysqli,encryptLoginEntry($_POST['password']))); mysqli_query($mysqli,"UPDATE software SET software_name = '$name', software_type = '$type', software_license = '$license', software_notes = '$notes', software_updated_at = NOW() WHERE software_id = $software_id AND company_id = $session_company_id"); //If login exists then update the login if($login_id > 0){ - mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_updated_at = NOW() WHERE login_id = $login_id AND company_id = $session_company_id"); + mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_updated_at = NOW() WHERE login_id = $login_id AND company_id = $session_company_id"); }else{ //If Username is filled in then add a login if(!empty($username)) { - mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_created_at = NOW(), login_software_id = $software_id, login_client_id = $client_id, company_id = $session_company_id"); + mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_username = '$username', login_password = '$password', login_created_at = NOW(), login_software_id = $software_id, login_client_id = $client_id, company_id = $session_company_id"); } } @@ -4439,14 +4556,14 @@ if(isset($_POST['add_login'])){ $name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['name']))); $uri = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['uri']))); $username = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['username']))); - $password = trim(mysqli_real_escape_string($mysqli,$_POST['password'])); + $password = trim(mysqli_real_escape_string($mysqli,encryptLoginEntry($_POST['password']))); $otp_secret = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['otp_secret']))); $note = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['note']))); $vendor_id = intval($_POST['vendor']); $asset_id = intval($_POST['asset']); $software_id = intval($_POST['software']); - mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_uri = '$uri', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_otp_secret = '$otp_secret', login_note = '$note', login_created_at = NOW(), login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id, company_id = $session_company_id"); + mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_uri = '$uri', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_created_at = NOW(), login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id, company_id = $session_company_id"); //Logging mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Created', log_description = '$name', log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); @@ -4463,14 +4580,14 @@ if(isset($_POST['edit_login'])){ $name = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['name']))); $uri = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['uri']))); $username = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['username']))); - $password = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['password']))); + $password = trim(mysqli_real_escape_string($mysqli,encryptLoginEntry($_POST['password']))); $otp_secret = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['otp_secret']))); $note = trim(strip_tags(mysqli_real_escape_string($mysqli,$_POST['note']))); $vendor_id = intval($_POST['vendor']); $asset_id = intval($_POST['asset']); $software_id = intval($_POST['software']); - mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_uri = '$uri', login_username = '$username', login_password = AES_ENCRYPT('$password','$config_aes_key'), login_otp_secret = '$otp_secret', login_note = '$note', login_updated_at = NOW(), login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id WHERE login_id = $login_id AND company_id = $session_company_id"); + mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_uri = '$uri', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_updated_at = NOW(), login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id WHERE login_id = $login_id AND company_id = $session_company_id"); //Logging mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'Modified', log_description = '$name', log_created_at = NOW(), company_id = $session_company_id, log_user_id = $session_user_id"); @@ -4504,7 +4621,7 @@ if(isset($_GET['export_client_logins_csv'])){ $client_name = $row['client_name']; - $sql = mysqli_query($mysqli,"SELECT *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM logins WHERE login_client_id = $client_id ORDER BY login_name ASC"); + $sql = mysqli_query($mysqli,"SELECT * FROM logins WHERE login_client_id = $client_id ORDER BY login_name ASC"); if($sql->num_rows > 0){ $delimiter = ","; $filename = $client_name . "-Logins-" . date('Y-m-d') . ".csv"; @@ -4518,7 +4635,8 @@ if(isset($_GET['export_client_logins_csv'])){ //output each row of the data, format line as csv and write to file pointer while($row = $sql->fetch_assoc()){ - $lineData = array($row['login_name'], $row['login_username'], $row['login_password'], $row['login_uri'], $row['login_note']); + $login_password = decryptLoginEntry($row['login_password']); + $lineData = array($row['login_name'], $row['login_username'], $login_password, $row['login_uri'], $row['login_note']); fputcsv($f, $lineData, $delimiter); } @@ -5681,7 +5799,7 @@ if(isset($_GET['export_client_pdf'])){ $sql_locations = mysqli_query($mysqli,"SELECT * FROM locations WHERE location_client_id = $client_id ORDER BY location_name ASC"); $sql_vendors = mysqli_query($mysqli,"SELECT * FROM vendors WHERE vendor_client_id = $client_id ORDER BY vendor_name ASC"); if(isset($_GET['passwords'])){ - $sql_logins = mysqli_query($mysqli,"SELECT *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM logins WHERE login_client_id = $client_id ORDER BY login_name ASC"); + $sql_logins = mysqli_query($mysqli,"SELECT * FROM logins WHERE login_client_id = $client_id ORDER BY login_name ASC"); } $sql_assets = mysqli_query($mysqli,"SELECT * FROM assets WHERE asset_client_id = $client_id ORDER BY asset_type ASC"); $sql_networks = mysqli_query($mysqli,"SELECT * FROM networks WHERE network_client_id = $client_id ORDER BY network_name ASC"); @@ -6022,7 +6140,7 @@ if(isset($_GET['export_client_pdf'])){ while($row = mysqli_fetch_array($sql_logins)){ $login_name = $row['login_name']; $login_username = $row['login_username']; - $login_password = $row['login_password']; + $login_password = decryptLoginEntry($row['login_password']); $login_uri = $row['login_uri']; $login_note = $row['login_note']; ?> @@ -6447,7 +6565,13 @@ 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"); session_start(); + + setcookie("user_encryption_session_key", '', time() - 3600, "/"); + unset($_COOKIE['user_encryption_session_key']); + + session_unset(); session_destroy(); + header('Location: login.php'); } diff --git a/settings-backup.php b/settings-backup.php index be66aa29..601c0bde 100644 --- a/settings-backup.php +++ b/settings-backup.php @@ -4,7 +4,7 @@
-

Backup

+

Backup Database

@@ -13,4 +13,26 @@
+

+ +
+
+

Backup Master Encryption Key

+
+
+
+ +
+
+ +
+
+
+ +
+
+
+
+
+ -
- -
-
- -
- -
- -
-
- This will also update the key on all client logins -
-
diff --git a/settings-update.php b/settings-update.php index b0f54a20..05f740cb 100644 --- a/settings-update.php +++ b/settings-update.php @@ -61,4 +61,61 @@ $git_log = shell_exec("git log master..origin/master --pretty=format:'%h
+ +
+
+

Update AES Key

+
+
+
+
+ +
+"; +echo "Current User ID: $session_user_id
"; + +if ($config_aes_key) { + echo "Current (legacy) AES key: $config_aes_key

"; + echo "Below are the decrypted credentials for five login entries, please confirm they show and are correct before continuing.
Do NOT continue if no entries are shown or if the decrypted passwords are incorrect.

"; + $sql = mysqli_query($mysqli,"SELECT *, AES_DECRYPT(login_password, '$config_aes_key') AS login_password FROM logins WHERE (company_id = '$session_company_id' AND login_password IS NOT NULL) LIMIT 5"); + foreach ($sql as $row){ + echo $row['login_username'] . ":" . $row['login_password']; + echo "
"; + } + echo "
"; + ?> + +
+
+
+ +
+
+

Warning: This action is irreversible. Do NOT proceed without a backup.

+ +
+
+"; + echo "Please ensure upgrade is required. If you are sure you need to update, ensure the AES key is set correctly for this company."; +} + +?> +
+
+
+