文件操作 - cerber-2fa.php
返回文件管理
返回主菜单
删除本文件
文件: /home/tecnoht/public_html/termozerba--com/wp-content/plugins/wp-cerber/cerber-2fa.php
编辑文件内容
<?php /* Copyright (C) 2015-21 CERBER TECH INC., https://cerber.tech Copyright (C) 2015-21 Markov Cregory, https://wpcerber.com Licenced under the GNU GPL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ const CERBER_PIN_LENGTH = 4; const CERBER_PIN_EXPIRES = 15; final class CRB_2FA { private static $user_id = null; static $token = null; /** * Enforce 2FA for a user if needed * * @param $login string * @param $user WP_User * * @return bool|WP_Error */ static function enforce( $login, $user ) { static $done = false; if ( $done ) { return false; } $done = true; if ( crb_acl_is_white() ) { return false; } if ( ( ! $user instanceof WP_User ) || empty( $user->ID ) ) { return new WP_Error( 'no-user', 'Invalid user data' ); } $cus = cerber_get_set( 'cerber_user', $user->ID ); $tfm = crb_array_get( $cus, 'tfm' ); if ( $tfm === 2 ) { return false; } $login = (string) $login; $go = false; if ( $tfm == 1 ) { $go = true; } else { $u_roles = null; if ( ! empty( $user->roles ) ) { $u_roles = $user->roles; } else { // a backup way $data = get_userdata( $user->ID ); if ( ! empty( $data->roles ) ) { $u_roles = $data->roles; } } if ( empty( $u_roles ) ) { return new WP_Error( 'no-roles', 'No roles found for the user #' . $user->ID ); } $go = self::check_role_policies( $user->ID, $cus, $u_roles ); } if ( ! $go ) { return false; } // This user must complete 2FA $ret = self::initiate_2fa( $user, $login ); if ( is_wp_error( $ret ) ) { return $ret; } cerber_log( 400, $login, $user->ID ); wp_safe_redirect( get_home_url() ); exit; } /** * @param int $user_id * @param array $cus * @param array $roles * * @return bool */ private static function check_role_policies( $user_id, $cus, $roles ) { foreach ( $roles as $role ) { $policies = cerber_get_role_policies( $role ); if ( empty( $policies['2famode'] ) ) { continue; } elseif ( $policies['2famode'] == 1 ) { return true; } if ( $history = crb_array_get( $cus, '2fa_history' ) ) { if ( ( $logins = crb_array_get( $policies, '2falogins' ) ) && ( $history[0] >= $logins ) ) { return true; } if ( ( $days = crb_array_get( $policies, '2fadays' ) ) && ( ( time() - $history[1] ) > $days * 24 * 3600 ) ) { return true; } } if ( $last_login = crb_array_get( $cus, 'last_login' ) ) { if ( crb_array_get( $policies, '2fanewip' ) ) { if ( $last_login['ip'] != cerber_get_remote_ip() ) { return true; } } if ( crb_array_get( $policies, '2fanewnet4' ) ) { if ( cerber_get_subnet_ipv4( $last_login['ip'] ) != cerber_get_subnet_ipv4( cerber_get_remote_ip() ) ) { return true; } } if ( crb_array_get( $policies, '2fanewua' ) ) { if ( $last_login['ua'] != sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) ) ) { return true; } } } if ( $limit = crb_array_get( $policies, '2fasessions' ) ) { if ( $limit < crb_sessions_get_num( $user_id ) ) { return true; } } if ( $last_login ) { if ( crb_array_get( $policies, '2fanewcountry' ) ) { if ( lab_get_country( $last_login['ip'], false ) != lab_get_country( cerber_get_remote_ip(), false ) ) { return true; } } } } return false; } /** * Initiate 2FA process * * @param $user * @param string $login * * @return bool|string|WP_Error */ private static function initiate_2fa( $user, $login = '' ) { if ( ! $pin = self::generate_pin( $user->ID ) ) { return new WP_Error( '2fa-error', 'Unable to create PIN for the user #' . $user->ID ); } $data = array( 'login' => $login, 'to' => cerber_2fa_get_redirect_to( $user ), 'ajax' => cerber_is_wp_ajax(), 'interim' => isset( $_REQUEST['interim-login'] ) ? 1 : 0, ); self::update_2fa_data( $data, $user->ID ); return $pin; } /** * Generates PIN and its expiration * * @param $user_id * * @return bool|string */ private static function generate_pin( $user_id ) { $pin = substr( str_shuffle( '1234567890' ), 0, CERBER_PIN_LENGTH ); $data = array( 'pin' => $pin, 'expires' => time() + CERBER_PIN_EXPIRES * 60, 'attempts' => 0, 'ip' => cerber_get_remote_ip(), 'ua' => sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) ) ); //cerber_diag_log( 'PIN ' . $pin ); if ( self::update_2fa_data( $data, $user_id ) ) { self::send_user_pin( $user_id, $pin ); return $pin; } return false; } /** * @param null $user_id User ID * */ static function restrict_and_verify( $user_id = null ) { global $cerber_act_status; static $done = false; if ( $done ) { return; } $done = true; if ( ! $user_id && ! $user_id = get_current_user_id() ) { return; } self::$user_id = $user_id; $cus = cerber_get_set( 'cerber_user', $user_id ); $twofactor = self::get_2fa_data( $user_id ); if ( empty( $twofactor['pin'] ) ) { return; } if ( crb_acl_is_white() ) { self::delete_2fa( $user_id ); return; } // Check user settings again $tfm = crb_array_get( $cus, 'tfm' ); if ( $tfm === 2 ) { self::delete_2fa( $user_id, true ); return; } elseif ( ! $tfm ) { $user = wp_get_current_user(); if ( ! self::check_role_policies( $user_id, $cus, $user->roles ) ) { self::delete_2fa( $user_id ); return; } } // Check if the same same browser and IP if ( $twofactor['ip'] != cerber_get_remote_ip() || $twofactor['ua'] != sha1( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', '' ) ) || ! cerber_is_ip_allowed() ) { self::delete_2fa( $user_id ); cerber_user_logout(); wp_redirect( get_home_url() ); exit; } // User wants to abort 2FA? if ( $now = cerber_get_get( 'cerber_2fa_now' ) ) { $go = null; if ( $now == 'different' ) { $go = wp_login_url( ( ! empty( $twofactor['to'] ) ) ? urldecode( $twofactor['to'] ) : '' ); } if ( $now == 'cancel' ) { $go = get_home_url(); } if ( $go ) { cerber_user_logout( 28 ); wp_redirect( $go ); exit; } } if ( $twofactor['attempts'] > 10 ) { cerber_block_add( cerber_get_remote_ip(), 721 ); cerber_user_logout(); wp_redirect( get_home_url() ); exit; } $new_pin = ''; if ( $twofactor['expires'] < time() ) { $new_pin = self::generate_pin( $user_id ); } // The first step of verification, ajax if ( cerber_is_http_post() ) { self::process_ajax( $new_pin ); } // The second, final step of verification if ( cerber_is_http_post() && ! empty( $twofactor['nonce'] ) && $_POST['cerber_tag'] === $twofactor['nonce'] && ( $pin = cerber_get_post( 'cerber_pin' ) ) && self::verify_pin( trim( $pin ) ) ) { self::delete_2fa( $user_id ); $cerber_act_status = 27; cerber_log( 5, $twofactor['login'], $user_id ); cerber_login_history( $user_id, true ); cerber_2fa_checker( true ); $url = ( ! empty( $twofactor['to'] ) ) ? $twofactor['to'] : get_home_url(); wp_safe_redirect( $url ); exit; } self::show_2fa_page(); exit; } static function process_ajax( $new_pin ) { if ( ( ! $nonce = cerber_get_post( 'the_2fa_nonce', '\w+' ) ) || ( ! $pin = cerber_get_post( 'cerber_verify_pin' ) ) ) { return; } $err = ''; if ( ! wp_verify_nonce( $nonce, 'crb-ajax-2fa' ) ) { $err = 'Nonce error.'; } elseif ( $new_pin ) { $err = __( 'This verification PIN code is expired. We have just sent a new one to your email.', 'wp-cerber' ); } elseif ( ! self::verify_pin( trim( $pin ), $nonce ) ) { $err = __( 'You have entered an incorrect verification PIN code', 'wp-cerber' ); } echo json_encode( array( 'error' => $err ) ); exit; } private static function verify_pin( $pin, $nonce = null ) { $data = self::get_2fa_data(); if ( empty( $data['pin'] ) || $data['expires'] < time() ) { return false; } if ( (string) $pin === (string) $data['pin'] ) { $ret = true; if ( ! $nonce ) { return $ret; } $data['nonce'] = $nonce; } else { $data['attempts'] ++; $ret = false; } self::update_2fa_data( $data ); return $ret; } static function show_2fa_page( $echo = true ) { @ini_set( 'display_errors', 0 ); $ajax_vars = 'var ajaxurl = "' . admin_url( 'admin-ajax.php' ) . '";'; $ajax_vars .= 'var nonce2fa = "'. wp_create_nonce( 'crb-ajax-2fa' ).'";'; if ( ! defined( 'CONCATENATE_SCRIPTS' ) ) { define( 'CONCATENATE_SCRIPTS', false ); } wp_enqueue_script( 'jquery' ); ob_start(); ?> <!DOCTYPE html> <html style="height: 100%;"> <head> <meta charset="UTF-8"> <title><?php _e( 'Please verify that it’s you', 'wp-cerber' ); ?></title> <style> body { font-family: Arial, Helvetica, sans-serif; color: #555; } #cerber_2fa_inner { width: 350px; } @media (-webkit-min-device-pixel-ratio: 2) and (max-width: 1000px), (min-resolution: 192dpi) and (max-width: 1000px), { #cerber_2fa_inner { width: 100%; } } @media screen and (max-width: 900px) { #cerber_2fa_inner { /*width: 100%;*/ } } #cerber_2fa_msg { display: none; position: fixed; top: 0; left: 0; width: 100%; /*height: 80px;*/ padding: 40px 0 40px 0; background-color: #FF5733; color: #fff; opacity: 0.9; } #cerber_2fa_form input[type="text"] { color: #000; text-align: center; font-size: 1.5em; letter-spacing: 0.1em; padding: 5px; min-width: 140px; border-radius: 4px; } #cerber_2fa_form input[type="submit"] { color: white; background: #0085ba; /*background: #0073aa;*/ border: 0; font-size: 1em; font-weight: 600; letter-spacing: 0.1em; text-align: center; cursor: pointer; padding: 1em; min-width: 150px; border-radius: 4px; } </style> <?php print_head_scripts(); ?> <script> <?php echo $ajax_vars; ?> </script> </head> <body style="height: 90%; text-align: center;"> <div style="display: flex; align-items: center; justify-content: center; text-align: center; height: 90%;"> <?php self::cerber_2fa_form(); ?> </div> </body> </html> <?php $html = ob_get_clean(); if ( $echo ) { echo $html; } return $html; } static function send_user_pin( $user_id, $pin, $details = true ) { $to = self::get_user_email( $user_id ); $subj = __( 'Please verify that it’s you', 'wp-cerber' ); $body = array(); $body[] = 'We need to verify that it’s you because you are trying to sign-in from a different device or a different location or you have not signed in for a long time. If this wasn’t you, please reset your password immediately.'; $body[] = __( 'Please use the following verification PIN code to confirm your identity', 'wp-cerber' ) . '. ' . sprintf( __( 'The code is valid for %s minutes.', 'wp-cerber' ), CERBER_PIN_EXPIRES ); if ( ! $pin && ( $p = self::get_user_pin( $user_id ) ) ) { $pin = $p['pin']; } if ( ! $pin ) { return false; } $body[] = $pin; $data = get_userdata( $user_id ); if ( $details ) { $ds = array(); $ds[] = 'Login: ' . $data->user_login; $ds[] = 'IP: ' . cerber_get_remote_ip(); if ( $c = lab_get_country( cerber_get_remote_ip(), false ) ) { $ds[] = 'Location: ' . cerber_country_name( $c ) . ' (' . $c . ')'; } $ds[] = 'Browser: ' . substr( strip_tags( crb_array_get( $_SERVER, 'HTTP_USER_AGENT', 'Not set' ) ), 0, 1000 ); $ds[] = 'Date: ' . cerber_date( time(), false ); $body[] = ''; $body[] = __( 'Here are the details of the sign-in attempt', 'wp-cerber' ); $body[] = implode( "\n", $ds ); } $body = implode( "\n\n", $body ); $result = wp_mail( $to, $subj, $body ); if ( $result && ( $data->user_email != $to ) ) { // TODO Add a notification to the main email //wp_mail( $data->user_email, $subj, $body ); } } static function get_user_email( $user_id = null ) { if ( ! $user_id ) { $user_id = get_current_user_id(); } $cus = cerber_get_set( 'cerber_user', $user_id ); if ( $cus && ( $email = crb_array_get( $cus, 'tfemail' ) ) ) { return $email; } $data = get_userdata( $user_id ); return $data->user_email; } static function get_user_pin( $user_id ) { $data = self::get_2fa_data(); if ( empty( $data['pin'] ) || $data['expires'] < time() ) { return false; } return $data; } static function get_user_pin_info( $user_id ) { if ( ! $pin = self::get_user_pin( $user_id ) ) { return ''; } return '<code style="font-size: 120%;">' . $pin['pin'] . '</code> ' . __( 'expires', 'wp-cerber' ) . ' ' . cerber_ago_time( $pin['expires'] ); } static function update_2fa_data( $data, $user_id = null ) { $token = self::cerber_2fa_session_id(); if ( ! $user_id ) { $user_id = get_current_user_id(); } $cus = cerber_get_set( 'cerber_user', $user_id ); if ( ! is_array( $cus ) ) { $cus = array(); } if ( ! isset( $cus['2fa'] ) ) { $cus['2fa'] = array(); } if ( ! isset( $cus['2fa'][ $token ] ) ) { $cus['2fa'][ $token ] = array(); } $cus['2fa'][ $token ] = array_merge( $cus['2fa'][ $token ], $data ); return cerber_update_set( 'cerber_user', $cus, $user_id ); } static function get_2fa_data( $user_id = null ) { $token = self::cerber_2fa_session_id(); if ( ! $user_id ) { $user_id = get_current_user_id(); } if ( ! $cus = cerber_get_set( 'cerber_user', $user_id ) ) { return array(); } return crb_array_get( $cus, array( '2fa', $token ), array() ); } static function delete_2fa( $uid, $all = false ) { if ( ! $uid = absint( $uid ) ) { return; } $cus = cerber_get_set( 'cerber_user', $uid ); if ( $cus && isset( $cus['2fa'] ) ) { if ( $all ) { unset( $cus['2fa'] ); } else { unset( $cus['2fa'][ self::cerber_2fa_session_id() ] ); } cerber_update_set( 'cerber_user', $cus, $uid ); } } static function cerber_2fa_session_id() { if ( self::$token ) { return self::$token; } return wp_get_session_token(); } static function cerber_2fa_form() { $max = CERBER_PIN_LENGTH; $atts = 'pattern="\d{' . $max . '}" maxlength="' . $max . '" size="' . $max . '" title="' . __( 'only digits are allowed', 'wp-cerber' ) . '"'; // Please enter your PIN code to continue $email = self::get_user_email(); $text = __( "We've sent a verification PIN code to your email", 'wp-cerber' ) . ' ' . cerber_mask_email( $email ) . '<p>'. __( 'Enter the code from the email in the field below.', 'wp-cerber' ).'</p>'; //$change = '<a href="' . cerber_get_home_url() . '/?cerber_2fa_now=different">' . __( 'Sign in with a different account', 'wp-cerber' ) . '</a>'; $change = '<a href="' . cerber_get_home_url() . '/?cerber_2fa_now=different">' . __( 'Try again', 'wp-cerber' ) . '</a>'; $cancel = '<a href="' . cerber_get_home_url() . '/?cerber_2fa_now=cancel">' . __( 'Cancel', 'wp-cerber' ) . '</a>'; $links = '<p>'.__( 'Did not receive an email?', 'wp-cerber' ) .'</p>'. $change . ' ' . __( 'or', 'wp-cerber' ) . ' ' . $cancel; ?> <div id="cerber_2fa_msg"></div> <div> <div id="cerber_2fa_wrap" style="text-align: center; background-color: #eee; border-top: solid 4px #ddd; padding: 1.5em 3em 1.5em 3em;"> <div id="cerber_2fa_inner" style="text-align: center;"> <h1 style="color:#000;"><?php _e( "Verify it's you", 'wp-cerber' ); ?></h1> <div id="cerber_2fa_info" style="color: #333;"><?php echo $text; ?></div> <form id="cerber_2fa_form" method="post" data-verified="no" style="margin-bottom: 3em;"> <p><input required type="text" name="cerber_pin" <?php echo $atts; ?> ></p> <p><input type="hidden" name="cerber_tag" value="2FA"></p> <p><input type="submit" value="<?php _e( 'Verify', 'wp-cerber' ); ?>"></p> </form> </div> </div> <?php echo $links; ?> </div> <script> jQuery(document).ready(function ($) { let cform = $('#cerber_2fa_form'); let umsg = 'cerber_2fa_msg'; cform.submit(function (event) { crb_hide_user_msg(); if (cform.data('verified') === 'yes') { return; } event.preventDefault(); $.post(ajaxurl, { the_2fa_nonce: nonce2fa, cerber_verify_pin: $(this).find('input[type="text"]').val() }, function (server_response, textStatus, jqXHR) { let server_data = $.parseJSON(server_response); if (server_data.error.length === 0) { cform.find('[name="cerber_tag"]').val(nonce2fa); cform.data('verified', 'yes'); cform.submit(); } else { crb_display_user_msg(server_data['error']); } } ).fail(function (jqXHR, textStatus, errorThrown) { let err = errorThrown + ' ' + jqXHR.status; alert(err); console.error('Server Error: ' + err); }); }); function crb_display_user_msg(msg) { $('#' + umsg).fadeIn(500).html(msg); setTimeout(function (args) { crb_hide_user_msg(); }, 5000); } function crb_hide_user_msg() { document.getElementById(umsg).style.display = "none"; } }); </script> <?php } } /** * @param $user WP_User * * @return string */ function cerber_2fa_get_redirect_to( $user ) { if ( isset( $_REQUEST['redirect_to'] ) ) { $redirect_to = $_REQUEST['redirect_to']; $requested_redirect_to = $redirect_to; } else { $redirect_to = admin_url(); $requested_redirect_to = ''; } $redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user ); return $redirect_to; } /** * Verify that 2FA on the website works * If it works, 2FA can be enabled for admins * */ function cerber_2fa_checker( $save = false ) { if ( $save ) { cerber_update_set( 'cerber_2fa_is_ok', 1, null, false ); } else { if ( cerber_get_set( 'cerber_2fa_is_ok', null, false ) ) { return true; } return false; } }
修改文件时间
将文件时间修改为当前时间的前一年
删除文件