From 1da19ed8028f1d0beb9ec7761455ffcd7c9835ae Mon Sep 17 00:00:00 2001 From: fabriziosalmi Date: Thu, 16 Jan 2025 13:49:54 +0100 Subject: [PATCH] nginx generation improved --- owasp2nginx.py => json2nginx.py | 37 +++- owasp.py => owasp2json.py | 0 waf_patterns/nginx/README.md | 21 ++ waf_patterns/nginx/attack.conf | 85 ++----- waf_patterns/nginx/correlation.conf | 41 ++-- waf_patterns/nginx/enforcement.conf | 295 ++++++------------------- waf_patterns/nginx/evaluation.conf | 51 ++--- waf_patterns/nginx/exceptions.conf | 36 ++- waf_patterns/nginx/fixation.conf | 41 ++-- waf_patterns/nginx/generic.conf | 31 ++- waf_patterns/nginx/iis.conf | 36 ++- waf_patterns/nginx/initialization.conf | 46 ++-- waf_patterns/nginx/java.conf | 81 ++----- waf_patterns/nginx/leakages.conf | 31 ++- waf_patterns/nginx/lfi.conf | 21 +- waf_patterns/nginx/php.conf | 71 ++---- waf_patterns/nginx/rce.conf | 116 +++------- waf_patterns/nginx/rfi.conf | 26 +-- waf_patterns/nginx/shells.conf | 141 +++--------- waf_patterns/nginx/sql.conf | 81 ++----- waf_patterns/nginx/sqli.conf | 191 ++++------------ waf_patterns/nginx/xss.conf | 141 +++--------- 22 files changed, 515 insertions(+), 1105 deletions(-) rename owasp2nginx.py => json2nginx.py (70%) rename owasp.py => owasp2json.py (100%) diff --git a/owasp2nginx.py b/json2nginx.py similarity index 70% rename from owasp2nginx.py rename to json2nginx.py index c61058c..4bcd803 100644 --- a/owasp2nginx.py +++ b/json2nginx.py @@ -5,19 +5,23 @@ import logging from pathlib import Path from collections import defaultdict +# Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()], ) +# Input and output paths INPUT_FILE = Path(os.getenv("INPUT_FILE", "owasp_rules.json")) OUTPUT_DIR = Path(os.getenv("OUTPUT_DIR", "waf_patterns/nginx")) +# Create output directory if it doesn't exist OUTPUT_DIR.mkdir(parents=True, exist_ok=True) def load_owasp_rules(file_path): + """Load OWASP rules from a JSON file.""" try: with open(file_path, "r") as f: return json.load(f) @@ -30,6 +34,7 @@ def load_owasp_rules(file_path): def validate_regex(pattern): + """Validate if a pattern is a valid regex.""" try: re.compile(pattern) return True @@ -38,7 +43,11 @@ def validate_regex(pattern): def sanitize_pattern(pattern): - if "@pmFromFile" in pattern or "!@eq" in pattern or "!@within" in pattern or "@lt" in pattern: + """Sanitize and validate OWASP patterns for Nginx compatibility.""" + if any( + keyword in pattern + for keyword in ["@pmFromFile", "!@eq", "!@within", "@lt"] + ): logging.warning(f"Skipping unsupported pattern: {pattern}") return None @@ -50,6 +59,7 @@ def sanitize_pattern(pattern): def generate_nginx_waf(rules): + """Generate Nginx WAF configuration snippets from OWASP rules.""" categorized_rules = defaultdict(set) # Group rules by category @@ -69,13 +79,23 @@ def generate_nginx_waf(rules): try: with open(output_file, "w") as f: f.write(f"# Nginx WAF rules for {category.upper()}\n") + f.write("# Automatically generated from OWASP rules.\n") f.write("# Include this file in your server or location block.\n\n") - + + # Use a map to avoid redundant patterns + f.write("map $request_uri $waf_block_{category} {{\n".format(category=category)) + f.write(" default 0;\n") for pattern in patterns: escaped_pattern = pattern.replace('"', '\\"') - f.write(f'if ($request_uri ~* "{escaped_pattern}") {{\n') - f.write(" return 403;\n") - f.write("}\n\n") + f.write(f' "~*{escaped_pattern}" 1;\n') + f.write("}\n\n") + + # Apply the WAF rule + f.write("if ($waf_block_{category}) {{\n".format(category=category)) + f.write(" return 403;\n") + f.write(" # Log the blocked request (optional)\n") + f.write(" # access_log /var/log/nginx/waf_blocked.log;\n") + f.write("}\n\n") logging.info(f"Generated {output_file} ({len(patterns)} patterns)") except IOError as e: @@ -99,9 +119,14 @@ def generate_nginx_waf(rules): f.write(" ```bash\n") f.write(" sudo nginx -t && sudo systemctl reload nginx\n") f.write(" ```\n") + f.write("\n## Notes\n") + f.write("- The rules use `map` directives for efficient pattern matching.\n") + f.write("- Blocked requests return a `403 Forbidden` response by default.\n") + f.write("- You can enable logging for blocked requests by uncommenting the `access_log` line.\n") def main(): + """Main function to load rules and generate Nginx configurations.""" try: logging.info("Loading OWASP rules...") owasp_rules = load_owasp_rules(INPUT_FILE) @@ -116,4 +141,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/owasp.py b/owasp2json.py similarity index 100% rename from owasp.py rename to owasp2json.py diff --git a/waf_patterns/nginx/README.md b/waf_patterns/nginx/README.md index 8b13789..da8247d 100644 --- a/waf_patterns/nginx/README.md +++ b/waf_patterns/nginx/README.md @@ -1 +1,22 @@ +# Nginx WAF Rule Snippets +This directory contains Nginx WAF rule snippets generated from OWASP rules. +You can include these snippets in your existing Nginx configuration to enhance security. + +## Usage +1. Include the rule snippets in your `server` or `location` block: + ```nginx + server { + # Your existing configuration + include /path/to/waf_patterns/nginx/*.conf; + } + ``` +2. Reload Nginx to apply the changes: + ```bash + sudo nginx -t && sudo systemctl reload nginx + ``` + +## Notes +- The rules use `map` directives for efficient pattern matching. +- Blocked requests return a `403 Forbidden` response by default. +- You can enable logging for blocked requests by uncommenting the `access_log` line. diff --git a/waf_patterns/nginx/attack.conf b/waf_patterns/nginx/attack.conf index 2063003..b91e387 100644 --- a/waf_patterns/nginx/attack.conf +++ b/waf_patterns/nginx/attack.conf @@ -1,64 +1,27 @@ # Nginx WAF rules for ATTACK -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "^[^sv,;]+[sv,;].*?(?:application/(?:.++)?json|(?:application/(?:soap+)?|text/)xml)") { - set $attack_detected 1; - } - - if ($request_uri ~* "TX:paramcounter_(.*)") { - set $attack_detected 1; - } - - if ($request_uri ~* "content-transfer-encoding:(.*)") { - set $attack_detected 1; - } - - if ($request_uri ~* "[rn]W*?(?:content-(?:type|length)|set-cookie|location):s*w") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:bhttp/d|<(?:html|meta)b)") { - set $attack_detected 1; - } - - if ($request_uri ~* "^content-types*:s*(.*)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:get|post|head|options|connect|put|delete|trace|track|patch|propfind|propatch|mkcol|copy|move|lock|unlock)s+[^s]+s+http/d") { - set $attack_detected 1; - } - - if ($request_uri ~* "[nr]") { - set $attack_detected 1; - } - - if ($request_uri ~* "unix:[^|]*|") { - set $attack_detected 1; - } - - if ($request_uri ~* "[nr]+(?:s|location|refresh|(?:set-)?cookie|(?:x-)?(?:forwarded-(?:for|host|server)|host|via|remote-ip|remote-addr|originating-IP))s*:") { - set $attack_detected 1; - } - - if ($request_uri ~* "^[^sv,;]+[sv,;].*?b(?:((?:tex|multipar)t|application)|((?:audi|vide)o|image|cs[sv]|(?:vn|relate)d|p(?:df|lain)|json|(?:soa|cs)p|x(?:ml|-www-form-urlencoded)|form-data|x-amf|(?:octe|repor)t|stream)|([+/]))b") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 1") { - set $attack_detected 1; - } - - if ($request_uri ~* ".") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_attack { + default 0; + "~*^[^sv,;]+[sv,;].*?b(?:((?:tex|multipar)t|application)|((?:audi|vide)o|image|cs[sv]|(?:vn|relate)d|p(?:df|lain)|json|(?:soa|cs)p|x(?:ml|-www-form-urlencoded)|form-data|x-amf|(?:octe|repor)t|stream)|([+/]))b" 1; + "~*[nr]" 1; + "~*^content-types*:s*(.*)$" 1; + "~*content-transfer-encoding:(.*)" 1; + "~*(?:get|post|head|options|connect|put|delete|trace|track|patch|propfind|propatch|mkcol|copy|move|lock|unlock)s+[^s]+s+http/d" 1; + "~*@gt 1" 1; + "~*TX:paramcounter_(.*)" 1; + "~*@gt 0" 1; + "~*[rn]W*?(?:content-(?:type|length)|set-cookie|location):s*w" 1; + "~*[nr]+(?:s|location|refresh|(?:set-)?cookie|(?:x-)?(?:forwarded-(?:for|host|server)|host|via|remote-ip|remote-addr|originating-IP))s*:" 1; + "~*unix:[^|]*|" 1; + "~*." 1; + "~*(?:bhttp/d|<(?:html|meta)b)" 1; } + +if ($waf_block_attack) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/correlation.conf b/waf_patterns/nginx/correlation.conf index 8a2492f..a4e26a9 100644 --- a/waf_patterns/nginx/correlation.conf +++ b/waf_patterns/nginx/correlation.conf @@ -1,28 +1,19 @@ # Nginx WAF rules for CORRELATION -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "@ge 5") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge %{tx.inbound_anomaly_score_threshold}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge %{tx.outbound_anomaly_score_threshold}") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_correlation { + default 0; + "~*@ge %{tx.outbound_anomaly_score_threshold}" 1; + "~*@ge %{tx.inbound_anomaly_score_threshold}" 1; + "~*@ge 5" 1; + "~*@gt 0" 1; + "~*@eq 0" 1; } + +if ($waf_block_correlation) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/enforcement.conf b/waf_patterns/nginx/enforcement.conf index 4ff05fa..9b8e8ce 100644 --- a/waf_patterns/nginx/enforcement.conf +++ b/waf_patterns/nginx/enforcement.conf @@ -1,228 +1,73 @@ # Nginx WAF rules for ENFORCEMENT -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(d+)-(d+)") { - set $attack_detected 1; - } - - if ($request_uri ~* "^[^;s]+") { - set $attack_detected 1; - } - - if ($request_uri ~* "@contains #") { - set $attack_detected 1; - } - - if ($request_uri ~* "^bytes=(?:(?:d+)?-(?:d+)?s*,?s*){63}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateByteRange 38,44-46,48-58,61,65-90,95,97-122") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateUtf8Encoding") { - set $attack_detected 1; - } - - if ($request_uri ~* "@streq POST") { - set $attack_detected 1; - } - - if ($request_uri ~* "^$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.max_file_size}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^(?:(?:max-age=[0-9]+|min-fresh=[0-9]+|no-cache|no-store|no-transform|only-if-cached|max-stale(?:=[0-9]+)?)(?:s*,s*|$)){1,7}$") { - set $attack_detected 1; - } - - if ($request_uri ~* "%[0-9a-fA-F]{2}") { - set $attack_detected 1; - } - - if ($request_uri ~* ".[^.~]+~(?:/.*|)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "x25") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^0?$") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(?:GET|HEAD)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateByteRange 32-36,38-126") { - set $attack_detected 1; - } - - if ($request_uri ~* "%u[fF]{2}[0-9a-fA-F]{2}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^OPTIONS$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@within %{tx.restricted_headers_basic}") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i)x5cu[0-9a-f]{4}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.combined_file_sizes}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@endsWith .pdf") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^0$") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@pm AppleWebKit Android Business Enterprise Entreprise") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@endsWith .pdf") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@pm AppleWebKit Android") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateByteRange 1-255") { - set $attack_detected 1; - } - - if ($request_uri ~* "@within %{tx.restricted_extensions}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^(?:OPTIONS|CONNECT)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "charsets*=s*[\"']?([^;\"'s]+)") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@streq JSON") { - set $attack_detected 1; - } - - if ($request_uri ~* "charset.*?charset") { - set $attack_detected 1; - } - - if ($request_uri ~* "^bytes=(?:(?:d+)?-(?:d+)?s*,?s*){6}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 50") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.total_arg_length}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^d+$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.arg_length}") { - set $attack_detected 1; - } - - if ($request_uri ~* "b(?:keep-alive|close),s?(?:keep-alive|close)b") { - set $attack_detected 1; - } - - if ($request_uri ~* "['\";=]") { - set $attack_detected 1; - } - - if ($request_uri ~* ".([^.]+)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.max_num_args}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@within %{tx.restricted_headers_extended}") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:^|[^x5c])x5c[cdeghijklmpqwxyz123456789]") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateByteRange 32,34,38,42-59,61,65-90,95,97-122") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:^([d.]+|[[da-f:]+]|[da-f:]+)(:[d]+)?$)") { - set $attack_detected 1; - } - - if ($request_uri ~* "@gt %{tx.arg_name_length}") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^[w/.+*-]+(?:s?;s?(?:action|boundary|charset|component|start(?:-info)?|type|version)s?=s?['\"w.()+,/:=?<>@#*-]+)*$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateByteRange 9,10,13,32-126,128-255") { - set $attack_detected 1; - } - - if ($request_uri ~* "^.*$") { - set $attack_detected 1; - } - - if ($request_uri ~* "@validateUrlEncoding") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_enforcement { + default 0; + "~*!@rx ^[w/.+*-]+(?:s?;s?(?:action|boundary|charset|component|start(?:-info)?|type|version)s?=s?['\"w.()+,/:=?<>@#*-]+)*$" 1; + "~*!@rx ^(?:OPTIONS|CONNECT)$" 1; + "~*@eq 1" 1; + "~*.([^.]+)$" 1; + "~*@validateByteRange 38,44-46,48-58,61,65-90,95,97-122" 1; + "~*@gt %{tx.total_arg_length}" 1; + "~*!@streq JSON" 1; + "~*^(?:GET|HEAD)$" 1; + "~*@validateUtf8Encoding" 1; + "~*.[^.~]+~(?:/.*|)$" 1; + "~*@validateByteRange 32,34,38,42-59,61,65-90,95,97-122" 1; + "~*%u[fF]{2}[0-9a-fA-F]{2}" 1; + "~*!@pm AppleWebKit Android Business Enterprise Entreprise" 1; + "~*@gt %{tx.max_num_args}" 1; + "~*!@rx ^(?:(?:max-age=[0-9]+|min-fresh=[0-9]+|no-cache|no-store|no-transform|only-if-cached|max-stale(?:=[0-9]+)?)(?:s*,s*|$)){1,7}$" 1; + "~*^(?i)up" 1; + "~*!@pm AppleWebKit Android" 1; + "~*@streq POST" 1; + "~*^.*$" 1; + "~*!@rx ^d+$" 1; + "~*@validateUrlEncoding" 1; + "~*@gt %{tx.arg_length}" 1; + "~*@gt %{tx.combined_file_sizes}" 1; + "~*^bytes=(?:(?:d+)?-(?:d+)?s*,?s*){63}" 1; + "~*@ge 1" 1; + "~*@gt %{tx.arg_name_length}" 1; + "~*!@rx (?i)^(?:&(?:(?:[acegiln-or-suz]acut|[aeiou]grav|[ain-o]tild)e|[c-elnr-tz]caron|(?:[cgk-lnr-t]cedi|[aeiouy]um)l|[aceg-josuwy]circ|[au]ring|a(?:mp|pos)|nbsp|oslash);|[^\"';=])*$" 1; + "~*@gt 0" 1; + "~*b(?:keep-alive|close),s?(?:keep-alive|close)b" 1; + "~*@validateByteRange 32-36,38-126" 1; + "~*!@endsWith .pdf" 1; + "~*x25" 1; + "~*['\";=]" 1; + "~*^bytes=(?:(?:d+)?-(?:d+)?s*,?s*){6}" 1; + "~*@gt 50" 1; + "~*%[0-9a-fA-F]{2}" 1; + "~*charset.*?charset" 1; + "~*!@rx ^0?$" 1; + "~*!@rx ^OPTIONS$" 1; + "~*^(?i)multipart/form-data" 1; + "~*(?:^|[^x5c])x5c[cdeghijklmpqwxyz123456789]" 1; + "~*(?i)x5cu[0-9a-f]{4}" 1; + "~*charsets*=s*[\"']?([^;\"'s]+)" 1; + "~*@within %{tx.restricted_headers_extended}" 1; + "~*(?:^([d.]+|[[da-f:]+]|[da-f:]+)(:[d]+)?$)" 1; + "~*@gt %{tx.max_file_size}" 1; + "~*@endsWith .pdf" 1; + "~*@within %{tx.restricted_extensions}" 1; + "~*^$" 1; + "~*(d+)-(d+)" 1; + "~*@gt 1" 1; + "~*@validateByteRange 1-255" 1; + "~*@validateByteRange 9,10,13,32-126,128-255" 1; + "~*@within %{tx.restricted_headers_basic}" 1; + "~*^[^;s]+" 1; + "~*@eq 0" 1; + "~*@contains #" 1; + "~*!@rx ^0$" 1; + "~*^(?i)application/x-www-form-urlencoded" 1; } + +if ($waf_block_enforcement) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/evaluation.conf b/waf_patterns/nginx/evaluation.conf index c717f69..91b725e 100644 --- a/waf_patterns/nginx/evaluation.conf +++ b/waf_patterns/nginx/evaluation.conf @@ -1,36 +1,21 @@ # Nginx WAF rules for EVALUATION -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "@ge 3") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge 4") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge %{tx.inbound_anomaly_score_threshold}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge 2") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ge %{tx.outbound_anomaly_score_threshold}") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_evaluation { + default 0; + "~*@ge 3" 1; + "~*@ge 4" 1; + "~*@eq 1" 1; + "~*@ge %{tx.outbound_anomaly_score_threshold}" 1; + "~*@ge %{tx.inbound_anomaly_score_threshold}" 1; + "~*@ge 1" 1; + "~*@ge 2" 1; } + +if ($waf_block_evaluation) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/exceptions.conf b/waf_patterns/nginx/exceptions.conf index 179449d..6f8ea02 100644 --- a/waf_patterns/nginx/exceptions.conf +++ b/waf_patterns/nginx/exceptions.conf @@ -1,24 +1,18 @@ # Nginx WAF rules for EXCEPTIONS -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "@streq GET /") { - set $attack_detected 1; - } - - if ($request_uri ~* "@endsWith (internal dummy connection)") { - set $attack_detected 1; - } - - if ($request_uri ~* "@ipMatch 127.0.0.1,::1") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(?:GET /|OPTIONS *) HTTP/[12].[01]$") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_exceptions { + default 0; + "~*^(?:GET /|OPTIONS *) HTTP/[12].[01]$" 1; + "~*@ipMatch 127.0.0.1,::1" 1; + "~*@streq GET /" 1; + "~*@endsWith (internal dummy connection)" 1; } + +if ($waf_block_exceptions) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/fixation.conf b/waf_patterns/nginx/fixation.conf index 9fed171..d4d1c3f 100644 --- a/waf_patterns/nginx/fixation.conf +++ b/waf_patterns/nginx/fixation.conf @@ -1,28 +1,19 @@ # Nginx WAF rules for FIXATION -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "!@endsWith %{request_headers.host}") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(?:ht|f)tps?://(.*?)/") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(?:jsessionid|aspsessionid|asp.net_sessionid|phpsession|phpsessid|weblogicsession|session_id|session-id|cfid|cftoken|cfsid|jservsession|jwsession)$") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i:.cookieb.*?;W*?(?:expires|domain)W*?=|bhttp-equivW+set-cookieb)") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_fixation { + default 0; + "~*^(?:jsessionid|aspsessionid|asp.net_sessionid|phpsession|phpsessid|weblogicsession|session_id|session-id|cfid|cftoken|cfsid|jservsession|jwsession)$" 1; + "~*(?i:.cookieb.*?;W*?(?:expires|domain)W*?=|bhttp-equivW+set-cookieb)" 1; + "~*@eq 0" 1; + "~*!@endsWith %{request_headers.host}" 1; + "~*^(?:ht|f)tps?://(.*?)/" 1; } + +if ($waf_block_fixation) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/generic.conf b/waf_patterns/nginx/generic.conf index 7680b87..33ad608 100644 --- a/waf_patterns/nginx/generic.conf +++ b/waf_patterns/nginx/generic.conf @@ -1,20 +1,17 @@ # Nginx WAF rules for GENERIC -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "[s*constructors*]") { - set $attack_detected 1; - } - - if ($request_uri ~* "@{.*}") { - set $attack_detected 1; - } - - if ($request_uri ~* "while[sv]*([sv(]*(?:!+(?:false|null|undefined|NaN|[+-]?0|\"{2}|'{2}|`{2})|(?:!!)*(?:(?:t(?:rue|his)|[+-]?(?:Infinity|[1-9][0-9]*)|new [A-Za-z][0-9A-Z_a-z]*|window|String|(?:Boolea|Functio)n|Object|Array)b|{.*}|[.*]|\"[^\"]+\"|'[^']+'|`[^`]+`)).*)") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_generic { + default 0; + "~*while[sv]*([sv(]*(?:!+(?:false|null|undefined|NaN|[+-]?0|\"{2}|'{2}|`{2})|(?:!!)*(?:(?:t(?:rue|his)|[+-]?(?:Infinity|[1-9][0-9]*)|new [A-Za-z][0-9A-Z_a-z]*|window|String|(?:Boolea|Functio)n|Object|Array)b|{.*}|[.*]|\"[^\"]+\"|'[^']+'|`[^`]+`)).*)" 1; + "~*[s*constructors*]" 1; + "~*@{.*}" 1; } + +if ($waf_block_generic) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/iis.conf b/waf_patterns/nginx/iis.conf index 0d5fdf7..95551ee 100644 --- a/waf_patterns/nginx/iis.conf +++ b/waf_patterns/nginx/iis.conf @@ -1,24 +1,18 @@ # Nginx WAF rules for IIS -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(?:Microsoft OLE DB Provider for SQL Server(?:.{1,20}?error '800(?:04005|40e31)'.{1,40}?Timeout expired| (0x80040e31)
Timeout expired
)|

