(NOW() - INTERVAL 10 MINUTE)")); $failed_login_count = intval($row['failed_login_count']); if ($failed_login_count >= 15) { // Logging mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Blocked', log_description = '$ip was blocked access to login due to IP lockout', log_ip = '$ip', log_user_agent = '$user_agent'"); // Inform user & quit processing page exit("

$config_app_name

Your IP address has been blocked due to repeated failed login attempts. Please try again later.

This action has been logged."); } // Query Settings for company $sql_settings = mysqli_query($mysqli, "SELECT * FROM settings LEFT JOIN companies ON settings.company_id = companies.company_id WHERE settings.company_id = 1"); $row = mysqli_fetch_array($sql_settings); // Company info $company_name = $row['company_name']; $company_logo = $row['company_logo']; $config_start_page = nullable_htmlentities($row['config_start_page']); $config_login_message = nullable_htmlentities($row['config_login_message']); // Mail $config_smtp_host = $row['config_smtp_host']; $config_smtp_port = intval($row['config_smtp_port']); $config_smtp_encryption = $row['config_smtp_encryption']; $config_smtp_username = $row['config_smtp_username']; $config_smtp_password = $row['config_smtp_password']; $config_mail_from_email = sanitizeInput($row['config_mail_from_email']); $config_mail_from_name = sanitizeInput($row['config_mail_from_name']); // Client Portal Enabled $config_client_portal_enable = intval($row['config_client_portal_enable']); // Login key (if setup) $config_login_key_required = $row['config_login_key_required']; $config_login_key_secret = $row['config_login_key_secret']; // Login key verification // If no/incorrect 'key' is supplied, send to client portal instead if ($config_login_key_required) { if (!isset($_GET['key']) || $_GET['key'] !== $config_login_key_secret) { header("Location: portal"); exit(); } } // HTTP-Only cookies ini_set("session.cookie_httponly", true); // Tell client to only send cookie(s) over HTTPS if ($config_https_only || !isset($config_https_only)) { ini_set("session.cookie_secure", true); } // Handle POST login request if (isset($_POST['login'])) { // Sessions should start after the user has POSTed data session_start(); // Passed login brute force check $email = sanitizeInput($_POST['email']); $password = $_POST['password']; $current_code = 0; // Default value if (isset($_POST['current_code'])) { $current_code = intval($_POST['current_code']); } $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_email = '$email' AND user_archived_at IS NULL AND user_status = 1")); // Check password if ($row && password_verify($password, $row['user_password'])) { // User password correct (partial login) // Set temporary user variables $user_name = sanitizeInput($row['user_name']); $user_id = intval($row['user_id']); $user_email = sanitizeInput($row['user_email']); $token = sanitizeInput($row['user_token']); $force_mfa = intval($row['user_config_force_mfa']); $remember_token = $row['user_config_remember_me_token']; if($force_mfa == 1 && $token == NULL) { $config_start_page = "user_security.php"; } $bypass_2fa = false; if (isset($_COOKIE['rememberme']) && $_COOKIE['rememberme'] == $remember_token) { $bypass_2fa = true; } elseif (empty($token) || TokenAuth6238::verify($token, $current_code)) { $bypass_2fa = true; } if ($bypass_2fa) { if (isset($_POST['remember_me'])) { $newRememberToken = bin2hex(random_bytes(64)); setcookie('rememberme', $newRememberToken, time() + 86400*14, "/", null, true, true); $updateTokenQuery = "UPDATE user_settings SET user_config_remember_me_token = '$newRememberToken' WHERE user_id = $user_id"; mysqli_query($mysqli, $updateTokenQuery); } // FULL LOGIN SUCCESS - 2FA not configured or was successful // Check this login isn't suspicious $sql_ip_prev_logins = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS ip_previous_logins FROM logs WHERE log_type = 'Login' AND log_action = 'Success' AND log_ip = '$ip' AND log_user_id = $user_id")); $ip_previous_logins = sanitizeInput($sql_ip_prev_logins['ip_previous_logins']); $sql_ua_prev_logins = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS ua_previous_logins FROM logs WHERE log_type = 'Login' AND log_action = 'Success' AND log_user_agent = '$user_agent' AND log_user_id = $user_id")); $ua_prev_logins = sanitizeInput($sql_ua_prev_logins['ua_previous_logins']); // Notify if both the user agent and IP are different if (!empty($config_smtp_host) && $ip_previous_logins == 0 && $ua_prev_logins == 0) { $subject = "$config_app_name new login for $user_name"; $body = "Hi $user_name,

A recent successful login to your $config_app_name account was considered a little unusual. If this was you, you can safely ignore this email!

IP Address: $ip
User Agent: $user_agent

If you did not perform this login, your credentials may be compromised.

Thanks,
ITFlow"; $data = [ [ 'from' => $config_mail_from_email, 'from_name' => $config_mail_from_name, 'recipient' => $user_email, 'recipient_name' => $user_name, 'subject' => $subject, 'body' => $body ] ]; addToMailQueue($mysqli, $data); } // Determine whether 2FA was used (for logs) $extended_log = ''; // Default value if ($current_code !== 0) { $extended_log = 'with 2FA'; } // Logging successful login mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Success', log_description = '$user_name successfully logged in $extended_log', log_ip = '$ip', log_user_agent = '$user_agent', log_user_id = $user_id"); // Session info $_SESSION['user_id'] = $user_id; $_SESSION['user_name'] = $user_name; $_SESSION['user_role'] = intval($row['user_role']); $_SESSION['csrf_token'] = randomString(156); $_SESSION['logged'] = true; // Setup encryption session key if (isset($row['user_specific_encryption_ciphertext']) && $row['user_role'] > 1) { $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 // 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) $user_php_session = session_id(); mysqli_query($mysqli, "UPDATE users SET user_php_session = '$user_php_session' WHERE user_id = $user_id"); } } header("Location: $config_start_page"); } else { // MFA is configured and needs to be confirmed, or was unsuccessful // HTML code for the token input field $token_field = "
"; // Log/notify if MFA was unsuccessful if ($current_code !== 0) { // Logging mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = '2FA Failed', log_description = '$user_name failed 2FA', log_ip = '$ip', log_user_agent = '$user_agent', log_user_id = $user_id"); // Email the tech to advise their credentials may be compromised if (!empty($config_smtp_host)) { $subject = "Important: $config_app_name failed 2FA login attempt for $user_name"; $body = "Hi $user_name,

A recent login to your $config_app_name account was unsuccessful due to an incorrect 2FA code. If you did not attempt this login, your credentials may be compromised.

Thanks,
ITFlow"; $data = [ [ 'from' => $config_mail_from_email, 'from_name' => $config_mail_from_name, 'recipient' => $user_email, 'recipient_name' => $user_name, 'subject' => $subject, 'body' => $body ] ]; $mail = addToMailQueue($mysqli, $data); } // HTML feedback for incorrect 2FA code $response = "
Please Enter 2FA Code!
"; } } } else { // Password incorrect or user doesn't exist - show generic error header("HTTP/1.1 401 Unauthorized"); mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Login', log_action = 'Failed', log_description = 'Failed login attempt using $email', log_ip = '$ip', log_user_agent = '$user_agent'"); $response = "
Incorrect username or password.
"; } } ?> <?php echo nullable_htmlentities($company_name); ?> | Login