$hits ) ); self::record_finding( $ip, $hits, $decision ); Argus_Policy_Engine::enforce_decision( $ip, 'waf_match', $decision, array( 'hits' => $hits ) ); } protected static function record_finding( $ip, array $hits, array $decision ) { $severity = Argus_WAF_Rules::highest_severity( $hits ); $categories = array_unique( wp_list_pluck( $hits, 'category' ) ); $rule_ids = array_values( array_unique( wp_list_pluck( $hits, 'id' ) ) ); $sources = array_unique( wp_list_pluck( $hits, 'source' ) ); Argus_Findings::record( 'waf', $severity, array( 'what_happened' => sprintf( 'A request from %s matched %d local WAF rule(s): %s', $ip, count( $rule_ids ), implode( ', ', $rule_ids ) ), 'why_it_matters' => 'This request contained a pattern associated with ' . implode( ', ', $categories ) . ', a common technique used to compromise WordPress sites.', 'what_argus_found' => sprintf( 'Matched in: %s. Action taken: %s (%s).', implode( ', ', $sources ), $decision['action'], $decision['observation_only'] ? 'observed only, MONITOR mode' : 'enforced' ), 'when_it_happened' => current_time( 'mysql' ), 'why_suspicious' => 'The matched pattern is not something a normal WordPress visitor, editor, or REST API client would ever legitimately send.', 'what_could_be_affected' => 'If successful, this class of request could read or modify site data, execute code, or access files outside what the request should be able to reach.', 'what_should_you_do' => $decision['observation_only'] ? 'ARGUS is in MONITOR mode and did not block this request. Review recent WAF findings and switch to BLOCK mode once you are confident legitimate traffic is not being flagged.' : 'No action needed -- ARGUS already blocked this request. If you believe this was a false positive, add an exception for this rule or IP in Settings.', ), array( 'ip' => $ip, 'hits' => $hits, 'decision' => $decision ) ); } }