internal server error

.*?

part of the server has crashed or it has a configuration error.

|cannot connect to the server: timed out)") { - set $attack_detected 1; - } - - if ($request_uri ~* "bServer Error in.{0,50}?bApplicationb") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx ^404$") { - set $attack_detected 1; - } - - if ($request_uri ~* "[a-z]:x5cinetpubb") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_iis { + default 0; + "~*(?:Microsoft OLE DB Provider for SQL Server(?:.{1,20}?error '800(?:04005|40e31)'.{1,40}?Timeout expired| (0x80040e31)
Timeout expired
)|

internal server error

.*?

part of the server has crashed or it has a configuration error.

|cannot connect to the server: timed out)" 1; + "~*!@rx ^404$" 1; + "~*bServer Error in.{0,50}?bApplicationb" 1; + "~*[a-z]:x5cinetpubb" 1; } + +if ($waf_block_iis) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/initialization.conf b/waf_patterns/nginx/initialization.conf index f4b94df..355a4c7 100644 --- a/waf_patterns/nginx/initialization.conf +++ b/waf_patterns/nginx/initialization.conf @@ -1,32 +1,20 @@ # Nginx WAF rules for INITIALIZATION -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "@eq 1") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 100") { - set $attack_detected 1; - } - - if ($request_uri ~* "@eq 0") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx (?:URLENCODED|MULTIPART|XML|JSON)") { - set $attack_detected 1; - } - - if ($request_uri ~* "^[a-f]*([0-9])[a-f]*([0-9])") { - set $attack_detected 1; - } - - if ($request_uri ~* "^.*$") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_initialization { + default 0; + "~*@eq 100" 1; + "~*@eq 1" 1; + "~*^[a-f]*([0-9])[a-f]*([0-9])" 1; + "~*^.*$" 1; + "~*@eq 0" 1; + "~*!@rx (?:URLENCODED|MULTIPART|XML|JSON)" 1; } + +if ($waf_block_initialization) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/java.conf b/waf_patterns/nginx/java.conf index 6af4a32..ffd657f 100644 --- a/waf_patterns/nginx/java.conf +++ b/waf_patterns/nginx/java.conf @@ -1,60 +1,27 @@ # Nginx WAF rules for JAVA -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(?:runtime|processbuilder)") { - set $attack_detected 1; - } - - if ($request_uri ~* "java.lang.(?:runtime|processbuilder)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:cnVudGltZQ|HJ1bnRpbWU|BydW50aW1l|cHJvY2Vzc2J1aWxkZXI|HByb2Nlc3NidWlsZGVy|Bwcm9jZXNzYnVpbGRlcg|Y2xvbmV0cmFuc2Zvcm1lcg|GNsb25ldHJhbnNmb3JtZXI|BjbG9uZXRyYW5zZm9ybWVy|Zm9yY2xvc3VyZQ|GZvcmNsb3N1cmU|Bmb3JjbG9zdXJl|aW5zdGFudGlhdGVmYWN0b3J5|Gluc3RhbnRpYXRlZmFjdG9yeQ|BpbnN0YW50aWF0ZWZhY3Rvcnk|aW5zdGFudGlhdGV0cmFuc2Zvcm1lcg|Gluc3RhbnRpYXRldHJhbnNmb3JtZXI|BpbnN0YW50aWF0ZXRyYW5zZm9ybWVy|aW52b2tlcnRyYW5zZm9ybWVy|Gludm9rZXJ0cmFuc2Zvcm1lcg|BpbnZva2VydHJhbnNmb3JtZXI|cHJvdG90eXBlY2xvbmVmYWN0b3J5|HByb3RvdHlwZWNsb25lZmFjdG9yeQ|Bwcm90b3R5cGVjbG9uZWZhY3Rvcnk|cHJvdG90eXBlc2VyaWFsaXphdGlvbmZhY3Rvcnk|HByb3RvdHlwZXNlcmlhbGl6YXRpb25mYWN0b3J5|Bwcm90b3R5cGVzZXJpYWxpemF0aW9uZmFjdG9yeQ|d2hpbGVjbG9zdXJl|HdoaWxlY2xvc3VyZQ|B3aGlsZWNsb3N1cmU)") { - set $attack_detected 1; - } - - if ($request_uri ~* ".*.(?:jsp|jspx).*$") { - set $attack_detected 1; - } - - if ($request_uri ~* "xacxedx00x05") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)(?:[^}]{0,15}(?:$|$?)(?:{|&l(?:brace|cub);?)|jndi|ctx)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:class.module.classLoader.resources.context.parent.pipeline|springframework.context.support.FileSystemXmlApplicationContext)") { - set $attack_detected 1; - } - - if ($request_uri ~* "javab.+(?:runtime|processbuilder)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:clonetransformer|forclosure|instantiatefactory|instantiatetransformer|invokertransformer|prototypeclonefactory|prototypeserializationfactory|whileclosure|getproperty|filewriter|xmldecoder)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:unmarshaller|base64data|java.)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)(?:[^}]*(?:$|$?)(?:{|&l(?:brace|cub);?)|jndi|ctx)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:rO0ABQ|KztAAU|Cs7QAF)") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_java { + default 0; + "~*javab.+(?:runtime|processbuilder)" 1; + "~*(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)(?:[^}]*(?:$|$?)(?:{|&l(?:brace|cub);?)|jndi|ctx)" 1; + "~*(?:clonetransformer|forclosure|instantiatefactory|instantiatetransformer|invokertransformer|prototypeclonefactory|prototypeserializationfactory|whileclosure|getproperty|filewriter|xmldecoder)" 1; + "~*.*.(?:jsp|jspx).*$" 1; + "~*(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)(?:[^}]{0,15}(?:$|$?)(?:{|&l(?:brace|cub);?)|jndi|ctx)" 1; + "~*(?i)(?:$|$?)(?:{|&l(?:brace|cub);?)" 1; + "~*(?:runtime|processbuilder)" 1; + "~*xacxedx00x05" 1; + "~*(?:class.module.classLoader.resources.context.parent.pipeline|springframework.context.support.FileSystemXmlApplicationContext)" 1; + "~*(?:cnVudGltZQ|HJ1bnRpbWU|BydW50aW1l|cHJvY2Vzc2J1aWxkZXI|HByb2Nlc3NidWlsZGVy|Bwcm9jZXNzYnVpbGRlcg|Y2xvbmV0cmFuc2Zvcm1lcg|GNsb25ldHJhbnNmb3JtZXI|BjbG9uZXRyYW5zZm9ybWVy|Zm9yY2xvc3VyZQ|GZvcmNsb3N1cmU|Bmb3JjbG9zdXJl|aW5zdGFudGlhdGVmYWN0b3J5|Gluc3RhbnRpYXRlZmFjdG9yeQ|BpbnN0YW50aWF0ZWZhY3Rvcnk|aW5zdGFudGlhdGV0cmFuc2Zvcm1lcg|Gluc3RhbnRpYXRldHJhbnNmb3JtZXI|BpbnN0YW50aWF0ZXRyYW5zZm9ybWVy|aW52b2tlcnRyYW5zZm9ybWVy|Gludm9rZXJ0cmFuc2Zvcm1lcg|BpbnZva2VydHJhbnNmb3JtZXI|cHJvdG90eXBlY2xvbmVmYWN0b3J5|HByb3RvdHlwZWNsb25lZmFjdG9yeQ|Bwcm90b3R5cGVjbG9uZWZhY3Rvcnk|cHJvdG90eXBlc2VyaWFsaXphdGlvbmZhY3Rvcnk|HByb3RvdHlwZXNlcmlhbGl6YXRpb25mYWN0b3J5|Bwcm90b3R5cGVzZXJpYWxpemF0aW9uZmFjdG9yeQ|d2hpbGVjbG9zdXJl|HdoaWxlY2xvc3VyZQ|B3aGlsZWNsb3N1cmU)" 1; + "~*java.lang.(?:runtime|processbuilder)" 1; + "~*(?:rO0ABQ|KztAAU|Cs7QAF)" 1; + "~*(?:unmarshaller|base64data|java.)" 1; } + +if ($waf_block_java) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/leakages.conf b/waf_patterns/nginx/leakages.conf index 6f94b74..edb7702 100644 --- a/waf_patterns/nginx/leakages.conf +++ b/waf_patterns/nginx/leakages.conf @@ -1,20 +1,17 @@ # Nginx WAF rules for LEAKAGES -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(?:<(?:TITLE>Index of.*?Index of.*?Index of|>[To Parent Directory]
)") { - set $attack_detected 1; - } - - if ($request_uri ~* "^5d{2}$") { - set $attack_detected 1; - } - - if ($request_uri ~* "^#!s?/") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_leakages { + default 0; + "~*^#!s?/" 1; + "~*(?:<(?:TITLE>Index of.*?Index of.*?Index of|>[To Parent Directory]
)" 1; + "~*^5d{2}$" 1; } + +if ($waf_block_leakages) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/lfi.conf b/waf_patterns/nginx/lfi.conf index 13d448a..482d57f 100644 --- a/waf_patterns/nginx/lfi.conf +++ b/waf_patterns/nginx/lfi.conf @@ -1,12 +1,15 @@ # Nginx WAF rules for LFI -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(?:(?:^|[x5c/;]).{2,3}[x5c/;]|[x5c/;].{2,3}(?:[x5c/;]|$))") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_lfi { + default 0; + "~*(?:(?:^|[x5c/;]).{2,3}[x5c/;]|[x5c/;].{2,3}(?:[x5c/;]|$))" 1; } + +if ($waf_block_lfi) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/php.conf b/waf_patterns/nginx/php.conf index 2016dd0..d8dc94f 100644 --- a/waf_patterns/nginx/php.conf +++ b/waf_patterns/nginx/php.conf @@ -1,52 +1,25 @@ # Nginx WAF rules for PHP -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "(?i)php://(?:std(?:in|out|err)|(?:in|out)put|fd|memory|temp|filter)") { - set $attack_detected 1; - } - - if ($request_uri ~* ".*.ph(?:pd*|tml|ar|ps|t|pt).*$") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?i)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:" 1; + "~*.*.(?:phpd*|phtml)..*$" 1; + "~*.*.ph(?:pd*|tml|ar|ps|t|pt).*$" 1; + "~*AUTH_TYPE|HTTP_(?:ACCEPT(?:_(?:CHARSET|ENCODING|LANGUAGE))?|CONNECTION|(?:HOS|USER_AGEN)T|KEEP_ALIVE|(?:REFERE|X_FORWARDED_FO)R)|ORIG_PATH_INFO|PATH_(?:INFO|TRANSLATED)|QUERY_STRING|REQUEST_URI" 1; + "~*[oOcC]:d+:\".+?\":d+:{.*}" 1; + "~*@pm =" 1; } + +if ($waf_block_php) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/rce.conf b/waf_patterns/nginx/rce.conf index aa7501f..c0e2b71 100644 --- a/waf_patterns/nginx/rce.conf +++ b/waf_patterns/nginx/rce.conf @@ -1,88 +1,34 @@ # Nginx WAF rules for RCE -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "ba[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?l[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?i[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?a[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?sb[sv]+[!-\"%',0-9@-Z_a-z]+=[^sv]") { - set $attack_detected 1; - } - - if ($request_uri ~* "['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{]") { - set $attack_detected 1; - } - - if ($request_uri ~* "/") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?:$(?:((?:(.*)|.*))|{.*})|[<>](.*)|[!?.+])") { - set $attack_detected 1; - } - - if ($request_uri ~* ";[sv]*.[sv]*[\"']?(?:a(?:rchive|uth)|b(?:a(?:ckup|il)|inary)|c(?:d|h(?:anges|eck)|lone|onnection)|d(?:atabases|b(?:config|info)|ump)|e(?:cho|qp|x(?:cel|it|p(?:ert|lain)))|f(?:ilectrl|ullschema)|he(?:aders|lp)|i(?:mpo(?:rt|ster)|ndexes|otrace)|l(?:i(?:mi|n)t|o(?:ad|g))|(?:mod|n(?:onc|ullvalu)|unmodul)e|o(?:nce|pen|utput)|p(?:arameter|r(?:int|o(?:gress|mpt)))|quit|re(?:ad|cover|store)|s(?:ave|c(?:anstats|hema)|e(?:lftest|parator|ssion)|h(?:a3sum|ell|ow)?|tats|ystem)|t(?:ables|estc(?:ase|trl)|ime(?:out|r)|race)|vfs(?:info|list|name)|width)") { - set $attack_detected 1; - } - - if ($request_uri ~* "/(?:[?*]+[a-z/]+|[a-z/]+[?*]+)") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?is)rn.*?b(?:(?:LIST|TOP [0-9]+)(?: [0-9]+)?|U(?:SER .+?|IDL(?: [0-9]+)?)|PASS .+?|(?:RETR|DELE) [0-9]+?|A(?:POP [0-9A-Z_a-z]+ [0-9a-f]{32}|UTH [-0-9A-Z_]{1,20} (?:(?:[+/-9A-Z_a-z]{4})*(?:[+/-9A-Z_a-z]{2}=|[+/-9A-Z_a-z]{3}))?=))") { - set $attack_detected 1; - } - - if ($request_uri ~* "!-d") { - set $attack_detected 1; - } - - if ($request_uri ~* "b(?:for(?:/[dflr].*)? %+[^ ]+ in(.*)[sv]?do|if(?:/i)?(?: not)?(?: (?:e(?:xist|rrorlevel)|defined|cmdextversion)b|[ (].*(?:b(?:g(?:eq|tr)|equ|neq|l(?:eq|ss))b|==)))") { - set $attack_detected 1; - } - - if ($request_uri ~* "^[^.]*?(?:['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{])") { - set $attack_detected 1; - } - - if ($request_uri ~* "(?is)rn[0-9A-Z_a-z]{1,50}b (?:C(?:(?:REATE|OPY [*,0-:]+) [\"-#%-&*--9A-Zx5c_a-z]+|APABILITY|HECK|LOSE)|DELETE [\"-#%-&*--.0-9A-Zx5c_a-z]+|EX(?:AMINE [\"-#%-&*--.0-9A-Zx5c_a-z]+|PUNGE)|FETCH [*,0-:]+|L(?:IST [\"-#*--9A-Zx5c_a-z~]+? [\"-#%-&*--9A-Zx5c_a-z]+|OG(?:IN [--.0-9@_a-z]{1,40} .*?|OUT))|RENAME [\"-#%-&*--9A-Zx5c_a-z]+? [\"-#%-&*--9A-Zx5c_a-z]+|S(?:E(?:LECT [\"-#%-&*--9A-Zx5c_a-z]+|ARCH(?: CHARSET [--.0-9A-Z_a-z]{1,40})? (?:(KEYWORD x5c)?(?:A(?:LL|NSWERED)|BCC|D(?:ELETED|RAFT)|(?:FLAGGE|OL)D|RECENT|SEEN|UN(?:(?:ANSWER|FLAGG)ED|D(?:ELETED|RAFT)|SEEN)|NEW)|(?:BODY|CC|FROM|HEADER .{1,100}|NOT|OR .{1,255}|T(?:EXT|O)) .{1,255}|LARGER [0-9]{1,20}|[*,0-:]+|(?:BEFORE|ON|S(?:ENT(?:(?:BEFOR|SINC)E|ON)|INCE)) \"?[0-9]{1,2}-[0-9A-Z_a-z]{3}-[0-9]{4}\"?|S(?:MALLER [0-9]{1,20}|UBJECT .{1,255})|U(?:ID [*,0-:]+?|NKEYWORD x5c(Seen|(?:Answer|Flagg)ed|D(?:eleted|raft)|Recent))))|T(?:ORE [*,0-:]+? [+-]?FLAGS(?:.SILENT)? (?:(x5c[a-z]{1,20}))?|ARTTLS)|UBSCRIBE [\"-#%-&*--9A-Zx5c_a-z]+)|UN(?:SUBSCRIBE [\"-#%-&*--9A-Zx5c_a-z]+|AUTHENTICATE)|NOOP)") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(s*)s+{") { - set $attack_detected 1; - } - - if ($request_uri ~* "rn(?s:.)*?b(?:(?:QUI|STA|RSE)(?i:T)|NOOP|CAPA)") { - set $attack_detected 1; - } - - if ($request_uri ~* "s") { - set $attack_detected 1; - } - - if ($request_uri ~* "rn(?s:.)*?b(?:(?i:E)(?:HLO [--.A-Za-zx17fx212a]{1,255}|XPN .{1,64})|HELO [--.A-Za-zx17fx212a]{1,255}|MAIL FROM:<.{1,64}(?i:@).{1,255}(?i:>)|(?i:R)(?:CPT TO:(?:(?i:<).{1,64}(?i:@).{1,255}(?i:>)|(?i: ))?(?i:<).{1,64}(?i:>)|SETb)|VRFY .{1,64}(?: <.{1,64}(?i:@).{1,255}(?i:>)|(?i:@).{1,255})|AUTH [-0-9A-Z_a-zx17fx212a]{1,20}(?i: )(?:(?:[+/-9A-Z_a-zx17fx212a]{4})*(?:[+/-9A-Z_a-zx17fx212a]{2}(?i:=)|[+/-9A-Z_a-zx17fx212a]{3}))?(?i:=)|STARTTLSb|NOOPb(?:(?i: ).{1,255})?)") { - set $attack_detected 1; - } - - if ($request_uri ~* "$(?:((?:.*|(.*)))|{.*})|[<>](.*)|/[0-9A-Z_a-z]*[!?.+]") { - set $attack_detected 1; - } - - if ($request_uri ~* "rn(?s:.)*?b(?:DATA|QUIT|HELP(?: .{1,255})?)") { - set $attack_detected 1; - } - - if ($request_uri ~* "!(?:d|!)") { - set $attack_detected 1; - } - - if ($request_uri ~* "!@rx [0-9]s*'s*[0-9]") { - set $attack_detected 1; - } - - if ($request_uri ~* "^[^.]+.[^;?]+[;?](.*(['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{]))") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_rce { + default 0; + "~*ba[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?l[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?i[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?a[\"')[-x5c]*(?:(?:(?:|||&&)[sv]*)?$[!#(*-0-9?-@_a-{]*)?x5c?sb[sv]+[!-\"%',0-9@-Z_a-z]+=[^sv]" 1; + "~*['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{]" 1; + "~*rn(?s:.)*?b(?:(?i:E)(?:HLO [--.A-Za-zx17fx212a]{1,255}|XPN .{1,64})|HELO [--.A-Za-zx17fx212a]{1,255}|MAIL FROM:<.{1,64}(?i:@).{1,255}(?i:>)|(?i:R)(?:CPT TO:(?:(?i:<).{1,64}(?i:@).{1,255}(?i:>)|(?i: ))?(?i:<).{1,64}(?i:>)|SETb)|VRFY .{1,64}(?: <.{1,64}(?i:@).{1,255}(?i:>)|(?i:@).{1,255})|AUTH [-0-9A-Z_a-zx17fx212a]{1,20}(?i: )(?:(?:[+/-9A-Z_a-zx17fx212a]{4})*(?:[+/-9A-Z_a-zx17fx212a]{2}(?i:=)|[+/-9A-Z_a-zx17fx212a]{3}))?(?i:=)|STARTTLSb|NOOPb(?:(?i: ).{1,255})?)" 1; + "~*s" 1; + "~*!(?:d|!)" 1; + "~*^[^.]+.[^;?]+[;?](.*(['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{]))" 1; + "~*^[^.]*?(?:['*?x5c`][^n/]+/|/[^/]+?['*?x5c`]|$[!#-$(*-0-9?-[_a-{])" 1; + "~*!@rx [0-9]s*'s*[0-9]" 1; + "~*$(?:((?:.*|(.*)))|{.*})|[<>](.*)|/[0-9A-Z_a-z]*[!?.+]" 1; + "~*rn(?s:.)*?b(?:DATA|QUIT|HELP(?: .{1,255})?)" 1; + "~*!-d" 1; + "~*/(?:[?*]+[a-z/]+|[a-z/]+[?*]+)" 1; + "~*;[sv]*.[sv]*[\"']?(?:a(?:rchive|uth)|b(?:a(?:ckup|il)|inary)|c(?:d|h(?:anges|eck)|lone|onnection)|d(?:atabases|b(?:config|info)|ump)|e(?:cho|qp|x(?:cel|it|p(?:ert|lain)))|f(?:ilectrl|ullschema)|he(?:aders|lp)|i(?:mpo(?:rt|ster)|ndexes|otrace)|l(?:i(?:mi|n)t|o(?:ad|g))|(?:mod|n(?:onc|ullvalu)|unmodul)e|o(?:nce|pen|utput)|p(?:arameter|r(?:int|o(?:gress|mpt)))|quit|re(?:ad|cover|store)|s(?:ave|c(?:anstats|hema)|e(?:lftest|parator|ssion)|h(?:a3sum|ell|ow)?|tats|ystem)|t(?:ables|estc(?:ase|trl)|ime(?:out|r)|race)|vfs(?:info|list|name)|width)" 1; + "~*b(?:for(?:/[dflr].*)? %+[^ ]+ in(.*)[sv]?do|if(?:/i)?(?: not)?(?: (?:e(?:xist|rrorlevel)|defined|cmdextversion)b|[ (].*(?:b(?:g(?:eq|tr)|equ|neq|l(?:eq|ss))b|==)))" 1; + "~*/" 1; + "~*(?is)rn.*?b(?:(?:LIST|TOP [0-9]+)(?: [0-9]+)?|U(?:SER .+?|IDL(?: [0-9]+)?)|PASS .+?|(?:RETR|DELE) [0-9]+?|A(?:POP [0-9A-Z_a-z]+ [0-9a-f]{32}|UTH [-0-9A-Z_]{1,20} (?:(?:[+/-9A-Z_a-z]{4})*(?:[+/-9A-Z_a-z]{2}=|[+/-9A-Z_a-z]{3}))?=))" 1; + "~*(?is)rn[0-9A-Z_a-z]{1,50}b (?:C(?:(?:REATE|OPY [*,0-:]+) [\"-#%-&*--9A-Zx5c_a-z]+|APABILITY|HECK|LOSE)|DELETE [\"-#%-&*--.0-9A-Zx5c_a-z]+|EX(?:AMINE [\"-#%-&*--.0-9A-Zx5c_a-z]+|PUNGE)|FETCH [*,0-:]+|L(?:IST [\"-#*--9A-Zx5c_a-z~]+? [\"-#%-&*--9A-Zx5c_a-z]+|OG(?:IN [--.0-9@_a-z]{1,40} .*?|OUT))|RENAME [\"-#%-&*--9A-Zx5c_a-z]+? [\"-#%-&*--9A-Zx5c_a-z]+|S(?:E(?:LECT [\"-#%-&*--9A-Zx5c_a-z]+|ARCH(?: CHARSET [--.0-9A-Z_a-z]{1,40})? (?:(KEYWORD x5c)?(?:A(?:LL|NSWERED)|BCC|D(?:ELETED|RAFT)|(?:FLAGGE|OL)D|RECENT|SEEN|UN(?:(?:ANSWER|FLAGG)ED|D(?:ELETED|RAFT)|SEEN)|NEW)|(?:BODY|CC|FROM|HEADER .{1,100}|NOT|OR .{1,255}|T(?:EXT|O)) .{1,255}|LARGER [0-9]{1,20}|[*,0-:]+|(?:BEFORE|ON|S(?:ENT(?:(?:BEFOR|SINC)E|ON)|INCE)) \"?[0-9]{1,2}-[0-9A-Z_a-z]{3}-[0-9]{4}\"?|S(?:MALLER [0-9]{1,20}|UBJECT .{1,255})|U(?:ID [*,0-:]+?|NKEYWORD x5c(Seen|(?:Answer|Flagg)ed|D(?:eleted|raft)|Recent))))|T(?:ORE [*,0-:]+? [+-]?FLAGS(?:.SILENT)? (?:(x5c[a-z]{1,20}))?|ARTTLS)|UBSCRIBE [\"-#%-&*--9A-Zx5c_a-z]+)|UN(?:SUBSCRIBE [\"-#%-&*--9A-Zx5c_a-z]+|AUTHENTICATE)|NOOP)" 1; + "~*(?:$(?:((?:(.*)|.*))|{.*})|[<>](.*)|[!?.+])" 1; + "~*rn(?s:.)*?b(?:(?:QUI|STA|RSE)(?i:T)|NOOP|CAPA)" 1; + "~*^(s*)s+{" 1; } + +if ($waf_block_rce) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/rfi.conf b/waf_patterns/nginx/rfi.conf index ef3e6c5..aec42ed 100644 --- a/waf_patterns/nginx/rfi.conf +++ b/waf_patterns/nginx/rfi.conf @@ -1,16 +1,16 @@ # Nginx WAF rules for RFI -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "!@endsWith .%{request_headers.host}") { - set $attack_detected 1; - } - - if ($request_uri ~* "^(?i:file|ftps?|https?)://(?:d{1,3}.d{1,3}.d{1,3}.d{1,3})") { - set $attack_detected 1; - } - - if ($attack_detected = 1) { - return 403; - } +map $request_uri $waf_block_rfi { + default 0; + "~*!@endsWith .%{request_headers.host}" 1; + "~*^(?i:file|ftps?|https?)://(?:d{1,3}.d{1,3}.d{1,3}.d{1,3})" 1; } + +if ($waf_block_rfi) { + return 403; + # Log the blocked request (optional) + # access_log /var/log/nginx/waf_blocked.log; +} + diff --git a/waf_patterns/nginx/shells.conf b/waf_patterns/nginx/shells.conf index 2e261cd..3fd4a7d 100644 --- a/waf_patterns/nginx/shells.conf +++ b/waf_patterns/nginx/shells.conf @@ -1,108 +1,39 @@ # Nginx WAF rules for SHELLS -location / { - set $attack_detected 0; +# Automatically generated from OWASP rules. +# Include this file in your server or location block. - if ($request_uri ~* "^PHP Web Shellrnrnrn ") { - set $attack_detected 1; - } - - if ($request_uri ~* "^n n azrail [0-9.]+ by C-W-M") { - set $attack_detected 1; - } - - if ($request_uri ~* "^ *n[ ]+n[ ]+lostDC -") { - set $attack_detected 1; - } - - if ($request_uri ~* "(<title>r57 Shell Version [0-9.]+|r57 shell)") { - set $attack_detected 1; - } - - if ($request_uri ~* "B4TM4N SH3LL.*") { - set $attack_detected 1; - } - - if ($request_uri ~* "^rnrnrnPhpSpy Ver [0-9]+") { - set $attack_detected 1; - } - - if ($request_uri ~* "^rnrnGRP WebShell [0-9.]+") { - set $attack_detected 1; - } - - if ($request_uri ~* "^<html>n<head>n<title>Ru24PostWebShell -") { - set $attack_detected 1; - } - - if ($request_uri ~* "@contains <title>punkholicshell") { - set $attack_detected 1; - } - - if ($request_uri ~* "CasuS [0-9.]+ by MafiABoY") { - set $attack_detected 1; - } - - if ($request_uri ~* "^n.*? ~ Shell Inn