| 1 |
<?php |
| 2 |
/** |
| 3 |
* Brute force attack countermeasures Class |
| 4 |
* |
| 5 |
* @package Welcart |
| 6 |
*/ |
| 7 |
|
| 8 |
/** |
| 9 |
* Brute force attack countermeasures Class |
| 10 |
*/ |
| 11 |
class USCES_BRUTE_FORCE_COUNTER_MEASURES { |
| 12 |
|
| 13 |
/** |
| 14 |
* Option value |
| 15 |
* |
| 16 |
* @var array |
| 17 |
*/ |
| 18 |
public static $opts; |
| 19 |
|
| 20 |
/** |
| 21 |
* Default option value |
| 22 |
* |
| 23 |
* @var array |
| 24 |
*/ |
| 25 |
public static $default_option; |
| 26 |
|
| 27 |
/** |
| 28 |
* Log file path |
| 29 |
* |
| 30 |
* @var string |
| 31 |
*/ |
| 32 |
private $uploads_folder_path; |
| 33 |
|
| 34 |
/** |
| 35 |
* Class Constructor |
| 36 |
*/ |
| 37 |
public function __construct() { |
| 38 |
self::initialize_data(); |
| 39 |
$this->uploads_folder_path = USCES_WP_CONTENT_DIR . '/uploads'; |
| 40 |
if ( is_admin() ) { |
| 41 |
add_action( 'usces_action_admin_system_extentions', array( $this, 'setting_form' ) ); |
| 42 |
add_action( 'init', array( $this, 'save_data' ) ); |
| 43 |
} |
| 44 |
} |
| 45 |
|
| 46 |
/** |
| 47 |
* Initialize |
| 48 |
*/ |
| 49 |
public function initialize_data() { |
| 50 |
global $usces; |
| 51 |
|
| 52 |
$options = get_option( 'usces_ex', array() ); |
| 53 |
$options['system']['brute_force']['status'] = ( ! isset( $options['system']['brute_force']['status'] ) ) ? 0 : (int) $options['system']['brute_force']['status']; |
| 54 |
$options['system']['brute_force']['monitoring_span'] = ( ! isset( $options['system']['brute_force']['monitoring_span'] ) ) ? 5 : (int) $options['system']['brute_force']['monitoring_span']; |
| 55 |
$options['system']['brute_force']['num_of_errors'] = ( ! isset( $options['system']['brute_force']['num_of_errors'] ) ) ? 3 : (int) $options['system']['brute_force']['num_of_errors']; |
| 56 |
$options['system']['brute_force']['rejection_time'] = ( ! isset( $options['system']['brute_force']['rejection_time'] ) ) ? 10 : (int) $options['system']['brute_force']['rejection_time']; |
| 57 |
$options['system']['brute_force']['excluded_ip'] = ( ! isset( $options['system']['brute_force']['excluded_ip'] ) ) ? array() : $options['system']['brute_force']['excluded_ip']; |
| 58 |
update_option( 'usces_ex', $options ); |
| 59 |
self::$opts = $options['system']['brute_force']; |
| 60 |
|
| 61 |
self::$default_option = array( |
| 62 |
'status' => array( 0, 1 ), |
| 63 |
'monitoring_span' => array( 5, 10, 15 ), |
| 64 |
'num_of_errors' => array( 3, 5, 10 ), |
| 65 |
'rejection_time' => array( 10, 20, 30 ), |
| 66 |
'excluded_ip' => array(), |
| 67 |
); |
| 68 |
} |
| 69 |
|
| 70 |
/** |
| 71 |
* Save Options |
| 72 |
* init |
| 73 |
*/ |
| 74 |
public function save_data() { |
| 75 |
global $usces; |
| 76 |
|
| 77 |
if ( isset( $_POST['usces_brute_force_option_update'] ) ) { |
| 78 |
check_admin_referer( 'admin_system', 'wc_nonce' ); |
| 79 |
if ( ! current_user_can( 'wel_manage_setting' ) ) { |
| 80 |
wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); |
| 81 |
} |
| 82 |
|
| 83 |
if ( ! file_exists( $this->uploads_folder_path ) || ! is_writable( $this->uploads_folder_path ) ) { |
| 84 |
self::$opts['error_message'] = __( "You can't write to the wp-content/uploads/ folder. Please check the permissions.", 'usces' ); |
| 85 |
self::$opts['status'] = 0; |
| 86 |
} else { |
| 87 |
if ( isset( self::$opts['error_message'] ) ) { |
| 88 |
unset( self::$opts['error_message'] ); |
| 89 |
} |
| 90 |
self::$opts['status'] = ( isset( $_POST['brute_force_status'] ) ) ? (int) $_POST['brute_force_status'] : 0; |
| 91 |
if ( 0 === self::$opts['status'] ) { |
| 92 |
$usces_log_folder = USCES_WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR . 'usces_logs'; |
| 93 |
$login_failed_log_path = $usces_log_folder . DIRECTORY_SEPARATOR . 'member_login_failed.log'; |
| 94 |
$ip_blocked_path = $usces_log_folder . DIRECTORY_SEPARATOR . 'ip_addresses_blocked.log'; |
| 95 |
if ( file_exists( $login_failed_log_path ) ) { |
| 96 |
rename( $login_failed_log_path, $usces_log_folder . DIRECTORY_SEPARATOR . 'member_login_failed' . date_i18n( '-YmdHis' ) . '.log' ); |
| 97 |
} |
| 98 |
if ( file_exists( $ip_blocked_path ) ) { |
| 99 |
rename( $ip_blocked_path, $usces_log_folder . DIRECTORY_SEPARATOR . 'ip_addresses_blocked' . date_i18n( '-YmdHis' ) . '.log' ); |
| 100 |
} |
| 101 |
} |
| 102 |
} |
| 103 |
|
| 104 |
self::$opts['monitoring_span'] = ( isset( $_POST['monitoring_span'] ) ) ? (int) $_POST['monitoring_span'] : 5; |
| 105 |
self::$opts['num_of_errors'] = ( isset( $_POST['num_of_errors'] ) ) ? (int) $_POST['num_of_errors'] : 3; |
| 106 |
self::$opts['rejection_time'] = ( isset( $_POST['rejection_time'] ) ) ? (int) $_POST['rejection_time'] : 10; |
| 107 |
if ( isset( $_POST['excluded_ip'] ) ) { |
| 108 |
$ips = array(); |
| 109 |
$excluded_ip = explode( "\n", usces_change_line_break( $_POST['excluded_ip'] ) ); |
| 110 |
foreach ( (array) $excluded_ip as $ip ) { |
| 111 |
if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) { |
| 112 |
$ips[] = $ip; |
| 113 |
} |
| 114 |
} |
| 115 |
self::$opts['excluded_ip'] = array_unique( $ips ); |
| 116 |
} |
| 117 |
|
| 118 |
$options = get_option( 'usces_ex', array() ); |
| 119 |
$options['system']['brute_force'] = self::$opts; |
| 120 |
if ( isset( $options['system']['brute_force']['error_message'] ) ) { |
| 121 |
unset( $options['system']['brute_force']['error_message'] ); |
| 122 |
} |
| 123 |
update_option( 'usces_ex', $options ); |
| 124 |
} |
| 125 |
} |
| 126 |
|
| 127 |
/** |
| 128 |
* Setting Form |
| 129 |
* usces_action_admin_system_extentions |
| 130 |
*/ |
| 131 |
public function setting_form() { |
| 132 |
$status = ( ! empty( self::$opts['status'] ) && 1 === (int) self::$opts['status'] ) ? '<span class="running">' . __( 'Running', 'usces' ) . '</span>' : '<span class="stopped">' . __( 'Stopped', 'usces' ) . '</span>'; |
| 133 |
if ( isset( self::$opts['excluded_ip'] ) && is_array( self::$opts['excluded_ip'] ) ) { |
| 134 |
$excluded_ip = implode( "\n", self::$opts['excluded_ip'] ); |
| 135 |
} else { |
| 136 |
$excluded_ip = ''; |
| 137 |
} |
| 138 |
?> |
| 139 |
<form action="" method="post" name="option_form" id="brute_force_form"> |
| 140 |
<div class="postbox"> |
| 141 |
<div class="postbox-header"> |
| 142 |
<h2><span><?php esc_html_e( 'Brute-force attack countermeasures', 'usces' ); ?></span><?php wel_esc_script_e( $status ); ?></h2> |
| 143 |
<div class="handle-actions"><button type="button" class="handlediv" id="brute_force"><span class="screen-reader-text"><?php echo esc_html( sprintf( __( 'Toggle panel: %s' ), __( 'Brute-force attack countermeasures', 'usces' ) ) ); ?></span><span class="toggle-indicator"></span></button></div> |
| 144 |
</div> |
| 145 |
<div class="inside"> |
| 146 |
<?php if ( isset( self::$opts['error_message'] ) ) : ?> |
| 147 |
<span class="stopped"><?php echo esc_html( self::$opts['error_message'] ); ?></span> |
| 148 |
<?php endif; ?> |
| 149 |
<table class="form_table"> |
| 150 |
<tr height="35"> |
| 151 |
<th class="system_th"><a style="cursor:pointer;" onclick="toggleVisibility('ex_brute_force_status');"><?php esc_html_e( 'Brute-force attack countermeasures', 'usces' ); ?></a></th> |
| 152 |
<td width="10"><input name="brute_force_status" type="radio" id="brute_force_status_0" value="0"<?php checked( self::$opts['status'], 0 ); ?> /></td> |
| 153 |
<td width="100"><label for="brute_force_status_0"><?php esc_html_e( 'disable', 'usces' ); ?></label></td> |
| 154 |
<td width="10"><input name="brute_force_status" type="radio" id="brute_force_status_1" value="1"<?php checked( self::$opts['status'], 1 ); ?> /></td> |
| 155 |
<td width="100" colspan="3"><label for="brute_force_status_1"><?php esc_html_e( 'enable', 'usces' ); ?></label></td> |
| 156 |
<td><div id="ex_brute_force_status" class="explanation"><?php esc_html_e( 'Enable brute-force attack countermeasures. Detects "brute-force attack" on Welcart member login and prevents login.', 'usces' ); ?></div></td> |
| 157 |
</tr> |
| 158 |
<tr height="35"> |
| 159 |
<th class="system_th"><a style="cursor:pointer;" onclick="toggleVisibility('ex_monitoring_span');"><?php esc_html_e( 'Monitoring span', 'usces' ); ?></a></th> |
| 160 |
<?php foreach ( self::$default_option['monitoring_span'] as $value ) : ?> |
| 161 |
<td width="10"><input name="monitoring_span" type="radio" id="brute_force_monitoring_span_<?php echo esc_attr( $value ); ?>" value="<?php echo esc_attr( $value ); ?>"<?php checked( self::$opts['monitoring_span'], $value ); ?> /></td> |
| 162 |
<td width="100"><label for="brute_force_monitoring_span_<?php echo esc_attr( $value ); ?>"><?php printf( __( '%s minutes', 'usces' ), esc_attr( $value ) ); ?></label></td> |
| 163 |
<?php endforeach; ?> |
| 164 |
<td><div id="ex_monitoring_span" class="explanation"><?php esc_html_e( 'If it fails "number of errors" times during the specified time, it is considered a "brute-force attack".', 'usces' ); ?></div></td> |
| 165 |
</tr> |
| 166 |
<tr height="35"> |
| 167 |
<th class="system_th"><a style="cursor:pointer;" onclick="toggleVisibility('ex_num_of_errors');"><?php esc_html_e( 'Number of errors', 'usces' ); ?></a></th> |
| 168 |
<?php foreach ( self::$default_option['num_of_errors'] as $value ) : ?> |
| 169 |
<td width="10"><input name="num_of_errors" type="radio" id="brute_force_num_of_errors_<?php echo esc_attr( $value ); ?>" value="<?php echo esc_attr( $value ); ?>"<?php checked( self::$opts['num_of_errors'], $value ); ?> /></td> |
| 170 |
<td width="100"><label for="brute_force_num_of_errors_<?php echo esc_attr( $value ); ?>"><?php printf( __( '%s times', 'usces' ), esc_attr( $value ) ); ?></label></td> |
| 171 |
<?php endforeach; ?> |
| 172 |
<td><div id="ex_num_of_errors" class="explanation"><?php esc_html_e( 'If it fails a specified number of times during the "monitoring span", it is considered a "brute-force attack".', 'usces' ); ?></div></td> |
| 173 |
</tr> |
| 174 |
<tr height="35"> |
| 175 |
<th class="system_th"><a style="cursor:pointer;" onclick="toggleVisibility('ex_rejection_time');"><?php esc_html_e( 'Rejection time', 'usces' ); ?></a></th> |
| 176 |
<?php foreach ( self::$default_option['rejection_time'] as $value ) : ?> |
| 177 |
<td width="10"><input name="rejection_time" type="radio" id="brute_force_rejection_time_<?php echo esc_attr( $value ); ?>" value="<?php echo esc_attr( $value ); ?>"<?php checked( self::$opts['rejection_time'], $value ); ?> /></td> |
| 178 |
<td width="100"><label for="brute_force_rejection_time_<?php echo esc_attr( $value ); ?>"><?php printf( __( '%s minutes', 'usces' ), esc_attr( $value ) ); ?></label></td> |
| 179 |
<?php endforeach; ?> |
| 180 |
<td><div id="ex_rejection_time" class="explanation"><?php esc_html_e( 'If it is considered a "brute-force attack", the login page will not be displayed for a specified period of time. (This will result in a 403 error.)', 'usces' ); ?></div></td> |
| 181 |
</tr> |
| 182 |
<tr> |
| 183 |
<th class="system_th"><a style="cursor:pointer;" onclick="toggleVisibility('ex_excluded_ip');"><?php esc_html_e( 'Excluded IP Address', 'usces' ); ?></a></th> |
| 184 |
<td colspan="6"><textarea name="excluded_ip" id="excluded_ip"><?php wel_esc_script_e( $excluded_ip ); ?></textarea></td> |
| 185 |
<td><div id="ex_excluded_ip" class="explanation"><?php esc_html_e( 'Set IP addresses to exclude from attack monitoring. When specifying multiple IP addresses, enter them in a new line. Illegal IP addresses cannot be registered.', 'usces' ); ?></div></td> |
| 186 |
</tr> |
| 187 |
</table> |
| 188 |
<hr/> |
| 189 |
<input name="usces_brute_force_option_update" type="submit" class="button button-primary" value="<?php esc_attr_e( 'change decision', 'usces' ); ?>"/> |
| 190 |
</div> |
| 191 |
</div><!--postbox--> |
| 192 |
<?php wp_nonce_field( 'admin_system', 'wc_nonce' ); ?> |
| 193 |
</form> |
| 194 |
<?php |
| 195 |
} |
| 196 |
} |
| 197 |
|