Server IP : 104.21.14.48 / Your IP : 3.143.203.190 [ Web Server : Apache System : Linux b70eb322-3aee-0c53-7c82-0db91281f2c6.secureserver.net 6.1.90-1.el9.elrepo.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 2 12:09:22 EDT 2024 x86_64 User : root ( 0) PHP Version : 8.0.30.2 Disable Function : NONE Domains : 0 Domains MySQL : ON | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/wp-content/plugins/sucuri-scanner/src/ |
Upload File : |
<?php /** * Code related to the lastlogins.php interface. * * PHP version 5 * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid <[email protected]> * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) { if (!headers_sent()) { /* Report invalid access if possible. */ header('HTTP/1.1 403 Forbidden'); } exit(1); } /** * Placeholder for the last logins interface. * * @category Library * @package Sucuri * @subpackage SucuriScanner * @author Daniel Cid <[email protected]> * @copyright 2010-2018 Sucuri Inc. * @license https://www.gnu.org/licenses/gpl-2.0.txt GPL2 * @link https://wordpress.org/plugins/sucuri-scanner */ class SucuriScanLastLogins extends SucuriScan { } /** * List all the user administrator accounts. * * @see https://codex.wordpress.org/Class_Reference/WP_User_Query * * @return void */ function sucuriscan_lastlogins_admins() { // Page pseudo-variables initialization. $params = array( 'AdminUsers.List' => '', ); $user_query = new WP_User_Query(array('role' => 'Administrator')); $admins = $user_query->get_results(); foreach ((array) $admins as $admin) { $last_logins = sucuriscan_get_logins(5, 0, $admin->ID); $user_snippet = array( 'AdminUsers.Username' => $admin->user_login, 'AdminUsers.Email' => $admin->user_email, 'AdminUsers.LastLogins' => '', 'AdminUsers.RegisteredAt' => 'unknown', 'AdminUsers.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $admin->ID), 'AdminUsers.NoLastLogins' => 'visible', 'AdminUsers.NoLastLoginsTable' => 'hidden', ); if ($last_logins && isset($last_logins['entries']) && !empty($last_logins['entries']) ) { $user_snippet['AdminUsers.NoLastLogins'] = 'hidden'; $user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible'; $user_snippet['AdminUsers.RegisteredAt'] = 'unknown'; foreach ($last_logins['entries'] as $i => $lastlogin) { if ($i === 0) { $user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime( $lastlogin['user_registered_timestamp'] ); } $user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::getSnippet( 'lastlogins-admins-lastlogin', array( 'AdminUsers.RemoteAddr' => $lastlogin['user_remoteaddr'], 'AdminUsers.Datetime' => SucuriScan::datetime($lastlogin['user_lastlogin_timestamp']), ) ); } } $params['AdminUsers.List'] .= SucuriScanTemplate::getSnippet('lastlogins-admins', $user_snippet); } return SucuriScanTemplate::getSection('lastlogins-admins', $params); } /** * List the last-logins for all user accounts in the site. * * This page will contains information of all the logins of the registered users. * * @return string Last-logings for all user accounts. */ function sucuriscan_lastlogins_all() { $max_per_page = SUCURISCAN_LASTLOGINS_USERSLIMIT; $page_number = SucuriScanTemplate::pageNumber(); $offset = ($max_per_page * $page_number) - $max_per_page; $params = array( 'UserList' => '', 'UserList.Limit' => $max_per_page, 'UserList.Total' => 0, 'UserList.Pagination' => '', 'UserList.PaginationVisibility' => 'hidden', 'UserList.NoItemsVisibility' => 'visible', ); // Clear last login logins when delete button is pressed. if (SucuriScanInterface::checkNonce() && SucuriScanRequest::post(':delete_lastlogins')) { SucuriScanEvent::clearLastLogs('sucuri-lastlogins.php'); } if (!sucuriscan_lastlogins_datastore_is_writable()) { $fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath()); SucuriScanInterface::error(sprintf(__('Last-logins data file is not writable: <code>%s</code>', 'sucuri-scanner'), $fpath)); } $last_logins = sucuriscan_get_logins($max_per_page, $offset); if (is_array($last_logins) && !empty($last_logins)) { $params['UserList.Total'] = $last_logins['total']; if ($last_logins['total'] > $max_per_page) { $params['UserList.PaginationVisibility'] = 'visible'; } if ($last_logins['total'] > 0) { $params['UserList.NoItemsVisibility'] = 'hidden'; } foreach ($last_logins['entries'] as $user) { $user_dataset = array( 'UserList.Number' => $user['line_num'], 'UserList.UserId' => $user['user_id'], 'UserList.Username' => 'unknown', 'UserList.Displayname' => '', 'UserList.Email' => '', 'UserList.Registered' => '', 'UserList.RemoteAddr' => $user['user_remoteaddr'], 'UserList.Hostname' => $user['user_hostname'], 'UserList.Datetime' => SucuriScan::datetime($user['user_lastlogin_timestamp']), 'UserList.TimeAgo' => SucuriScan::humanTime($user['user_lastlogin_timestamp']), 'UserList.UserURL' => SucuriScan::adminURL('user-edit.php?user_id=' . $user['user_id']), ); if ($user['user_exists']) { $user_dataset['UserList.Username'] = $user['user_login']; $user_dataset['UserList.Displayname'] = $user['display_name']; $user_dataset['UserList.Email'] = $user['user_email']; $user_dataset['UserList.Registered'] = $user['user_registered']; } $params['UserList'] .= SucuriScanTemplate::getSnippet('lastlogins-all', $user_dataset); } // Generate the pagination for the list. $params['UserList.Pagination'] = SucuriScanTemplate::pagination( '%%SUCURI.URL.Lastlogins%%', $last_logins['total'], $max_per_page ); } return SucuriScanTemplate::getSection('lastlogins-all', $params); } /** * Get the filepath where the information of the last logins of all users is stored. * * @return string Absolute filepath where the user's last login information is stored. */ function sucuriscan_lastlogins_datastore_filepath() { return SucuriScan::dataStorePath('sucuri-lastlogins.php'); } /** * Check whether the user's last login datastore file exists or not, if not then * we try to create the file and check again the success of the operation. * * @return string|bool Path to the storage file if exists, false otherwise. */ function sucuriscan_lastlogins_datastore_exists() { $fpath = sucuriscan_lastlogins_datastore_filepath(); if (!file_exists($fpath)) { @file_put_contents($fpath, "<?php exit(0); ?>\n", LOCK_EX); } return file_exists($fpath) ? $fpath : false; } /** * Check whether the user's last login datastore file is writable or not, if not * we try to set the right permissions and check again the success of the operation. * * @return string|bool Path to the storage file if writable, false otherwise. */ function sucuriscan_lastlogins_datastore_is_writable() { $datastore_filepath = sucuriscan_lastlogins_datastore_exists(); if ($datastore_filepath) { if (!is_writable($datastore_filepath)) { @chmod($datastore_filepath, 0644); } if (is_writable($datastore_filepath)) { return $datastore_filepath; } } return false; } /** * Check whether the user's last login datastore file is readable or not, if not * we try to set the right permissions and check again the success of the operation. * * @return string|bool Path to the storage file if readable, false otherwise. */ function sucuriscan_lastlogins_datastore_is_readable() { $datastore_filepath = sucuriscan_lastlogins_datastore_exists(); if ($datastore_filepath && is_readable($datastore_filepath)) { return $datastore_filepath; } return false; } if (!function_exists('sucuriscan_set_lastlogin')) { /** * Add a new user session to the list of last user logins. * * @param string $user_login User account involved in the operation. * @return void */ function sucuriscan_set_lastlogin($user_login = '') { $filename = sucuriscan_lastlogins_datastore_is_writable(); if (!is_string($filename)) { return false; } $current_user = get_user_by('login', $user_login); $remote_addr = SucuriScan::getRemoteAddr(); $login_info = array( 'user_id' => $current_user->ID, 'user_login' => $current_user->user_login, 'user_remoteaddr' => $remote_addr, 'user_hostname' => @gethostbyaddr($remote_addr), 'user_lastlogin' => current_time('mysql') ); @file_put_contents( $filename, json_encode($login_info) . "\n", FILE_APPEND ); } add_action('wp_login', 'sucuriscan_set_lastlogin', 50); } /** * Retrieve the list of all the user logins from the datastore file. * * The results of this operation can be filtered by specific user identifiers, * or limiting the quantity of entries. * * @param int $limit How many entries will be returned from the operation. * @param int $offset Initial point where the logs will be start counting. * @param int $user_id Optional user identifier to filter the results. * @return array|bool All user logins, false on failure. */ function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0) { $limit = intval($limit); /* prevent arbitrary user input */ $datastore_filepath = sucuriscan_lastlogins_datastore_is_readable(); $last_logins = array( 'total' => 0, 'entries' => array(), ); if (!$datastore_filepath) { return SucuriScan::throwException(__('Invalid last-logins storage file', 'sucuri-scanner')); } $parsed_lines = 0; $data_lines = SucuriScanFileInfo::fileLines($datastore_filepath); if (!$data_lines) { return SucuriScan::throwException(__('No last-logins data is available', 'sucuri-scanner')); } /** * This count will not be 100% accurate considering that we are checking the * syntax of each line in the loop bellow, there may be some lines without the * right syntax which will differ from the total entries returned, but there's * not other EASY way to do this without affect the performance of the code. * * @var integer */ $total_lines = count($data_lines); $last_logins['total'] = $total_lines; // Get a list with the latest entries in the first positions. $reversed_lines = array_reverse($data_lines); /** * Only the user accounts with administrative privileges can see the logs of all * the users, for the rest of the accounts they will only see their own logins. * * @var object */ $user_ids = array(); $current_user = wp_get_current_user(); $is_admin_user = (bool) current_user_can('manage_options'); for ($i = $offset; $i < $total_lines; $i++) { $line = $reversed_lines[$i] ? trim($reversed_lines[$i]) : ''; // Check if the data is serialized (which we will consider as insecure). $last_login = @json_decode($line, true); if (!$last_login) { $last_logins['total'] -= 1; continue; } $last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']); $last_login['user_registered_timestamp'] = 0; // Only administrators can see all login stats. if (!$is_admin_user && $current_user->user_login != $last_login['user_login']) { continue; } // Filter the user identifiers using the value passed tot his function. if ($user_id > 0 && $last_login['user_id'] != $user_id) { continue; } $last_login['user_exists'] = false; $user_ids[] = $last_login['user_id']; $last_login['line_num'] = $i + 1; $last_logins['entries'][] = $last_login; $parsed_lines += 1; if ($limit > 0 && $parsed_lines >= $limit) { break; } } /* no need for database query */ if (empty($user_ids)) { return $last_logins; } /* extra information for the unique user accounts */ $user_ids = array_unique($user_ids); $dbquery = new WP_User_Query(array('include' => $user_ids)); if ($dbquery) { $results = $dbquery->get_results(); foreach ($last_logins['entries'] as $key => $entry) { foreach ($results as $dbentry) { if ($entry['user_id'] === $dbentry->ID) { $last_logins['entries'][$key]['user_exists'] = true; $last_logins['entries'][$key]['user_nicename'] = $dbentry->user_nicename; $last_logins['entries'][$key]['user_email'] = $dbentry->user_email; $last_logins['entries'][$key]['user_url'] = $dbentry->user_url; $last_logins['entries'][$key]['user_status'] = $dbentry->user_status; $last_logins['entries'][$key]['display_name'] = $dbentry->display_name; $last_logins['entries'][$key]['user_registered'] = $dbentry->user_registered; $last_logins['entries'][$key]['user_registered_timestamp'] = strtotime($dbentry->user_registered); } } } } return $last_logins; } if (!function_exists('sucuriscan_login_redirect')) { /** * Hook for the wp-login action to redirect the user to a specific URL after * his successfully login to the administrator interface. * * @param string $redirect_to The redirect destination URL. * @param mixed $request The requested redirect destination URL passed as a parameter. * @param bool $user WP_User object if login was successful, WP_Error object otherwise. * @return string URL where the browser must be redirected to. */ function sucuriscan_login_redirect($redirect_to = '', $request = null, $user = false) { $login_url = !empty($redirect_to) ? $redirect_to : SucuriScan::adminURL(); if ($user instanceof WP_User && in_array('administrator', $user->roles) && SucuriScanOption::isEnabled(':lastlogin_redirection') ) { $login_url = add_query_arg('sucuriscan_lastlogin', 1, $login_url); } return $login_url; } if (SucuriScanOption::isEnabled(':lastlogin_redirection')) { add_filter('login_redirect', 'sucuriscan_login_redirect', 10, 3); } } if (!function_exists('sucuriscan_get_user_lastlogin')) { /** * Display the last user login at the top of the admin interface. * * @return void */ function sucuriscan_get_user_lastlogin() { if (current_user_can('manage_options') && SucuriScanRequest::get(':lastlogin', '1') ) { $current_user = wp_get_current_user(); $last_logins = sucuriscan_get_logins(2, 0, $current_user->ID); if ($last_logins && isset($last_logins['entries']) && isset($last_logins['entries'][1]) ) { $row = $last_logins['entries'][1]; $page_url = SucuriScanTemplate::getUrl('lastlogins'); $message = sprintf( __('Last login was at <b>%s</b> from <b>%s</b> <em>(%s)</em> <a href="%s" target="_self">view all logs</a>', 'sucuri-scanner'), SucuriScan::datetime($row['user_lastlogin_timestamp']), SucuriScan::escape($row['user_remoteaddr']), SucuriScan::escape($row['user_hostname']), SucuriScan::escape($page_url) ); SucuriScanInterface::info($message); } } } add_action('network_admin_notices', 'sucuriscan_get_user_lastlogin'); add_action('admin_notices', 'sucuriscan_get_user_lastlogin'); }