ARGUS WordPress Defence 7.23.0
Real changes since 1.0.0, all live-verified before this release: - Firewall: rule corpus expanded 19 -> 43 rules, real OWASP-CRS-equivalent coverage (XXE, SSRF, session fixation, Log4Shell/JNDI, scanner-tool detection, deeper SQL injection/XSS/PHP-injection). - Fixed a real bug: a quarantined file's severity badge and its content analysis score could disagree with no explanation (e.g. a benign file showing CRITICAL next to Score 0); both are now derived consistently and shown together. - ARGUS now always keeps itself updated, and can optionally do the same for every other installed plugin and theme (Settings, on by default) -- uses WordPress's own native update system, nothing custom. - Global Threat Intelligence is now opt-in, not automatic -- a single click on its own page, with an honest, specific description of exactly what's shared (an IP address, a reason code, a confidence score, a country). Previously connected automatically on activation. - New first-run Welcome screen after activation: confirms what's already protecting the site, and surfaces the few real optional choices in one place. - Dashboard: running version now visible in the header; new "IPs Tracked" and "ANIS Protections" metrics. - Full WordPress.org Plugin Directory readiness audit performed against this codebase. Two real compliance issues found and fixed (see above: Global Threat Intelligence's default, and the self-update mechanism, which is excluded from this build entirely -- WordPress.org prohibits a plugin from using any update channel other than its own, even an inert one). This release is still self-distributed, not a WordPress.org submission -- that remains a future step. Verified before publishing: this exact ZIP was installed, activated (14 admin pages loaded clean, zero PHP errors/warnings), and uninstalled (zero leftover database tables or options) in a fresh, disposable WordPress + MySQL environment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,11 +11,12 @@ class Argus_WAF_Rules {
|
||||
}
|
||||
|
||||
$rules = array(
|
||||
|
||||
|
||||
// --- SQL Injection (CRS 942-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'sqli-union-select', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
'pattern' => '/\bunion\b[^\w]{1,20}\bselect\b/i' ),
|
||||
array( 'id' => 'sqli-classic-tautology', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
|
||||
'pattern' => '/(\%27|\'|\%22|")\s*(or|and)\s*(\%27|\'|\%22|")?[\d\w]+(\%27|\'|\%22|")?\s*=\s*(\%27|\'|\%22|")?[\d\w]+(\%27|\'|\%22|")?/i' ),
|
||||
array( 'id' => 'sqli-information-schema', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
'pattern' => '/information_schema|sysobjects|sysdatabases/i' ),
|
||||
@@ -23,41 +24,116 @@ class Argus_WAF_Rules {
|
||||
'pattern' => '/\b(sleep|benchmark|pg_sleep|waitfor\s+delay)\s*\(/i' ),
|
||||
array( 'id' => 'sqli-stacked-comment', 'category' => 'sql_injection', 'severity' => 'high',
|
||||
'pattern' => '/;\s*(drop|delete|update|insert)\s+(table|from|into)/i' ),
|
||||
array( 'id' => 'sqli-error-based-xpath', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
'pattern' => '/\b(extractvalue|updatexml)\s*\(/i' ),
|
||||
array( 'id' => 'sqli-file-read-write', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
'pattern' => '/\b(load_file|into\s+outfile|into\s+dumpfile)\s*\(?/i' ),
|
||||
array( 'id' => 'sqli-mssql-xp-cmdshell', 'category' => 'sql_injection', 'severity' => 'critical',
|
||||
'pattern' => '/\bxp_cmdshell\b/i' ),
|
||||
array( 'id' => 'sqli-hex-literal', 'category' => 'sql_injection', 'severity' => 'medium',
|
||||
'pattern' => '/\bunhex\s*\(|0x[0-9a-f]{12,}/i' ),
|
||||
array( 'id' => 'sqli-conditional-error', 'category' => 'sql_injection', 'severity' => 'high',
|
||||
'pattern' => '/\b(and|or)\s+\d+\s*=\s*\d+\s*(--|#|\/\*)/i' ),
|
||||
|
||||
// --- Cross-Site Scripting (CRS 941-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'xss-script-tag', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/<\s*script[\s>\/]/i' ),
|
||||
|
||||
array( 'id' => 'xss-event-handler', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/\bon(error|load|mouseover|click|focus)\s*=\s*["\']?[^"\'>]*[\(\{]/i' ),
|
||||
array( 'id' => 'xss-javascript-uri', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/javascript\s*:\s*[^\s]/i' ),
|
||||
array( 'id' => 'xss-svg-onload', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/<\s*svg[^>]*onload/i' ),
|
||||
array( 'id' => 'xss-embed-object-tag', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/<\s*(iframe|object|embed)\b[^>]*(src|data)\s*=/i' ),
|
||||
array( 'id' => 'xss-data-uri-html', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/data\s*:\s*text\/html\s*;\s*base64/i' ),
|
||||
array( 'id' => 'xss-vbscript-uri', 'category' => 'xss', 'severity' => 'high',
|
||||
'pattern' => '/vbscript\s*:/i' ),
|
||||
array( 'id' => 'xss-css-expression', 'category' => 'xss', 'severity' => 'medium',
|
||||
'pattern' => '/style\s*=\s*["\'][^"\']*expression\s*\(/i' ),
|
||||
array( 'id' => 'xss-dom-sink', 'category' => 'xss', 'severity' => 'medium',
|
||||
'pattern' => '/document\s*\.\s*(cookie|write|location)\s*[=\(]|window\s*\.\s*location\s*=/i' ),
|
||||
array( 'id' => 'xss-entity-encoded-script', 'category' => 'xss', 'severity' => 'medium',
|
||||
'pattern' => '/&(lt|#0*60|#x3c)\s*;?\s*script/i' ),
|
||||
|
||||
// --- Remote Code Execution / Command Injection (CRS 932-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'cmdi-shell-metachars', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/;\s*(cat|ls|whoami|id|uname|wget|curl)\s/i' ),
|
||||
array( 'id' => 'cmdi-backtick-subshell', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/`[^`]{1,80}`|\$\([^\)]{1,80}\)/' ),
|
||||
|
||||
// --- PHP Injection (CRS 933-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'phpi-eval-base64', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/\beval\s*\(\s*(base64_decode|gzinflate|str_rot13)\s*\(/i' ),
|
||||
'pattern' => '/\beval\s*\(\s*(base64_decode|gzinflate|gzuncompress|str_rot13)\s*\(/i' ),
|
||||
array( 'id' => 'phpi-dangerous-function', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/\b(system|exec|shell_exec|passthru|proc_open|popen)\s*\(/i' ),
|
||||
'pattern' => '/\b(system|exec|shell_exec|passthru|proc_open|popen|pcntl_exec|dl)\s*\(/i' ),
|
||||
array( 'id' => 'phpi-dynamic-eval-construct', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/\b(assert|create_function|call_user_func(_array)?)\s*\(/i' ),
|
||||
array( 'id' => 'phpi-preg-replace-eval-modifier', 'category' => 'rce', 'severity' => 'critical',
|
||||
'pattern' => '/preg_replace\s*\(\s*["\'][^"\']*\/[a-zA-Z]*e[a-zA-Z]*["\']/i' ),
|
||||
array( 'id' => 'phpi-tag-in-input', 'category' => 'rce', 'severity' => 'high',
|
||||
'pattern' => '/<\?php|<\?=/i' ),
|
||||
|
||||
// --- Java / JNDI Injection (CRS 944-XXX equivalent -- Log4Shell class) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'java-jndi-lookup', 'category' => 'java_injection', 'severity' => 'critical',
|
||||
'pattern' => '/\$\{jndi:(ldap|ldaps|rmi|dns|iiop|corba|nds|http|https):\/\//i' ),
|
||||
array( 'id' => 'java-el-injection', 'category' => 'java_injection', 'severity' => 'high',
|
||||
'pattern' => '/\$\{\s*(java|javax|org\.springframework|Runtime)\s*[\.\(]/' ),
|
||||
|
||||
// --- Local / Remote File Inclusion (CRS 930/931-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'lfi-dot-dot-slash', 'category' => 'file_access', 'severity' => 'high',
|
||||
'pattern' => '/(\.\.\/|\.\.\\\\|%2e%2e%2f|%252e%252e%252f)/i' ),
|
||||
array( 'id' => 'lfi-sensitive-file', 'category' => 'file_access', 'severity' => 'high',
|
||||
'pattern' => '/\/etc\/(passwd|shadow|hosts)\b|wp-config\.php/i' ),
|
||||
array( 'id' => 'lfi-php-wrapper', 'category' => 'file_access', 'severity' => 'high',
|
||||
'pattern' => '/php:\/\/(filter|input|data)/i' ),
|
||||
'pattern' => '/(php|zip|phar|expect|glob)\s*:\/\/(filter|input|data|)/i' ),
|
||||
array( 'id' => 'rfi-remote-scheme', 'category' => 'file_access', 'severity' => 'high',
|
||||
'pattern' => '/^(https?|ftp):\/\/.+\.(php|txt)(\?|$)/i' ),
|
||||
array( 'id' => 'lfi-dotfile-path', 'category' => 'file_access', 'severity' => 'medium',
|
||||
'pattern' => '/\/\.(git|svn|env|ssh|hg)\/[\w\-\.\/]*(config|credentials|id_rsa)?/i',
|
||||
'sources' => array( 'HEADER:REQUEST_URI' ) ),
|
||||
array( 'id' => 'lfi-backup-file-request', 'category' => 'file_access', 'severity' => 'medium',
|
||||
'pattern' => '/\.(bak|old|swp|save|orig|sql|sql\.gz|tar\.gz)(\?|$)/i',
|
||||
'sources' => array( 'HEADER:REQUEST_URI' ) ),
|
||||
|
||||
// --- XML External Entity (CRS-equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'xxe-doctype-entity', 'category' => 'xxe', 'severity' => 'critical',
|
||||
'pattern' => '/<!DOCTYPE[^>]*\[.*<!ENTITY/is' ),
|
||||
array( 'id' => 'xxe-entity-system', 'category' => 'xxe', 'severity' => 'critical',
|
||||
'pattern' => '/<!ENTITY[^>]+SYSTEM\s+["\'](file|https?|ftp|expect|php):\/\//i' ),
|
||||
|
||||
// --- Server-Side Request Forgery (CRS-equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'ssrf-internal-target', 'category' => 'ssrf', 'severity' => 'high',
|
||||
'pattern' => '/^(https?|gopher|dict|ftp|ldap):\/\/(127\.\d{1,3}\.\d{1,3}\.\d{1,3}|0\.0\.0\.0|localhost|169\.254\.169\.254|\[::1\]|10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})([:\/]|$)/i' ),
|
||||
|
||||
// --- Session Fixation (CRS 943-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'session-fixation-id-in-url', 'category' => 'session_fixation', 'severity' => 'low',
|
||||
'pattern' => '/[?&](PHPSESSID|JSESSIONID|ASPSESSIONID|ASP\.NET_SessionId)=/i',
|
||||
'sources' => array( 'HEADER:REQUEST_URI' ) ),
|
||||
|
||||
// --- Scanner / Reconnaissance Detection (CRS 913-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'scanner-known-tool-ua', 'category' => 'scanner_activity', 'severity' => 'medium',
|
||||
'pattern' => '/\b(sqlmap|nikto|acunetix|nessus|openvas|w3af|havij|nmap scripting engine|masscan|zgrab|dirbuster|gobuster|wfuzz|metasploit|zmeu|wpscan)\b/i',
|
||||
'sources' => array( 'HEADER:HTTP_USER_AGENT' ) ),
|
||||
|
||||
// --- Protocol Anomaly (CRS 920-XXX equivalent) -------------------------------------------------
|
||||
|
||||
array( 'id' => 'proto-null-byte', 'category' => 'protocol_anomaly', 'severity' => 'medium',
|
||||
'pattern' => '/%00/' ),
|
||||
array( 'id' => 'proto-double-encoding', 'category' => 'protocol_anomaly', 'severity' => 'low',
|
||||
'pattern' => '/%25(2e|2f|5c)/i' ),
|
||||
array( 'id' => 'proto-crlf-injection', 'category' => 'protocol_anomaly', 'severity' => 'high',
|
||||
'pattern' => '/%0[dD]%0[aA]/' ),
|
||||
);
|
||||
|
||||
return $rules;
|
||||
@@ -74,6 +150,10 @@ class Argus_WAF_Rules {
|
||||
$decoded = rawurldecode( $value );
|
||||
|
||||
foreach ( self::corpus() as $rule ) {
|
||||
if ( ! empty( $rule['sources'] ) && ! in_array( $source, $rule['sources'], true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matched = preg_match( $rule['pattern'], $decoded, $m ) ? $m : ( preg_match( $rule['pattern'], $value, $m ) ? $m : null );
|
||||
if ( null === $matched ) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user