| @@ -12,8 +12,9 @@ | ||
| 12 | 12 | use WP_Defender\Model\Lockout_Log; |
| 13 | 13 | use WP_Defender\Traits\File_Operations; |
| 14 | 14 | use WP_Defender\Integrations\Smartcrawl; |
| 15 | 15 | use WP_Defender\Model\Setting\User_Agent_Lockout; |
| 16 | +use WP_Defender\Model\Notification\Firewall_Notification; | |
| 16 | 17 | |
| 17 | 18 | /** |
| 18 | 19 | * Handles operations to insert a weekly rotating hash URL into the footer, |
| 19 | 20 | * and blocking IP addresses that access this URL. |
| @@ -24,8 +25,9 @@ | ||
| 24 | 25 | |
| 25 | 26 | public const URL_HASH_KEY = 'wpdef_malicious_bot_url_hash'; |
| 26 | 27 | public const SCENARIO_MALICIOUS_BOT = 'malicious_bot'; |
| 27 | 28 | public const USER_AGENT_REGEX = '/(^User-agent:\s*\*)/mi'; |
| 29 | + public const URL_QUERY = 'wpdef-malicious-bot-url'; | |
| 28 | 30 | |
| 29 | 31 | /** |
| 30 | 32 | * The path to the robots.txt file. |
| 31 | 33 | * |
| @@ -104,8 +106,10 @@ | ||
| 104 | 106 | public function rotate_hash() { |
| 105 | 107 | $new_hash = $this->generate_hash(); |
| 106 | 108 | $this->set_hash( $new_hash ); |
| 107 | 109 | |
| 110 | + $this->register_rewrite_rule(); | |
| 111 | + | |
| 108 | 112 | flush_rewrite_rules(); |
| 109 | 113 | |
| 110 | 114 | $this->remove_rule(); |
| 111 | 115 | $this->inject_rule(); |
| @@ -229,22 +233,10 @@ | ||
| 229 | 233 | * @param string $uri The URI that was accessed. |
| 230 | 234 | * @param string $scenario The scenario under which the event is logged. |
| 231 | 235 | */ |
| 232 | 236 | public function log_event( $ip, $uri, $scenario ) { |
| 233 | - $model = new Lockout_Log(); | |
| 234 | - $model->ip = $ip; | |
| 235 | - $user_agent = defender_get_data_from_request( 'HTTP_USER_AGENT', 's' ); | |
| 236 | - $model->user_agent = isset( $user_agent ) ? User_Agent::fast_cleaning( $user_agent ) : null; | |
| 237 | - $model->date = time(); | |
| 238 | - $model->tried = $uri; | |
| 239 | - $model->blog_id = get_current_blog_id(); | |
| 237 | + $model = Lockout_Log::create( $ip, $uri ); | |
| 240 | 238 | |
| 241 | - $ip_to_country = $this->ip_to_country( $ip ); | |
| 242 | - | |
| 243 | - if ( isset( $ip_to_country['iso'] ) ) { | |
| 244 | - $model->country_iso_code = $ip_to_country['iso']; | |
| 245 | - } | |
| 246 | - | |
| 247 | 239 | switch ( $scenario ) { |
| 248 | 240 | case self::SCENARIO_MALICIOUS_BOT: |
| 249 | 241 | default: |
| 250 | 242 | $model->type = Lockout_Log::LOCKOUT_MALICIOUS_BOT; |
| @@ -251,8 +243,10 @@ | ||
| 251 | 243 | $model->log = esc_html__( 'Lockout occurred: Bot ignored robots.txt rules.', 'defender-security' ); |
| 252 | 244 | break; |
| 253 | 245 | } |
| 254 | 246 | $model->save(); |
| 247 | + // Notify directly because the 'defender_notify' hook isn't registered yet at firewall-time. | |
| 248 | + wd_di()->get( Firewall_Notification::class )->notify_lockout( $model ); | |
| 255 | 249 | } |
| 256 | 250 | |
| 257 | 251 | /** |
| 258 | 252 | * Creates a lockout for a blocked IP. |
| @@ -326,6 +320,16 @@ | ||
| 326 | 320 | '.*?' . preg_quote( $this->end_comment, '/' ) . '/s'; |
| 327 | 321 | $contents_without_defender = preg_replace( $defender_block_pattern, '', $contents ); |
| 328 | 322 | |
| 329 | 323 | return preg_match( $pattern, $contents_without_defender ) === 1; |
| 324 | + } | |
| 325 | + | |
| 326 | + /** | |
| 327 | + * Registers a rewrite rule for the malicious bot URL. | |
| 328 | + * The URL will be in the format: /{hash}/ | |
| 329 | + * where {hash} is a 16-character hexadecimal string. | |
| 330 | + */ | |
| 331 | + public function register_rewrite_rule() { | |
| 332 | + $hash = $this->get_hash(); | |
| 333 | + add_rewrite_rule( "^{$hash}/?$", 'index.php?' . self::URL_QUERY . '=' . $hash, 'top' ); | |
| 330 | 334 | } |
| 331 | 335 | } |