Automatic WordPress security: local firewall, malware and file-integrity scanning, vulnerability protection, quarantine, scheduled backups, an optional page cache, and automatic global threat intelligence. See README.md for installation, update, and uninstall instructions.
77 lines
2.8 KiB
PHP
77 lines
2.8 KiB
PHP
<?php
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
class Argus_WAF {
|
|
|
|
protected static $already_ran = false;
|
|
|
|
public static function inspect_and_enforce() {
|
|
|
|
if ( self::$already_ran ) {
|
|
return;
|
|
}
|
|
self::$already_ran = true;
|
|
|
|
if ( ! Argus_Settings::get( 'waf_enabled', true ) ) {
|
|
return;
|
|
}
|
|
|
|
$ip = Argus_Request_Inputs::client_ip();
|
|
|
|
if ( Argus_Challenge::maybe_handle_submission( $ip ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( Argus_Ban_Engine::is_banned( $ip ) ) {
|
|
Argus_Policy_Engine::deny_already_banned( $ip );
|
|
return;
|
|
}
|
|
|
|
if ( class_exists( 'Argus_ANIS_Client' ) && Argus_ANIS_Client::maybe_enforce( $ip ) ) {
|
|
Argus_Policy_Engine::deny_already_banned( $ip );
|
|
return;
|
|
}
|
|
|
|
$inputs = Argus_Request_Inputs::collect();
|
|
$hits = Argus_WAF_Rules::scan( $inputs );
|
|
|
|
if ( empty( $hits ) ) {
|
|
return;
|
|
}
|
|
|
|
$decision = Argus_Policy_Engine::evaluate( $ip, 'waf_match', array( 'hits' => $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 )
|
|
);
|
|
}
|
|
}
|