pax_global_header00006660000000000000000000000064135566054230014523gustar00rootroot0000000000000052 comment=05651137bf03ed17672fc372768da7ce4f9b28ae modsecurity-crs-3.2.0/000077500000000000000000000000001355660542300146615ustar00rootroot00000000000000modsecurity-crs-3.2.0/.github/000077500000000000000000000000001355660542300162215ustar00rootroot00000000000000modsecurity-crs-3.2.0/.github/ISSUE_TEMPLATE.md000066400000000000000000000021501355660542300207240ustar00rootroot00000000000000 ## Type of Issue ## Description ## Your Environment * CRS version (e.g. v3.0.2): * ModSecurity version (e.g. 2.9.2): * Web Server and version (e.g. apache 2.4.27): * Operating System and version: ## Confirmation [ ] I have removed any personal data (email addresses, IP addresses, passwords, domain names) from any logs posted. modsecurity-crs-3.2.0/.gitignore000066400000000000000000000005661355660542300166600ustar00rootroot00000000000000*.swp *.swo # User configuration crs-setup.conf rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf # The MaxMind GeoIP database can be downloaded or upgraded by running: # util/upgrade.py geoip util/geo-location/GeoIP.dat # Unit test caches .cache # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.classmodsecurity-crs-3.2.0/.gitmodules000066400000000000000000000002601355660542300170340ustar00rootroot00000000000000[submodule "documentation/OWASP-CRS-Documentation"] path = documentation/OWASP-CRS-Documentation url = https://github.com/SpiderLabs/OWASP-CRS-Documentation branch = master modsecurity-crs-3.2.0/.travis.yml000066400000000000000000000041151355660542300167730ustar00rootroot00000000000000language: python python: - 2.7 sudo: required services: - docker jobs: allow_failures: - env: CONFIG=3.0-apache LOGDIR=/var/log/apache2 - env: CONFIG=3.0-nginx LOGDIR=/var/log/nginx fast_finish: true include: - &test-common env: CONFIG=2.9-apache LOGDIR=/var/log/apache2 before_install: - | if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then docker build --build-arg REPO=$TRAVIS_PULL_REQUEST_SLUG \ --build-arg BRANCH=$TRAVIS_PULL_REQUEST_BRANCH \ --build-arg COMMIT=$TRAVIS_PULL_REQUEST_SHA \ -f ./util/docker/Dockerfile-$CONFIG \ -t modsecurity-crs-$CONFIG ./util/docker/ else docker build -f ./util/docker/Dockerfile-$CONFIG \ -t modsecurity-crs-$CONFIG ./util/docker/ fi - | docker run -ti -e PARANOIA=5 -d -p 80:80 \ --volume $LOGDIR:$LOGDIR \ --name "$TRAVIS_BUILD_ID" modsecurity-crs-$CONFIG - | docker ps | grep -q modsecurity-crs if [[ $? -ne 0 ]]; then docker logs "$TRAVIS_BUILD_ID" docker rm -f "$TRAVIS_BUILD_ID" exit 1 fi install: - pip install -r util/integration/requirements.txt - pip install -r util/regression-tests/requirements.txt before_script: - git clone https://github.com/CRS-support/secrules_parsing - pip install -r secrules_parsing/requirements.txt - python secrules_parsing/secrules_parser.py -c -f rules/*.conf script: - py.test -vs util/integration/format_tests.py - | py.test -vs util/regression-tests/CRS_Tests.py \ --config=$CONFIG --ruledir_recurse=util/regression-tests/tests - docker rm -f "$TRAVIS_BUILD_ID" - <<: *test-common env: CONFIG=3.0-apache LOGDIR=/var/log/apache2 - <<: *test-common env: CONFIG=3.0-nginx LOGDIR=/var/log/nginx # safelist branches: only: - v3.0/dev - v3.0/master - v3.1/dev - v3.2/dev notifications: irc: "chat.freenode.net#modsecurity" modsecurity-crs-3.2.0/CHANGES000066400000000000000000001724141355660542300156650ustar00rootroot00000000000000== OWASP ModSecurity Core Rule Set (CRS) CHANGES == == Report Bugs/Issues to GitHub Issues Tracker or the mailinglist == * https://github.com/SpiderLabs/owasp-modsecurity-crs/issues or the CRS mailinglist at * https://lists.owasp.org/mailman/listinfo/owasp-modsecurity-core-rule-set == Version 3.2.0 - 9/24/2019 == New functionality: * Add AngularJS client side template injection 941380 PL2 (Franziska Bühler) * Add docker-compose.yaml and example rule exclusion files for docker-compose (Franziska Bühler) * Add extended access.log format to Docker (Franziska Bühler) * Add libinjection check on last path segment (Max Leske, Christian Folini) * Add PUBLIC identifier for XML entities (#1490) (Rufus125) * Add .rdb to default restricted_extensions (Walter Hop) * Add .swp to default restricted_extensions (Andrea Menin) * Add rule 933200 PHP Wrappers (Andrea Menin) * Add send-payload-pls.sh script to test payload against multiple paranoia levels (Christian Folini, Manuel Spartan) * Add support for shell evasions with $IFS (Walter Hop, Chaim Sanders) * Add unix-shell commands (Christoph Hansen, Chaim Sanders) * Also inspect the path for the script tag (Federico G. Schwindt) * Detect 80legs, sysscan, Gobuster scanners (Brent Clark) * Detect CGI source code leakages (Christoph Hansen, Walter Hop) * Detect 'crawler' user-agent (Federico G. Schwindt) * Detect Jorgee, Zgrab scanners (Walter Hop) * Detect MySQL in-line comments (Franziska Bühler) * Detect Wappalyzer scanner (Christian Folini, Chaim Sanders) * Java RCE: Add struts namespaces (Walter Hop) * Java RCE: Detect more java classes (Manuel Leos) * Javascript: Add 941370 preventing a bypass for 941180 (Andrea Menin) * Make CRS variables configurable in Docker image (Franziska Bühler) * New PL3 rule 920490 to protect against content-type charset bypassing (Christian Folini) * Node.js unserialization + javascript RCE snippets (Walter Hop) * Request smuggling: Also cover pre http/1.0 requests (Federico G. Schwindt) * Restricted files: Added many dotfiles (Dan Ehrlich) * SQLi bypass detection: ticks and backticks (Franziska Bühler) * XenForo rule exclusion profile (Walter Hop) Removed functionality: * Remove unused protected_uploads setting from setup (Walter Hop) * Remove deprecated tx.msg and tx.%{rule.id}-... (Federico G. Schwindt) * Remove deprecated upgrade script (Walter Hop) Improved compatibility: * Add OWASP_CRS tags for ModSec 3 changes and replace ruleRemoveTargetByTag arguments (Ervin Hegedus) * Replace @contain % with @rx 25; ModSec 3 fails to parse % by itself (or escaped). (Federico G. Schwindt) * RE2 compatibility for 941130, 920220, 920240, 920230, 920460, 942200, 942370 (Allan Boll) * Hyperscan compatibility and simplification for 942450 (Allan Boll) Fixes and improvements: * 932140: fix ReDoS in FOR expression (Walter Hop) * 933200: Simplify pattern (Federico G. Schwindt, Andrea Menin) * 941380: fix anomaly score variable (Franziska Bühler) * 942510, 942511: fix anomaly score variable (Walter Hop) * Add content-type application/csp-report (Andrea Menin) * Add content-type application/xss-auditor-report (Andrea Menin) * Add CRS 3.2 Badge build support. (Chaim Sanders) * Add CVE numbers for Apache Struts vulnerabilities to comments in rules (Franziska Bühler) * Add CVE-2018-11776 to comments of 933160 and 933161 (Franziska Bühler) * Add CVE-2018-2380 to comments of rules (Franziska Bühler) * Add default env vars for anomaly scores in Docker (Franziska Bühler) * Add missing OWASP_CRS tags to 921xxx rules (Walter Hop) * Add REQUEST_FILENAME to rule id 944130 and add exploits to comment (Franziska Bühler) * Add spaces in front of closing square brackets (Franziska Bühler) * Add travis changes (#1316) (Chaim Sanders) * Allow dot characters in Content-Type multipart boundary (Walter Hop) * Also handle dot variant of X_Filename. PHP will transform dots to underscore in variable names since dot is invalid. (Federico G. Schwindt) * As per the ref manual, it is compressWhitespace (Federico G. Schwindt) * Avoid php leak false positive with WOFF files (Manuel Spartan) * Bring back CRS 2.x renumbering utility (Walter Hop) * Clean up travis and reorg (Federico G. Schwindt) * Code cosmetics: reorder the actions of rules (Ervin Hegedus) * Content-Type is case insensitive (Federico G. Schwindt) * Disassembled 941160 (Franziska Bühler) * Drop separate regexp files. They are not really needed and save us from updating multiple places. (Federico G. Schwindt) * Drop t:lowercase from 941350 (Federico G. Schwindt) * Drop unneeded capture groups and tidy up (Federico G. Schwindt) * Drop unneeded capture groups and tidy up regexps (Federico G. Schwindt) * Drop unneeded unicode from 941110. Add tests to cover a few more variants as well as a negative test (Federico G. Schwindt) * Fix 920440 "URL file extension is restricted by policy" regex (Andrea Menin) * Fix 920460 test (Federico G. Schwindt) * Fix 942101 and 942460 by adding to sqli_score variable (Christian Folini) * Fix checking the existence of 'HTTP' trailing request verb and request path in the payload for HTTP request smuggling; decreases false-positives on free-form text. (Yu Yagihashi) * Fix commit default for non 2.9 branch (Chaim Sanders) * Fix CRS2->CRS3 mapping table (973344 -> 941100) (Chaim Sanders) * Fix date (Chaim Sanders) * Fix Docker image SSL support (Franziska Bühler) * Fix duplicate .env (jschleus, Chaim Sanders) * Fix executing paranoia level counters (Christian Folini) * Fix indentation and python version in crs2-renumbering script (Chaim Sanders) * Fix input / headers misordering (Christian Folini) * Fix path traversal attack pattern at id:930110 (Ervin Hegedus) * Fix regexp in Docker image (Franziska Bühler) * Fix regexp with incorrect dot '.' escape in rule 943120 (XeroChen) * Fix request header Sec-Fetch-User false positive (na1ex) * Fix runaway regexp in 942260. Add variant regexp assemble script to handle possessive qualifiers. Use possessive qualifiers to tight this up and solve ReDoS problem. (Federico G. Schwindt) * Fix small typo in variable (Felipe Zipitria) * Fix spelling error in variable name (supplient) * Fix transform name pointed out by secrules_parsing (Federico G. Schwindt) * Fix Travis Merge not being able to find HEAD (Chaim Sanders) * Fix vulnerable regexp in rule 942490 (CVE-2019-11387) (Christoph Hansen) * Fix wrong regex, assembly result, in 942370 (Franziska Bühler) * INSTALL: advise to use release zips, remove upgrade.py, update Nginx (Walter Hop) * Java: change tag from COMMAND_INJECTION to JAVA_INJECTION (Manuel Spartan) * Jwall auditconsole outbound anomaly scoring requirements (Christoph Hansen) * Mark patterns not supported by re2 (Federico G. Schwindt) * Move duplicated 900270 to 900280 Fixes #1236. (Federico G. Schwindt) * Move PROXYLOCATION var (Franziska Bühler) * PHP: move get_defined_functions() and friends into PL1 (Walter Hop) * Pin the ftw version to 1.1.7 for now (Federico G. Schwindt) * Prevent bypass 933180 PHP Variable Function (Andrea Menin) * Reduce comments, introduction of triggered exploits (Franziska Bühler) * Remove all trailing spaces from ftw yaml test files (Ervin Hegedus) * Remove auditlog No other rules specify it. Add missing quotes and drop rev (Federico G. Schwindt) * Remove capture, remove tx.0, add transformation functions, fix regex, add presentation link (Andrea Menin) * Remove old and unwanted setvar constructs (Federico G. Schwindt) * Remove superfluous comments (Walter Hop) * Remove superfluous pmf (Federico G. Schwindt) * Remove t:lowercase from 920490 (Christian Folini) * Remove WARNING from php-errors.data (Andrea Menin) * Reorder actions (Federico G. Schwindt) * Replacing all @pmf with @pmFromFile (Christian Treutler) * Restricted-files.data: add AWS config (Walter Hop) * SQLI: removed unnecessary + (Christoph Hansen) * Switch Docker image to owasp/modsecurity:2.9-apache-ubuntu (Federico G. Schwindt) * unix-shell.data: fix typo in 'more' (Walter Hop) * Update .travis.yml Update to support v3.1 (Chaim Sanders) * Update dockerfile to always use 3.2/dev (Federico G. Schwindt) * Update OWASP CRS Docker image to support the new upstream and 2.9.3 (Peter Bittner, Chaim Sanders) * Update RESPONSE-950-DATA-LEAKAGES.conf (Christoph Hansen) * Update RESPONSE-959-BLOCKING-EVALUATION.conf (Christoph Hansen) * Wordpress: add support for Gutenberg editor (siric_, Walter Hop) * Wordpress: allow searching for any term in admin posts/pages overview (Walter Hop) * WordPress: exclude Gutenberg via rest_route (Walter Hop) * WordPress: exclude some more profile.php fields from RFI rule (Walter Hop) * WordPress: exclude SQL comment rule from _wp_http_referer (Walter Hop) * XML Soap Encoding fix 920240 (Christoph Hansen) Unit tests: * 932140: add regression tests (Walter Hop) * 933180: fix tests which were doing nothing (Walter Hop) * 941370: add some more tests, fix whitespace (Walter Hop) * Add more tests for 941130 (Christian Folini) * Add regression test for 941101 (Avery Wong) * Add regression tests for 942150, 942100, 942260 (Christian Folini) * Add regression tests to 941160 (Franziska Bühler) * Add some regression tests (Ervin Hegedus) * Add testing support for libmodsecurity running on Apache and Nginx (Chaim Sanders) * Add tests for 941360 that fights JSFuck and Hieroglyphy (Christian Folini) * Add tests for rule 921110 (Yu Yagihashi) * Added regression tests for rules 942320, 942360, 942361, 942210, 942380, 942410, 942470, 942120, 942240, 942160, 942190, 942140, 942490, 942120 (Christoph Hansen) * Drop tests for removed rules (Federico G. Schwindt) * Fix failing regression tests (Ervin Hegedus) * Fix failing tests (Manuel Spartan, Chaim Sanders) * Fix readme typos in example rule (Walter Hop) * Fix test 941110-2 (Federico G. Schwindt) * Fix YAML 1.2 compliance with "true" (Federico G. Schwindt) * RCE: Add tests for the for command (Federico G. Schwindt) * Update regression tests for rules 931110, 931120, 931130 (Simon Studer) Documentation: * Add details to README for Dockerhub (Franziska Bühler) * Add intro/comment to CVE comments (Franziska Bühler) * CONTRIBUTING: add note about separate PRs (Walter Hop) * Erased gitter chat. Added CII badge (Felipe Zipitria) * Replaced descriptions (Christian Folini) * Summarized authors on single line in tests for 941160 (Christian Folini) * Update broken link in regexp-assemble blog URLs (Walter Hop) * Update CONTRIBUTING.md To base changes on v3.2/dev. (Felipe Zipitría) * Update CONTRIBUTORS order (Andrea Menin) * Update README.md (Rufus125) * Updating crs site location (Chaim Sanders) == Version 3.1.1 - 2019-06-26 == * Fix CVE-2019-11387 ReDoS against CRS on ModSecurity 3 at PL 2 (Christoph Hansen, Federico G. Schwindt) * Content-Type made case insensitive in 920240, 920400 (Federico G. Schwindt) * Allow % encoding in 920240 (Christoph Hansen) * Fix bug in 920440 (Andrea Menin) * Fix bug in 920470 (Walter Hop) * Reduce false positives in 921110 (Yu Yagihashi, Federico G. Schwindt) * Fix bug in 943120 (XeroChen) == Version 3.1.0 - 8/7/2018 == * Add Detectify scanner (theMiddle) * Renaming matched_var/s (Victor Hora) * Remove lines with bare '#' comment char (Walter Hop) * Drop the XML variable from rule 932190 (Federico G. Schwindt) * Update outdated URLs (Walter Hop) * remove unused rule 901180 (Walter Hop) * Drop exit from unix and windows RCE (Federico G. Schwindt) * Fix anomaly_score counters (Federico G. Schwindt) * Remove mostly redundant 944220 in favor of 944240 (Christian Folini) * Add self[ and document[ to rule 941180 (theMiddle) * Provide proxy support within CRS docker image (Scott O'Neil) * Prevent bypass in rule 930120 PL3 (theMiddle) * Fix small typo in variable (Felipe Zipitría) * Fix bug #1166 in Docker image (Franziska Bühler) * Remove revision status from rules (Federico G. Schwindt) * Add template for issues (Federico G. Schwindt) * Correct failing travis tests in merge situations (Federico G. Schwindt) * Remove unused global variable in IIS rules (Chaim Sanders) * Refactor to use phase number instead of name (Federico G. Schwindt) * Add uploaded file name check; refresh LFI / filename checks (Walter Hop) * Introduce critical sibling of 920340 in PL2 (Walter Hop) * Fix bypass caused by multiple spaces in RCE rules (Walter Hop) * Remove unneded regex capture groups (Federico G. Schwindt) * Add built-in exceptions for CPanel (Christoph Hansen) * Add additional file restrictios for ws_ftp, DS_Store... (Jose Nazario) * Fix missing strings in 942410 (Franziska Bühler) * Add 2 missing PDO errors (Christoph Hansen) * Fix issues with FPs in regression tests (Chaim Sanders) * Add Nextcloud client exclusion support (Christoph Hansen) * Fix spelling mistakes in REQUEST-942- (Padraig Doran, Chaim Sanders) * Explicitly ignore the user defined rules (Aaron Haaf, Chaim Sanders) * Add regression tests for 942490 (Christoph Hansen, Chaim Sanders) * Add Owncloud client exclusion support (Christoph Hansen, Christian Folini) * Adding 'F-Secure Radar' vulnerability scanner UA (Christian Folini, Chaim Sanders) * Update DockerFile to use Ubuntu as base (Chaim Sanders) * False positives 942360: move alter and union (Franziska Bühler, Chaim Sanders) * Add support for Java style attacks (Manuel Spartan, Walter Hop) * Fix various regression tests issues caused by webserver handling (azhao155, Chaim Sanders) * Update TravisCI to build on a per PR basis (Chaim Sanders) * Optimized rule 921160 and regex (Allan Boll, Chaim Sanders) * Update the consistency across various files (Federico G. Schwindt) * Add missing transform, 944120 sibling 944240 (Manuel Spartan) * Fix false positive for 'like' in 942120 (Walter Hop) * Add regression tests for Java Rules (Manuel Spartan) * Fixup and small reorg of dokuwiki rule exclusion package (Christian Folini) * Make TravisCI tests fail if Apache can't load rules (Felipe Zipitría) * Add exclusion rules for Dokuwiki (Matt Bagley, Christian Folini) * Inital exclusions for NextCloud installs (Matt Bagley, Christian Folini) * Added struts-pwn UA to list (Manuel Spartan) * Uses MULTIPART_MISSING_SEMICOLON instead of MULTIPART_SEMICOLON_MISSING (Felipe Zimmerle) * Add file upload checks (Manuel Spartan) * Check if Transfer-Encoding is missing (Federico G. Schwindt, Christian Folini) * Remove duplicated variables (Federico G. Schwindt) * Reduce FP by splitting classic SQL injection rule 942370 (Christoph Hansen) * Fix typo in REQUEST-920-PROTOCOL-ENFORCEMENT (ihacku, Franziska Bühler) * Add configurable timestamp format to FTW integration (Christian Folini) * Add badges to README (Felipe Zipitría) * Add clarifying comments to 910110 (Christian Folini) * Making rule 933131 case-insensitive (Manuel Spartan) * Merge and reorder rules as part of cleanup (Federico G. Schwindt) * Update copyright date and syntax (Jose Nazario, Felipe Zipitría) * Updated SecMarker and SkipAfter names to use meet guidelines (Felipe Zipitría) * Tidy up single quotes and other guidelines updates (Felipe Zipitría) * Syntax fix for setvar crs_exclusions_wordpress (Manuel Spartan) * Updated various contributors to developers (Christian Folini) * Revise SQL rules by disassembling them into their core protections (Franziska Bühler) * Add an exmaple payload to 920220 (coolt) * Add a missing regex to rule 942310 (Franziska Bühler) * Detect GET or HEAD with Transfer-Encoding header (Federico G. Schwindt) * Fix broken links in references (Pásztor Gábor) * Add contributing guidelines (Felipe Zipitría) * Fix processing bypasses in rule 931130 (Felipe Zipitría, Christian Folini) * Correct small omissions in unix-shell.data (Walter Hop) * Add IIS specific detection to LFI-os-files.data (Manuel Spartan) * Update examples to match the current cleanup (Federico G. Schwindt) * Corrected the ordering of actions to meet guidelines (Felipe Zipitría) * Remove unused capture groups (Federico G. Schwindt) * Use explicit rx operator (Federico G. Schwindt) * Update the RCE regular expressions(Walter Hop, Federico G. Schwindt) * Removing maturity & accuracy from rules (Felipe Zipitría) * Increasing range header (Christoph Hansen) * Fixed upgrade.py script argument options (Glyn Mooney) * Updating to reflect OWASP flagship status (Chaim Sanders) * Adding Docker support for CRS (Chaim Sanders) * Initial Travis deployment (Zack Allen, Walter Hop) * Inital commit of regression tests (Chaim Sanders, Walter Hop) * Remove test for 921170 because it won't ever fire (Chaim Sanders, Walter Hop) * Update minor incorrectness in asp.net regex (Chaim Sanders, Walter Hop) * Add notification for builds against #modsecurity on freenode (Zack Allen, Walter Hop) * Add all past code contributors and convert to markdown (Walter Hop) * Block uploads of files with .phps extension (Walter Hop) * Improve message for script upload with superfluous extension (Walter Hop) * Remove trailing whitespace in various regexs (Walter Hop) * Add command popd to direct unix rce list in rule 932150 (Franziska Bühler) * Remove unnecessary END_XSS_CHECKS marker (Christian Folini) * Ignore Whitespaces in Rule 942110 (Christoph Hansen) * Update missing RCE Commands (Umar Farook) * Update lfi-os-files.data (Umar Farook) * Removed deprecated t:removeComments from 942100 (Christian Folini) * Add word boundary to rule 942410 (Franziska Bühler) == Version 3.0.2 - 5/12/2017 == * Remove debug rule that popped up in 3.0.1 (Christian Folini) == Version 3.0.1 - 5/9/2017 == * SECURITY: Removed insecure handling of X-Forwarded-For header; reported by Christoph Hansen (Walter Hop) * Fixed documentation errors in RESPONSE-999-... (Chaim Sanders) * Reduced FPs on 942190 by adding a word boundary to regex (Franziska Bühler) * Reduced FPs on 932150 by removing keyword reset (Franziska Bühler) * Tidied exceptions in 930100 (Roberto Paprocki) * Reduced FPs for 920120 by splitting into stricter sibling (Franziska Bühler) * Simplified some Drupal rule exclusions (Damien McKenna, Christian Folini) * Extended KNOWN_BUGS with remarks on JSON support on Debian (Franziska Bühler) * Updated README to add gitter support (Chaim Sanders) * Clarified DoS documentation for static extensions (Roberto Paprocki) * Added application/octet-stream to allowed content types (Christian Folini) * Typo in 942220 alert message (Chaim Sanders, @bossloper) * Moved referrer check of 941100 into new PL2 rule (Franziska Bühler) * Closed multiple @pmf evasions via lowercase transformation (Roberto Paprocki) * Clarified libinjection bundling in INSTALL file (@cjdp) * Reduced FPs via Wordpress Rule Exclusions (Walter Hop) * Support for RFC 3902 (Content Type application/soap+xml; Christoph Hansen) Make sure you update ModSecurity recommended rule 200000 as well. * Bugfix in 942410 regex (Christian Folini) * Reduced FPs for 942360 (Walter Hop) * Reduced FPs for 941120 by restricting event handler names (Franziska Bühler) * Extended 931000 with scheme "file" to fix false negative (Federico Schwindt) * Extended 905100 and 905110 for HTTP/2.0 (includes bugfix, Christoph Hansen) * Moved 941150 from PL1 to PL2; includes Bugfix for rule (Christian Folini) * Updated documentation for 920260 (Chaim Sanders) * Bugfix in upgrade.py (Victor Hora) * Fixed FP in RCE rule 932140 (Walter Hop) * Fixed comment for arg limit check rule 920370 (Christian Folini) * Created CONTRIBUTORS file * Added Christoph Hansen (emphazer) to CONTRIBUTORS file * Added Franziska Bühler (franbuehler) to CONTRIBUTORS file * Fixed bug with DoS rule 912160 (@loudly-soft, Christian Folini) == Version 3.0.0 - 11/10/2016 == Huge changeset running in separate branch from September 2013 to September 2016. This is a cursory summary of the most important changes: * Huge reduction of false positives (Ryan Barnett, Felipe Zimmerle, Chaim Sanders, Walter Hop, Christian Folini) * Anomaly scoring is the new default, renamed thresholds from tx.(in|out)bound_anomaly_score_level to tx.(in|out)bound_anomaly_score_threshold * Introduction of libinjection for SQLi detection * Introduction of libinjection for XSS detection * Big improvement on detection of Remote Command Execution (Walter Hop) * Big improvement on PHP function name detection (Walter Hop) * Paranoia Mode (Christian Folini, Noël Zindel, Franziska Bühler, Manuel Leos, Walter Hop) * Shifted dozens of rules into higher paranoia levels * Introduced a lot of stricter sibling rules in higher levels * Generic mechanism to support application specific rule exclusions (Chaim Sanders) * Initial Wordpress rule exclusions (Walter Hop) * Initial Drupal rule exclusions (Christian Folini, @emphazer) * Renumbering of rules. See folder id_renumbering for a csv map (Chaim Sanders) * Consolidation of rules, namely XSS and SQLi (Spider Labs/Trustwave team) * Sampling mode / Easing in (Christian Folini) * Cleanup of reputation checks / persistent blocking (Christian Folini / Walter Hop) * Tags much more systematic (Walter Hop) * IP reputation checks / persistent blocking of certain clients (Spider Labs/Trustwave team) * Phase actions use request/response/logging now instead of numerical phases (Spider Labs/Trustwave team) * Added NoScript XSS Filters (Spider Labs/Trustwave team) * Updated "severity" action to use words (CRITICAL, WARNING, etc...) vs. numbers (5, 4, etc..) * Various regex fixes after research by Vladimir Ivanov (Chaim Sanders) * Overhaul of the regression mode into debug mode (Walter Hop, Ryan Barnett) * Introduction of util/upgrade.py (Walter Hop) * Removal of GeoIP database. Download via util/upgrade.py now. * Introduction of Initialization rules with default values (Walter Hop, Christian Folini) * Sorting out terminology with whitelisting and rule exclusions (Christian Folini) * Overhaul of testing (Chaim Sanders) * Protection from HTTP Parameter Pollution (Franziska Bühler) * Simplification of setup config file, renamed file to crs-setup.conf.example * Improved session fixation detection logic (Christian Peron, credits to Eric Hodel for the discovery) * Updated list of malicious webscanners * Splitting scanner user agents data files (github user @ygrek) * Countless bugfixes in severities, anomaly scores, tags, etc. across the board * Cleanup of formerly experimental DDoS rules, fix documentation (Ryan Barnett, Christian Folini) * Improves http blacklist checks (Walter Hop) * Extended XSS detection (as suggested by Mazin Ahmed) * Added support for Travis CI * Added support for HTTP/2 in recent Apache 2.4 (Walter Hop) * Added many, many bots and scanners (among others suggested by github user @toby78, @jamuse, Matt Koch) * Fixed mime types suitable for XML processor (Chaim Sanders) * Include script in util/join-multiline-rules to work around Apache 2.4 < 2.4.11 bug with long lines (Walter Hop) * New detection for request smuggling attacks (Achim Hofmann, Christian Folini) * Fixes with project honeypot setup (Ryan Barnett) * Separated DB / SQL messages by DB software (Ryan Barnett) * CPanel integration (Chaim Sanders) * Introduction of var for static resources (Chaim Sanders) * Many improvements to rules in 2014/5 (Ryan Barnett) == Version 2.2.9 - 09/30/2013 == Security Fixes: Improvements: * Updated the /util directory structure Bug Fixes: * fix 950901 - word boundary added * modsecurity_35_bad_robots.data - gecko/25 blocks Firefox Android https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/157 == Version 2.2.8 - 06/30/2013 == Security Fixes: Improvements: * Updatd the /util directory structure * Added scripts to check Rule ID duplicates * Added script to remove v2.7 actions so older ModSecurity rules will work - https://github.com/SpiderLabs/owasp-modsecurity-crs/pull/43 * Added new PHP rule (958977) to detect PHP exploits (Plesk 0-day from king cope) - http://seclists.org/fulldisclosure/2013/Jun/21 - http://blog.spiderlabs.com/2013/06/honeypot-alert-active-exploits-attempts-for-plesk-vulnerability-.html Bug Fixes: * fix 950901 - word boundary added - https://github.com/SpiderLabs/owasp-modsecurity-crs/pull/48 * fix regex error - https://github.com/SpiderLabs/owasp-modsecurity-crs/pull/44 * Updated the Regex in 981244 to include word boundaries - https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/36 * Problem with Regression Test (Invalid use of backslash) - Rule 960911 - Test2 - https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/34 * ModSecurity: No action id present within the rule - ignore_static.conf - https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/17 * "Bad robots" rule blocks all Java applets on Windows XP machines - https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/16 * duplicated rules id 981173 - https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/18 == Version 2.2.7 - 12/19/2012 == Security Fixes: Improvements: * Added JS Overrides file to identify successfull XSS probes * Added new XSS Detection Rules from Ashar Javed (http://twitter.com/soaj1664ashar) - http://jsfiddle.net/U9RmU/4/ * Updated the SQLi Filters to add in Oracle specific functions - https://github.com/SpiderLabs/owasp-modsecurity-crs/pull/7 Bug Fixes: * Fixed Session Hijacking rules - https://github.com/SpiderLabs/owasp-modsecurity-crs/pull/8 * Fixed bug in XSS rules checking TX:PM_XSS_SCORE variable == Version 2.2.6 - 09/14/2012 == Security Fixes: Improvements: * Started rule formatting update for better readability * Added maturity and accuracy action data to each rule * Updated rule revision (rev) action * Added rule version (ver) action * Added more regression tests (util/regression_tests/) * Modified Rule ID 960342 to block large file attachments in phase:1 * Removed all PARANOID rule checks * Added new Session Fixation rules Bug Fixes: * Fixed missing ending double-quotes in XSS rules file * Moved SecDefaultAction setting from phase:2 to phase:1 * Fixed Session Hijacking SessionID Regex https://www.modsecurity.org/tracker/browse/CORERULES-79 * Changed the variable listing for many generic attack rules to exclude REQUEST_FILENAME https://www.modsecurity.org/tracker/browse/CORERULES-78 == Version 2.2.5 - 06/14/2012 == Security Fixes: * Updated the anomaly scoring value for rule ID 960000 to critical (Identified by Qualys Vulnerability & Malware Research Labs (VMRL)) (https://community.qualys.com/blogs/securitylabs/2012/06/15/modsecurity-and-modsecurity-core-rule-set-multipart-bypasses) * Updated Content-Type check to fix possible evasion with @within (Identified by Qualys Vulnerability & Malware Research Labs (VMRL)) (https://community.qualys.com/blogs/securitylabs/2012/06/15/modsecurity-and-modsecurity-core-rule-set-multipart-bypasses) Improvements: * Renamed main config file to modsecurity_crs_10_setup.conf * Updated the rule IDs to start from CRS reserved range: 900000 * Updated rule formatting for readibility * Updated the CSRF rules to use UNIQUE_ID as the token source * Added the zap2modsec.pl script to the /util directory which converts OWASP ZAP Scanner XML data into ModSecurity Virtual Patches * Updated the Directory Traversal Signatures to include more obfuscated data * Added Arachni Scanner Integration Lua script/rules files Bug Fixes: * Added forceRequestBodyVariable action to rule ID 960904 == Version 2.2.4 - 03/14/2012 == Improvements: * Added Location and Set-Cookie checks to Response Splitting rule ID 950910 * Added a README file to the activated_rules directory * Consolidate a number of SQL Injection rules into optimized regexs * Removed multiMatch and replaceComments from SQL Injection rules * Updated the SQLi regexs for greediness * Updated the SQLi setvar anomaly score values to use macro expansion * Removed PARANOID mode rules Bug Fixes: * Fixed missing comma before severity action in rules 958291, 958230 and 958231 * Fixed duplidate rule IDs == Version 2.2.3 - 12/19/2011 == Improvements: * Added Watcher Cookie Checks to optional_rules/modsecurity_crs_55_appication_defects.conf file http://websecuritytool.codeplex.com/wikipage?title=Checks#cookies * Added Watcher Charset Checks to optional_rules/modsecurity_crs_55_application_defects.conf file http://websecuritytool.codeplex.com/wikipage?title=Checks#charset * Added Watcher Header Checks to optional_rules/modsecurity_crs_55_application_defects.conf file http://websecuritytool.codeplex.com/wikipage?title=Checks#header Bug Fixes: * Fixed Content-Type evasion issue by adding ctl:forceRequestBodyVariable action to rule ID 960010. (Identified by Andrew Wilson of Trustwave SpiderLabs). * Updated the regex and added tags for RFI rules. == Version 2.2.2 - 09/28/2011 == Improvements: * Updated the AppSensor Profiling (to use Lua scripts) for Request Exceptions Detection Points * Added new Range header detection checks to prevent Apache DoS * Added new Security Scanner User-Agent strings * Added example script to the /util directory to convert Arachni DAST scanner XML data into ModSecurity virtual patching rules. * Updated the SQLi Character Anomaly Detection Rules * Added Host header info to the RESOURCE collection key for AppSensor profiling rules Bug Fixes: * Fixed action list for XSS rules (replaced pass,nolog,auditlog with block) * Fixed Request Limit rules by removing & from variables * Fixed Session Hijacking IP/UA hash captures * Updated the SQLi regex for rule ID 981242 == Version 2.2.1 - 07/20/2011 == Improvements: * Extensive SQL Injection signature updates as a result of the SQLi Challenge http://www.modsecurity.org/demo/challenge.html * Updated the SQL Error message detection in reponse bodies * Updated SQL Injection signatures to include more DB functions * Updated the WEAK SQL Injection signatures * Added tag AppSensor/RE8 to rule ID 960018 Bug Fixes: * Fixed Bad Robot logic for rule ID 990012 to further qualify User-Agent matches https://www.modsecurity.org/tracker/browse/CORERULES-70 * Fixed Session Hijacking rules to properly capture IP address network hashes. * Added the multiMatch action to the SQLi rules * Fixed a false negative logic flaw within the advanced_filter_converter.lua script * Fixed missing : in id action in DoS ruleset. * Updated rule ID 971150 signature to remove ; == Version 2.2.0 - 05/26/2011 == Improvements: * Changed Licensing from GPLv2 to Apache Software License v2 (ASLv2) http://www.apache.org/licenses/LICENSE-2.0.txt * Created new INSTALL file outlining quick config setup * Added a new rule regression testing framework to the /util directory * Added new activated_rules directory which will allow users to place symlinks pointing to files they want to run. This allows for easier Apache Include wild-carding * Adding in new RULE_MATURITY and RULE_ACCURACY tags * Adding in a check for X-Forwarded-For source IP when creating IP collection * Added new Application Defect checks (55 app defect file) from Watcher tool (Check Charset) http://websecuritytool.codeplex.com/wikipage?title=Checks#charset * Added new AppSensor rules to experimental_dir https://www.owasp.org/index.php/AppSensor_DetectionPoints * Added new Generic Malicious JS checks in outbound content * Added experimental IP Forensic rules to gather Client hostname/whois info http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html * Added support for Mozilla's Content Security Policy (CSP) to the experimental_rules http://blog.spiderlabs.com/2011/04/modsecurity-advanced-topic-of-the-week-integrating-content-security-policy-csp.html * Global collection in the 10 file now uses the Host Request Header as the collection key. This allows for per-site global collections. * Added new SpiderLabs Research (SLR) rules directory (slr_rules) for known vulnerabilties. This includes both converted web rules from Emerging Threats (ET) and from SLR Team. * Added new SLR rule packs for known application vulns for WordPress, Joomla and phpBB * Added experimental rules for detecting Open Proxy Abuse http://blog.spiderlabs.com/2011/03/detecting-malice-with-modsecurity-open-proxy-abuse.html * Added experimental Passive Vulnerability Scanning ruleset using OSVDB and Lua API http://blog.spiderlabs.com/2011/02/modsecurity-advanced-topic-of-the-week-passive-vulnerability-scanning-part-1-osvdb-checks.html * Added additional URI Request Validation rule to the 20 protocol violations file (Rule ID - 981227) * Added new SQLi detection rules (959070, 959071 and 959072) * Added "Toata dragostea mea pentru diavola" to the malicious User-Agent data https://www.modsecurity.org/tracker/browse/CORERULES-64 Bug Fixes: * Assigned IDs to all active SecRules/SecActions * Removed rule inversion (!) from rule ID 960902 * Fixed false negative issue in Response Splitting Rule * Fixed false negative issue with @validateByteRange check * Updated the TARGETS lising for rule ID 950908 * Updated TX data for REQBODY processing * Changed the pass action to block in the RFI rules in the 40 generic file * Updated RFI regex to catch IP address usage in hostname https://www.modsecurity.org/tracker/browse/CORERULES-68 * Changed REQUEST_URI_RAW variable to REQUEST_LINE in SLR rules to allow matches on request methods. * Updated the RFI rules in the 40 generic attacks conf file to remove explicit logging actions. They will now inherit the settings from the SecDefaultAction == Version 2.1.2 - 02/17/2011 == Improvements: * Added experimental real-time application profiling ruleset. * Added experimental Lua script for profiling the # of page scripts, iframes, etc.. which will help to identify successful XSS attacks and planting of malware links. * Added new CSRF detection rule which will trigger if a subsequent request comes too quickly (need to use the Ignore Static Content rules). Bug Fixes: * Added missing " in the skipAfter SecAction in the CC Detection rule set == Version 2.1.1 - 12/30/2010 == Bug Fixes: * Updated the 10 config conf file to add in pass action to User-Agent rule * Updated the CSRF ruleset to conditionally do content injection - if the csrf token was created by the session hijacking conf file * Updated the session hijacking conf file to only enforce rules if a SessionID Cookie was submitted * Fixed macro expansion setvar bug in the restricted file extension rule * Moved the comment spam data file into the optional_rules directory == Version 2.1.0 - 12/29/2010 == Improvements: * Added Experimental Lua Converter script to normalize payloads. Based on PHPIDS Converter code and it used with the advanced filters conf file. * Changed the name of PHPIDS converted rules to Advanced Filters * Added Ignore Static Content (Performance enhancement) rule set * Added XML Enabler (Web Services) rule set which will parse XML data * Added Authorized Vulnerability Scanning (AVS) Whitelist rule set * Added Denial of Service (DoS) Protection rule set * Added Slow HTTP DoS (Connection Consumption) Protection rule set * Added Brute Force Attack Protection rule set * Added Session Hijacking Detection rule set * Added Username Tracking rule set * Added Authentication Tracking rule set * Added Anti-Virus Scanning of File Attachments rule set * Added AV Scanning program to /util directory * Added Credit Card Usage Tracking/Leakage Prevention rule set * Added experimental CC Track/PAN Leakage Prevention rule set * Added an experimental_rules directory to hold new BETA rules * Moved the local exceptions conf file back into base_rules dirctory however it has a ".example" extension to prevent overwriting customized versions when upgrading * Separated out HTTP Parameter Pollution and Restricted Character Anomaly Detection rules to the experimental_rules directory * Adding the REQUEST_HEADERS:User-Agent macro data to the initcol in 10 config file, which will help to make collections a bit more unique == Version 2.0.10 - 11/29/2010 == Improvements: * Commented out the Anomaly Scoring Blocking Mode TX variable since, by default, the CRS is running in traditional mode. Bug Fixes: * Moved all skipAfter actions in chained rules to chain starter SecRules https://www.modsecurity.org/tracker/browse/MODSEC-159 * Changed phases on several rules in the 20 protocol anomaly rules file to phase:1 to avoid FNs == Version 2.0.9 - 11/17/2010 == Improvements: * Changed the name of the main config file to modsecurity_crs_10_config.conf.example so that it will not overwrite existing config settings. Users should rename this file to activate it. * Traditional detection mode is now the current default * Users can now more easily toggle between traditional/standard mode vs. anomaly scoring mode by editing the modsecurity_crs_10_config.conf file * Updated the disruptive actions in most rules to use "block" action instead of "pass". This is to allow for the toggling between traditional vs. anomaly scoring modes. * Removed logging actions from most rules so that it can be controlled from the SecDefaultAction setting in the modsecurity_crs_10_config.conf file * Updated the anomaly scores in the modsecurity_crs_10_config.conf file to more closely match what is used in the PHPIDS rules. These still have the same factor of severity even though the numbers themselves are smaller. * Updated the 49 and 59 blocking rules to include the matched logdata * Updated the TAG data to further classify attack/vuln categories. * Updated the SQL Injection filters to detect more boolean logic attacks * Moved some files to optional_rules directory (phpids, Emerging Threats rules) Bug Fixes: * Fixed Rule ID 960023 in optional_rules/modsecurity_crs_40_experimental.conf is missing 1 single quote https://www.modsecurity.org/tracker/browse/CORERULES-63 * Moved all skipAfter actions in chained rules to the rule starter line (must have ModSec v2.5.13 or higher) https://www.modsecurity.org/tracker/browse/MODSEC-159 * Fixed restricted file extension bug with macro expansion https://www.modsecurity.org/tracker/browse/CORERULES-60 * Updated the SQLI TX variable macro expansion data in the 49 and 60 files so that it matches what is being set in the sql injection conf file * Fixed typo in SQL Injection regexs - missing backslash for word boundary (b) https://www.modsecurity.org/tracker/browse/CORERULES-62 == Version 2.0.8 - 08/27/2010 == Improvements: * Updated the PHPIDS filters * Updated the SQL Injection filters to detect boolean attacks (1<2, foo == bar, etc..) * Updated the SQL Injection fitlers to account for different quotes * Added UTF-8 encoding validation support to the modsecurity_crs_10_config.conf file * Added Rule ID 950109 to detect multiple URL encodings * Added two experimental rules to detect anomalous use of special characters Bug Fixes: * Fixed Encoding Detection RegEx (950107 and 950108) * Fixed rules-updater.pl script to better handle whitespace https://www.modsecurity.org/tracker/browse/MODSEC-167 * Fixed missing pass action bug in modsecurity_crs_21_protocol_anomalies.conf https://www.modsecurity.org/tracker/browse/CORERULES-55 * Fixed the anomaly scoring in the modsecurity_crs_41_phpids_filters.conf file https://www.modsecurity.org/tracker/browse/CORERULES-54 * Updated XSS rule id 958001 to improve the .cookie regex to reduce false postives https://www.modsecurity.org/tracker/browse/CORERULES-29 == Version 2.0.7 - 06/4/2010 == Improvements: * Added CSRF Protection Ruleset which will use Content Injection to add javascript to specific outbound data and then validate the csrf token on subsequent requests. * Added new Application Defect Ruleset which will identify/fix missing HTTPOnly cookie flags * Added Experimental XSS/Missing Output Escaping Ruleset which looks for user supplied data being echoed back to user unchanged. * Added rules-updater.pl script and configuration file to allow users to automatically download CRS rules from the CRS rules repository. * Added new SQLi keyword for ciel() and reverse() functions. * Updated the PHPIDS filters Bug Fixes: * Fixed false positives for Request Header Name matching in the 30 file by adding boundary characters. * Added missing pass actions to @pmFromFile prequalifier rules * Added backslash to SQLi regex https://www.modsecurity.org/tracker/browse/CORERULES-41 * Fixed hard coded anomaly score in PHPIDS filter file https://www.modsecurity.org/tracker/browse/CORERULES-45 * Fixed restricted_extension false positive by adding boundary characters == Version 2.0.6 - 02/26/2010 == Bug Fixes: * Added missing transformation functions to SQLi rules. https://www.modsecurity.org/tracker/browse/CORERULES-32 * Fixed duplicate rule IDs. https://www.modsecurity.org/tracker/browse/CORERULES-33 * Fixed typo in @pmFromFile in the Comment SPAM rules https://www.modsecurity.org/tracker/browse/CORERULES-34 * Added macro expansion to Restricted Headers rule https://www.modsecurity.org/tracker/browse/CORERULES-35 * Fixed misspelled SecMarker https://www.modsecurity.org/tracker/browse/CORERULES-36 * Fixed missing chain action in Content-Type header check https://www.modsecurity.org/tracker/browse/CORERULES-37 * Update phpids filters to use pass action instead of block == Version 2.0.5 - 02/01/2010 == Improvements: * Removed previous 10 config files as they may conflict with local customized Mod configs. * Added a new 10 config file that allows the user to globally set TX variables to turn on/off PARANOID_MODE inspection, set anomaly score levels and http policies. Must have ModSecurity 2.5.12 to use the macro expansion in numeric operators. * Added Rule Logic and Reference links to rules descriptions. * Added Rule IDs to all rules. * Added tag data mapping to new OWASP Top 10 and AppSensor Projects, WASC Threat Classification * Removed Apache limit directives from the 23 file * Added macro expansion to 23 file checks. * Added @pmFromFile check to 35 bad robots file * Added malicious UA strings to 35 bad robots check * Created an experimental rules file * Updated HTTP Parameter Pollution (HPP) rule logic to concat data into a TX variable for inspection * Removed TX inspections for generic attacks and reverted to standard ARGS inspection https://www.modsecurity.org/tracker/browse/MODSEC-120 * Updated the variable list for standard inspections (ARGS|ARGS_NAMES|XML:/*) and moved the other variables to the PARANOID list (REQUEST_URI|REQUEST_BODY|REQUEST_HEADERS|TX:HPP_DATA) * Moved converted ET Snort rules to the /optional_rules directory * Created a new Header Tagging ruleset (optional_rules) that will add matched rule data to the request headers. * Updated Inbound blocking conf file to use macro expansion from the 10 config file settings * Added separate anomaly scores for inbound, outbound and total to be evaluated for blocking. * Updated the regex logic in the (1=1) rule to factor in quotes and other logical operators. * Updated the SPAMMER RBL check rules logic to only check once per IP/Day. * Added new outbound malware link detection rules. * Added PHP "call_user_func" to blacklist Identified by SOGETI ESEC R&D Bug Fixes: * Removed Non-numeric Rule IDs https://www.modsecurity.org/tracker/browse/CORERULES-28 * Updated the variable list on SQLi rules. * Fixed outbound @pmFromFile action from allow to skipAfter to allow for outbound anomaly scoring and blocking == Version 2.0.4 - 11/30/2009 == Improvements: * Updated converted PHPIDS signatures (https://svn.php-ids.org/svn/trunk/lib/IDS/default_filter.xml) * Updated PHPIDS rules logic to first search for payloads in ARGS and then if there is no match found then search more generically in request_body|request_uri_raw * Updated PHPIDS rules logic to only set TX variables and to not log. This allows for more clean exceptions in the 48 file which can then expire/delete false positive TX matches and adjust the anomaly scores. These rules will then inspect for any TX variables in phase:5 and create appropriate alerts for any variable matches that exist. Bug Fixes: * Added Anomaly Score check to the 60 correlation file to recheck the anomaly score at the end of phase:4 which would allow for blocking based on information leakage issues. == Version 2.0.3 - 11/05/2009 == Improvements: * Updated converted PHPIDS signatures (https://svn.php-ids.org/svn/trunk/lib/IDS/default_filter.xml) * Create a new PHPIDS Converter rules file (https://svn.php-ids.org/svn/trunk/lib/IDS/Converter.php) * Added new rules to identify multipart/form-data bypass attempts * Increased anomaly scoring (+100) for REQBODY_PROCESSOR_ERROR alerts Bug Fixes: * Added t:urlDecodeUni transformation function to phpids rules to fix both false positives/negatives https://www.modsecurity.org/tracker/browse/CORERULES-17 * Added new variable locations to the phpids filters https://www.modsecurity.org/tracker/browse/CORERULES-19 * Use of transformation functions can cause false negatives - added multiMatch action to phpids rules https://www.modsecurity.org/tracker/browse/CORERULES-20 * Fixed multipart parsing evasion issues by adding strict parsing rules https://www.modsecurity.org/tracker/browse/CORERULES-21 * Fixed typo in xss rules (missing |) https://www.modsecurity.org/tracker/browse/CORERULES-22 * Fixed regex text in IE8 XSS filters (changed to lowercase) https://www.modsecurity.org/tracker/browse/CORERULES-23 == Version 2.0.2 - 09/11/2009 == Improvements: * Added converted PHPIDS signatures (https://svn.php-ids.org/svn/trunk/lib/IDS/default_filter.xml) https://www.modsecurity.org/tracker/browse/CORERULES-13 Bug Fixes: * Rule 958297 - Fixed Comment SPAM UA false positive that triggered only on mozilla. https://www.modsecurity.org/tracker/browse/CORERULES-15 == Version 2.0.1 - 08/07/2009 == Improvements: * Updated the transformation functions used in the XSS/SQLi rules to improve performance https://www.modsecurity.org/tracker/browse/CORERULES-10 * Updated the variable/target list in the XSS rules https://www.modsecurity.org/tracker/browse/CORERULES-11 * Added XSS Filters from IE8 https://www.modsecurity.org/tracker/browse/CORERULES-12 Bug Fixes: * Rule 958297 - Fixed unescaped double-quote issue in Comment SPAM UA rule. https://www.modsecurity.org/tracker/browse/CORERULES-9 == Version 2.0.0 - 07/29/2009 == New Rules & Features: * Fine Grained Policy The rules have been split to having one signature per rule instead of having all signatures combined into one optimized regular expression. This should allow you to modify/disable events based on specific patterns instead of having to deal with the whole rule. * Converted Snort Rules Emerging Threat web attack rules have been converted. http://www.emergingthreats.net/ * Anomaly Scoring Mode Option The rules have been updated to include anomaly scoring variables which allow you to evaluate the score at the end of phase:2 and phase:5 and decide on what logging and disruptive actions to take based on the score. * Correlated Events There are rules in phase:5 that will provide some correlation between inbound events and outbound events and will provide a result of successful atttack or attempted attack. * Updated Severity Ratings The severity ratings in the rules have been updated to the following: - 0: Emergency - is generated from correlation where there is an inbound attack and an outbound leakage. - 1: Alert - is generated from correlation where there is an inbound attack and an outbound application level error. - 2: Critical - is the highest severity level possible without correlation. It is normally generated by the web attack rules (40 level files). - 3: Error - is generated mostly from outbound leakabe rules (50 level files). - 4: Warning - is generated by malicious client rules (35 level files). - 5: Notice - is generated by the Protocol policy and anomaly files. - 6: Info - is generated by the search engine clients (55 marketing file). * Updated Comment SPAM Protections Updated rules to include RBL lookups and client fingerprinting concepts from Bad Behavior (www.bad-behavior.ioerror.us) * Creation of Global Collection Automatically create a Global collection in the *10* config file. Other rules can then access it. * Use of Block Action Updated the rules to use the "block" action. This allows the Admin to globally set the desired block action once with SecDefaultAction in the *10* config file rather than having to edit the disruptive actions in all of the rules or for the need to have multiple versions of the rules (blocking vs. non-blocking). * "Possible HTTP Parameter Pollution Attack: Multiple Parameters with the same Name." http://tacticalwebappsec.blogspot.com/2009/05/http-parameter-pollution.html * Added new generic RFI detection rules. http://tacticalwebappsec.blogspot.com/2009/06/generic-remote-file-inclusion-attack.html * "Possibly malicious iframe tag in output" (Rules 981001,981002) Planting invisible iframes in a site can be used by attackers to point users from the victim site to their malicious site. This is actually as if the user was visiting the attacker's site himself, causing the user's browser to process the content in the attacker's site. New Events: * Rule 960019 - Expect Header Not Allowed. * Rule 960020 - Pragma Header Requires Cache-Control Header * Rule 958290 - Invalid Character in Request - Browsers should not send the (#) character as it is reserved for use as a fragment identifier within the html page. * Rule 958291 - Range: field exists and begins with 0. * Rule 958292 - Invalid Request Header Found. * Rule 958293 - Lowercase Via Request Header Found. * Rule 958294 - Common SPAM Proxies found in Via Request Header. * Rule 958295 - Multiple/Conflicting Connection Header Data Found. * Rule 958296 - Request Indicates a SPAM client accessed the Site. * Rule 958297 - Common SPAM/Email Harvester crawler. * Rule 958298 - Common SPAM/Email Harvester crawler Bug Fixes: * Rule 950107 - Split the rule into 2 separate rules to factor in the Content-Type when inspecting the REQUEST_BODY variable. * Rule 960017 - Bug fix for when having port in the host header. * Rule 960014 - Bug fix to correlate the SERVER_NAME variable. * Rule 950801 - Increased the logic so that the rule will only run if the web site uses UTF-8 Encoding. * Rules 999210,999211 - Bug fix to move ctl actions to last rule, add OPTIONS and allow the IPv6 loopback address * Rule 950117 - Updated the RFI logic to factor in both a trailing "?" in the ARG and to identify offsite hosts by comparing the ARG URI to the Host header. Due to this rule now being stronger, moved it from optional tight security rule to *40* generic attacks file. Other Fixes: * Added more HTTP Protocol violations to *20* file. * Set the SecDefaultAction in the *10* config file to log/pass (This was the default setting, however this sets it explicitly. * Added SecResponseBodyLimitAction ProcessPartial to the *10* config file. This was added so that when running the SecRuleEngine in DetectionOnly mode, it will not deny response bodies that go over the size restrictions. * Changed SecServerSignature to "Apache/1.3.28" * Fixed the use of SkipAfter and SecMarkers to make it consistent. Now have BEGIN and END SecMarkers for rule groups to more accurately allow moving to proper locations. * Fixed the @pm/@pmFromFile pre-qualifier logic to allow for operator inversion. This removes the need for some SecAction/SkipAfter rules. * Updated rule formatting to easily show rule containers (SecMarkers, pre-qualifier rules and chained rules). == Version 1.6.1 - 2008/04/22 == * Fixed a bug where phases and transformations where not specified explicitly in rules. The issue affected a significant number of rules, and we strongly recommend to upgrade. == Version 1.6.0 - 2008/02/19 == New Rulesets & Features: * 42 - Tight Security This ruleset contains currently 2 rules which are considered highly prone to FPs. They take care of Path Traversal attacks, and RFI attacks. This ruleset is included in the optional_rulesets dir * 42 - Comment Spam Comment Spam is used by the spammers to increase their rating in search engines by posting links to their site in other sites that allow posting of comments and messages. The rules in this ruleset will work against that. (Requires ModSecurity 2.5) * Tags A single type of attack is often detected by multiple rules. The new alert classification tags solve this issue by providing an alternative alert type indication and can serve for filtering and analysis of audit logs. The classification tags are hierarchical with slashes separating levels. Usually there are two levels with the top level describing the alert group and the lower level denoting the alert type itself, for example: WEB_ATTACK/SQL_INJECTION. False Positives Fixes: * Rule 960903 - Moved to phase 4 instead of 5 to avoid FPs * Rule 950107 - Will look for invalid url decoding in variables that are not automatically url decoded Additional rules logic: * Using the new "logdata" action for logging the matched signature in rules * When logging an event once, init the collection only if the alert needs to log * Using the new operator @pm as a qualifier before large rules to enhance performance (Requires ModSecurity 2.5) * SQL injection - A smarter regexp is used to detect 1=1,2=2,etc.. and not only 1=1. (Thanks to Marc Stern for the idea) * New XSS signatures - iframe & flash XSS == Version 1.5.1 - 2007/12/6 == False Positives Fixes: * Protocol Anomalies (file 21) - exception for Apache SSL pinger (Request: GET /) New Events: * 960019 - Detect HTTP/0.9 Requests HTTP/0.9 request are not common these days. This rule will log by default, and block in the blocking version of file 21 Other Fixes: * File 40, Rules 950004,950005 - Repaired the correction for the double url decoding problem * File 55 contained empty regular expressions. Fixed. == Version 1.5 - 2007/11/23 == New Rulesets: * 23 - Request Limits "Judging by appearances". This rulesets contains rules blocking based on the size of the request, for example, a request with too many arguments will be denied. Default policy changes: * XML protection off by default * BLOCKING dir renamed to optional_rules * Ruleset 55 (marketing) is now optional (added to the optional_rules dir) * Ruleset 21 - The exception for apache internal monitor will not log anymore New Events: * 960912 - Invalid request body Malformed content will not be parsed by modsecurity, but still there might be applications that will parse it, ignoring the errors. * 960913 - Invalid Request Will trigger a security event when request was rejected by apache with code 400, without going through ModSecurity rules. Additional rules logic: * 950001 - New signature: delete from * 950007 - New signature: waitfor delay False Positives Fixes: * 950006 - Will not be looking for /cc pattern in User-Agent header * 950002 - "Internet Explorer" signature removed * Double decoding bug used to cause FPs. Some of the parameters are already url-decoded by apache. This caused FPs when the rule performed another url-decoding transformation. The rules have been split so that parameters already decoded by apache will not be decoded by the rules anymore. * 960911 - Expression is much more permissive now * 950801 - Commented out entirely. NOTE: If your system uses UTF8 encoding, then you should uncomment this rule (in file 20) version 1.4.3 - 2007/07/21 New Events: * 950012 - HTTP Request Smuggling For more info on this attack: http://www.cgisecurity.com/lib/HTTP-Request-Smuggling.pdf * 960912 - Invalid request body Malformed content will not be parsed by modsecurity, but still there might be applications that will parse it, ignoring the errors. * 960913 - Invalid Request Will trigger a security event when request was rejected by apache with code 400, without going through ModSecurity rules. False Positives Fixes: * 950107 - Will allow a % sign in the middle of a string as well * 960911 - A more accurate expression based on the rfc: http://www.ietf.org/rfc/rfc2396.txt * 950015 - Will not look for http/ pattern in the request headers Additional rules logic: * Since Apache applies scope directives only after ModSecurity phase 1 this directives cannot be used to exclude phase 1 rules. Therefore we moved all inspection rules to phase 2. version 1.4 build 2 - 2007/05/17 New Feature: * Search for signatures in XML content XML Content will be parsed and ispected for signatures New Events: * 950116 - Unicode Full/Half Width Abuse Attack Attempt Full-width unicode can by used to bypass content inspection. Such encoding will be forbidden http://www.kb.cert.org/vuls/id/739224 * 960911 - Invalid HTTP request line Enforce request line to be valid, i.e.: * 960904 - Request Missing Content-Type (when there is content) When a request contains content, the content-type must be specified. If not, the content will not be inspected * 970018 - IIS installed in default location (any drive) Log once if IIS in installed in the /Inetpub directory (on any drive, not only C) * 950019 - Email Injection Web forms used for sending mail (such as "tell a friend") are often manipulated by spammers for sending anonymous emails Regular expressions fixes: * Further optimization of some regular expressions (using the non-greediness operator) The non-greediness operator, , prevents excessive backtracking FP fixes: * Rule 950107 - Will allow a parameter to end in a % sign from now on version 1.4 - 2007/05/02 New Events: * 970021 - WebLogic information disclosure Matching of "JSP compile error" in the response body, will trigger this rule, with severity 4 (Warning) * 950015,950910,950911 - HTTP Response Splitting Looking for HTTP Response Splitting patterns as described in Amit Klein's excellent white paper: http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf ModSecurity does not support compressed content at the moment. Thus, the following rules have been added: * 960902 - Content-Encoding in request not supported Any incoming compressed request will be denied * 960903 - Content-Encoding in response not suppoted An outgoing compressed response will be logged to alert, but ONLY ONCE. False Positives Fixes: * Removed <.exe>,<.shtml> from restricted extensions * Will not be looking for SQL Injection signatures , in the Via request header * Excluded Referer header from SQL injection, XSS and command injection rules * Excluded X-OS-Prefs header from command injection rule * Will be looking for command injection signatures in REQUEST_COOKIES|REQUEST_COOKIES_NAMES instead of REQUEST_HEADERS:Cookie. * Allowing charset specification in the Content-Type Additional rules logic: * Corrected match of OPTIONS method in event 960015 * Changed location for event 960014 (proxy access) to REQUEST_URI_RAW * Moved all rules apart from method inspection from phase 1 to phase 2 - This will enable viewing content if such a rule triggers as well as setting exceptions using Apache scope tags. * Added match for double quote in addition to single quote for signature (SQL Injection) * Added 1=1 signature (SQL Injection) version 1.3.2 build 4 2007/01/17 Fixed apache 2.4 dummy requests exclusion Added persistent PDF UXSS detection rule == Version 1.3.2 build 3 2007/01/10 == Fixed regular expression in rule 960010 (file #30) to allow multipart form data content == Version 1.3.2 - 2006/12/27 == New events: * 960037 Directory is restricted by policy * 960038 HTTP header is restricted by policy Regular expressions fixes: * Regular expressions with @ at end of beginning (for example "@import) * Regular expressions with un-escaped "." * Command Injections now always require certain characters both before and after the command. Important since many are common English words (finger, mail) * The command injection wget is not searched in the UA header as it has different meaning there. * LDAP Fixed to reduce FPs: + More accurate regular expressions + high bit characters not accpeted between signature tokens. * Do not detect Include modsecurity.d/owasp-modsecurity-crs/crs-setup.conf Include modsecurity.d/owasp-modsecurity-crs/rules/*.conf ``` 8. Restart web server and ensure it starts without errors 9. Make sure your web sites are still running fine. 10. Proceed to the section "Testing the Installation" below. Installing on Nginx ------------------- 1. Compile ModSecurity into Nginx 2. Ensure that ModSecurity is loading correctly by checking error.log at start up for lines indicating ModSecurity is installed. An example might appear as follows: ```ModSecurity for nginx (STABLE)/2.9.1 (http://www.modsecurity.org/) configured.``` 3. The most common method of deploying ModSecurity we have seen is to create a new folder underneath the Nginx directory (typically /usr/local/nginx/conf/). Often this folder is called 'owasp-modsecurity-crs'. Create this folder and cd into it. 4. Download our release from https://coreruleset.org/installation/ and unpack it into a new owasp-modsecurity-crs folder. 5. Move the crs-setup.conf.example file to crs-setup.conf. Please take this time to go through this file and customize the settings for your local environment. Failure to do so may result in false negatives and false positives. See the section entitled OWASP CRS Configuration for more detail. 6. Rename rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example and rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example to remove the '.example' extension. This will allow you to add exceptions without updates overwriting them in the future. 7. Nginx requires the configuration of a single ModSecurity configuration file within the nginx.conf file using the 'ModSecurityConfig' directive (when using ModSecurity 2.x). Best practice is to set 'ModSecurityConfig' to a file from which you will include your other ModSecurity configuration files. In this example we will use: ```ModSecurityConfig modsec_includes.conf;``` 7. Within modsec_includes.conf create your includes to the CRS folder similar to as follows (The modsecurity.conf file from the ModSecurity installation is included in this example): ``` include modsecurity.conf include owasp-modsecurity-crs/crs-setup.conf include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf include owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf include owasp-modsecurity-crs/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-JAVA.conf include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf ``` 8. Restart web server and ensure it starts without errors 9. Make sure your web sites are still running fine. 10. Proceed to the section "Testing the Installation" below. Installing on IIS ----------------- The IIS installer comes with an optional version of CRS built in. To upgrade or install this after the fact follow the following steps. 1. Navigate to "[drive_letters]:\Program Files\ModSecurity IIS\" 2. Download our release from https://coreruleset.org/installation/ and unpack it into the current folder. 3. Move the crs-setup.conf.example file to crs-setup.conf. Please take this time to go through this file and customize the settings for your local environment. Failure to do so may result in false negatives and false positives. See the section entitled OWASP CRS Configuration for more detail. 4. Rename rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example and rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example to remove the '.example' extension. This will allow you to add exceptions without updates overwriting them in the future. 5. Navigate back to the 'ModSecurity IIS' folder and modify the 'modsecurity_iis' to include the following: ``` include owasp-modsecurity-crs/crs-setup.conf include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf ``` 6. Restart web server and ensure it starts without errors 7. Make sure your web sites are still running fine. 8. Proceed to the section "Testing the Installation" below. Testing the Installation ======================== To test your installation you should be able to use any number of attacks. A typical request which should trigger CRS would be ```http://localhost/?param=">``` Upon sending this request you should see events reported in the error log (nginx apache) or the event viewer (IIS). If have not changed the defaults with regards to anomaly scoring, blocking and sampling percentage, then this request should have been blocked and access forbidden. Likewise if you have configured ModSecurity debug logging and/or audit logging this event should log to these locations as well. OWASP CRS Configuration ======================= The crs-setup.conf file includes management rules and directives that can control important CRS functions. The crs-setup.conf file comes with extensive comments. This section here brings only the essential parts. By default we do not include settings within the crs-setup.conf that configure ModSecurity itself. Instead those configuration settings are set during the installation of ModSecurity proper. An example for such such a configuration file is available via the ModSecurity project (https://github.com/SpiderLabs/ModSecurity/blob/master/modsecurity.conf-recommended). Be aware the crs-setup.conf file DOES specify configuration directives such as SecDefaultAction. The default is the anomaly scoring mode with the appropriate SecDefaultAction as defined in the crs-setup.conf. Alternative configuration modes are supported and explained in crs-setup.conf. The default anomaly/correlation mode establishes an incoming anomaly score threshold of 5 and an outgoing anomaly score threshold of 4. The default installation has been tuned to reduce false positives in a way that will allow most requests to pass in this default setup. However, testing the setup and tuning false positives before going to production is vital. This is especially true if you raise the paranoia level with is set to 1 by default. Higher paranoia levels ranging from 2 to 4 include more aggressive rules which will raise additional false positives but also raise the security level of your service. If you are unsure about the performance impact of the CRS or if you are unsure about the number of false positives, then you may want to use the sampling percentage. This number, which is set to 100 by default, controls the percentage of requests which is funneled into the CRS. Fresh installs on high traffic sites are advised to start with a low, or very low number of percentages and raise the number slowly up to 100. Be aware that any number below 100 allows a random number of requests to bypass the ruleset completely. Update the TX policy settings for allowed Request Methods, File Extensions, maximum numbers of arguments, etc to better reflect your environment that is being protected. Make sure your GeoIP and Project Honeypot settings are specified if you are using them. The GeoIP database is no longer included with the CRS. Instead you are advised to download it regularly. The use of Project Honeypot requires a free API key. These require an account but can be obtained at https://www.projecthoneypot.org/httpbl_configure.php. Be sure to check out the other settings present within the crs-setup.conf file. There are many other options that have to do with aspects of web application security that are beyond this document but are well explained in crs-setup.conf. modsecurity-crs-3.2.0/KNOWN_BUGS000066400000000000000000000054031355660542300163220ustar00rootroot00000000000000== OWASP ModSecurity Core Rule Set (CRS) KNOWN BUGS == == Report Bugs/Issues to GitHub Issues Tracker or the mailinglist == * https://github.com/SpiderLabs/owasp-modsecurity-crs/issues or the CRS mailinglist at * https://lists.owasp.org/mailman/listinfo/owasp-modsecurity-core-rule-set * There are still false positives for standard web applications in the default install (paranoia level 1). Please report these when you encounter them. False Positives from paranoia level 2 rules are less interesting, as we expect users to write exclusion rules for their alerts in the higher paranoia levels. * Permanent blocking of clients is based on a previous user agent / IP combination. Changing the user agent will thus allow to bypass this new filter. The plan is to allow for a purely IP based filter in the future. * Apache 2.4 prior to 2.4.11 is affected by a bug in parsing multi-line configuration directives, which causes Apache to fail during startup with an error such as: Error parsing actions: Unknown action: \\ Action 'configtest' failed. This bug is known to plague RHEL/Centos 7 below v7.4 or httpd v2.4.6 release 67 and Ubuntu 14.04 LTS users. https://bz.apache.org/bugzilla/show_bug.cgi?id=55910 We advise to upgrade your Apache version. If upgrading is not possible, we have provided a script in the util/join-multiline-rules directory which converts the rules into a format that works around the bug. You have to re-run this script whenever you modify or update the CRS rules. * Debian up to and including Jessie lacks YAJL/JSON support in ModSecurity, which causes the following error in the Apache ErrorLog or SecAuditLog: 'ModSecurity: JSON support was not enabled.' JSON support was enabled in Debian's package version 2.8.0-4 (Nov 2014). You can either use backports.debian.org to install the latest ModSecurity release or disable rule id 200001. * As of CRS version 3.0.1, support has been added for the application/soap+xml MIME type by default, as specified in RFC 3902. OF IMPORTANCE, application/soap+xml is indicative that XML will be provided. In accordance with this, ModSecurity's XML Request Body Processor should also be configured to support this MIME type. Within the ModSecurity project, commit 5e4e2af (https://github.com/SpiderLabs/ModSecurity/commit/5e4e2af7a6f07854fee6ed36ef4a381d4e03960e) has been merged to support this endevour. However, if you are running a modified or preexisting version of the modsecurity.conf provided by this repository, you may wish to upgrade rule '200000' accordingly. The rule now appears as follows: ``` SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \ "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" ``` modsecurity-crs-3.2.0/LICENSE000066400000000000000000000261461355660542300156770ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2006 the OWASP Core Rule Set contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. modsecurity-crs-3.2.0/README.md000066400000000000000000000044001355660542300161360ustar00rootroot00000000000000![Travis build v3.2/dev](https://badges.herokuapp.com/travis/SpiderLabs/owasp-modsecurity-crs?branch=v3.2/dev&label=CRS%20v3.2/dev)![Travis build v3.1/dev](https://badges.herokuapp.com/travis/SpiderLabs/owasp-modsecurity-crs?branch=v3.1/dev&label=CRS%20v3.1/dev)![Travis build v3.0/dev](https://badges.herokuapp.com/travis/SpiderLabs/owasp-modsecurity-crs?branch=v3.0/dev&label=CRS%20v3.0/dev) [![OWASP Flagship](https://img.shields.io/badge/owasp-flagship%20project-38a047.svg)](https://www.owasp.org/index.php/OWASP_Project_Inventory#tab=Flagship_Projects) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1390/badge)](https://bestpractices.coreinfrastructure.org/projects/1390) # OWASP ModSecurity Core Rule Set (CRS) The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. The CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts. ## CRS Resources Please see the [OWASP ModSecurity Core Rule Set page](https://coreruleset.org/) to get introduced to the CRS and view resources on installation, configuration, and working with the CRS. ## Contributing to the CRS We strive to make the OWASP ModSecurity CRS accessible to a wide audience of beginner and experienced users. We are interested in hearing any bug reports, false positive alert reports, evasions, usability issues, and suggestions for new detections. [Create an issue on GitHub](https://github.com/SpiderLabs/owasp-modsecurity-crs/issues) to report a false positive or false negative (evasion). Please include your installed version and the relevant portions of your ModSecurity audit log. [Sign up for the mailing list](https://lists.owasp.org/mailman/listinfo/owasp-modsecurity-core-rule-set) to ask general usage questions and participate in discussions on the CRS. [Join the #modsecurity channel on Freenode IRC](https://webchat.freenode.net/?channels=%23modsecurity) to chat about the CRS. ## License Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. The OWASP ModSecurity Core Rule Set is distributed under Apache Software License (ASL) version 2. Please see the enclosed LICENSE file for full details. modsecurity-crs-3.2.0/crs-setup.conf.example000066400000000000000000000753641355660542300211260ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -- [[ Introduction ]] -------------------------------------------------------- # # The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack # detection rules that provide a base level of protection for any web # application. They are written for the open source, cross-platform # ModSecurity Web Application Firewall. # # See also: # https://coreruleset.org/ # https://github.com/SpiderLabs/owasp-modsecurity-crs # https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project # # # -- [[ System Requirements ]] ------------------------------------------------- # # CRS requires ModSecurity version 2.8.0 or above. # We recommend to always use the newest ModSecurity version. # # The configuration directives/settings in this file are used to control # the OWASP ModSecurity CRS. These settings do **NOT** configure the main # ModSecurity settings (modsecurity.conf) such as SecRuleEngine, # SecRequestBodyAccess, SecAuditEngine, SecDebugLog, and XML processing. # # The CRS assumes that modsecurity.conf has been loaded. It is bundled with # ModSecurity. If you don't have it, you can get it from: # 2.x: https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v2/master/modsecurity.conf-recommended # 3.x: https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended # # The order of file inclusion in your webserver configuration should always be: # 1. modsecurity.conf # 2. crs-setup.conf (this file) # 3. rules/*.conf (the CRS rule files) # # Please refer to the INSTALL file for detailed installation instructions. # # # -- [[ Mode of Operation: Anomaly Scoring vs. Self-Contained ]] --------------- # # The CRS can run in two modes: # # -- [[ Anomaly Scoring Mode (default) ]] -- # In CRS3, anomaly mode is the default and recommended mode, since it gives the # most accurate log information and offers the most flexibility in setting your # blocking policies. It is also called "collaborative detection mode". # In this mode, each matching rule increases an 'anomaly score'. # At the conclusion of the inbound rules, and again at the conclusion of the # outbound rules, the anomaly score is checked, and the blocking evaluation # rules apply a disruptive action, by default returning an error 403. # # -- [[ Self-Contained Mode ]] -- # In this mode, rules apply an action instantly. This was the CRS2 default. # It can lower resource usage, at the cost of less flexibility in blocking policy # and less informative audit logs (only the first detected threat is logged). # Rules inherit the disruptive action that you specify (i.e. deny, drop, etc). # The first rule that matches will execute this action. In most cases this will # cause evaluation to stop after the first rule has matched, similar to how many # IDSs function. # # -- [[ Alert Logging Control ]] -- # In the mode configuration, you must also adjust the desired logging options. # There are three common options for dealing with logging. By default CRS enables # logging to the webserver error log (or Event viewer) plus detailed logging to # the ModSecurity audit log (configured under SecAuditLog in modsecurity.conf). # # - To log to both error log and ModSecurity audit log file, use: "log,auditlog" # - To log *only* to the ModSecurity audit log file, use: "nolog,auditlog" # - To log *only* to the error log file, use: "log,noauditlog" # # Examples for the various modes follow. # You must leave one of the following options enabled. # Note that you must specify the same line for phase:1 and phase:2. # # Default: Anomaly Scoring mode, log to error log, log to ModSecurity audit log # - By default, offending requests are blocked with an error 403 response. # - To change the disruptive action, see RESPONSE-999-EXCEPTIONS.conf.example # and review section 'Changing the Disruptive Action for Anomaly Mode'. # - In Apache, you can use ErrorDocument to show a friendly error page or # perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html # SecDefaultAction "phase:1,log,auditlog,pass" SecDefaultAction "phase:2,log,auditlog,pass" # Example: Anomaly Scoring mode, log only to ModSecurity audit log # - By default, offending requests are blocked with an error 403 response. # - To change the disruptive action, see RESPONSE-999-EXCEPTIONS.conf.example # and review section 'Changing the Disruptive Action for Anomaly Mode'. # - In Apache, you can use ErrorDocument to show a friendly error page or # perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html # # SecDefaultAction "phase:1,nolog,auditlog,pass" # SecDefaultAction "phase:2,nolog,auditlog,pass" # Example: Self-contained mode, return error 403 on blocking # - In this configuration the default disruptive action becomes 'deny'. After a # rule triggers, it will stop processing the request and return an error 403. # - You can also use a different error status, such as 404, 406, et cetera. # - In Apache, you can use ErrorDocument to show a friendly error page or # perform a redirect: https://httpd.apache.org/docs/2.4/custom-error.html # # SecDefaultAction "phase:1,log,auditlog,deny,status:403" # SecDefaultAction "phase:2,log,auditlog,deny,status:403" # Example: Self-contained mode, redirect back to homepage on blocking # - In this configuration the 'tag' action includes the Host header data in the # log. This helps to identify which virtual host triggered the rule (if any). # - Note that this might cause redirect loops in some situations; for example # if a Cookie or User-Agent header is blocked, it will also be blocked when # the client subsequently tries to access the homepage. You can also redirect # to another custom URL. # SecDefaultAction "phase:1,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" # SecDefaultAction "phase:2,log,auditlog,redirect:'http://%{request_headers.host}/',tag:'Host: %{request_headers.host}'" # # -- [[ Paranoia Level Initialization ]] --------------------------------------- # # The Paranoia Level (PL) setting allows you to choose the desired level # of rule checks that will add to your anomaly scores. # # With each paranoia level increase, the CRS enables additional rules # giving you a higher level of security. However, higher paranoia levels # also increase the possibility of blocking some legitimate traffic due to # false alarms (also named false positives or FPs). If you use higher # paranoia levels, it is likely that you will need to add some exclusion # rules for certain requests and applications receiving complex input. # # - A paranoia level of 1 is default. In this level, most core rules # are enabled. PL1 is advised for beginners, installations # covering many different sites and applications, and for setups # with standard security requirements. # At PL1 you should face FPs rarely. If you encounter FPs, please # open an issue on the CRS GitHub site and don't forget to attach your # complete Audit Log record for the request with the issue. # - Paranoia level 2 includes many extra rules, for instance enabling # many regexp-based SQL and XSS injection protections, and adding # extra keywords checked for code injections. PL2 is advised # for moderate to experienced users desiring more complete coverage # and for installations with elevated security requirements. # PL2 comes with some FPs which you need to handle. # - Paranoia level 3 enables more rules and keyword lists, and tweaks # limits on special characters used. PL3 is aimed at users experienced # at the handling of FPs and at installations with a high security # requirement. # - Paranoia level 4 further restricts special characters. # The highest level is advised for experienced users protecting # installations with very high security requirements. Running PL4 will # likely produce a very high number of FPs which have to be # treated before the site can go productive. # # Rules in paranoia level 2 or higher will log their PL to the audit log; # example: [tag "paranoia-level/2"]. This allows you to deduct from the # audit log how the WAF behavior is affected by paranoia level. # # It is important to also look into the variable # tx.enforce_bodyproc_urlencoded (Enforce Body Processor URLENCODED) # defined below. Enabling it closes a possible bypass of CRS. # # Uncomment this rule to change the default: # #SecAction \ # "id:900000,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.paranoia_level=1" # It is possible to execute rules from a higher paranoia level but not include # them in the anomaly scoring. This allows you to take a well-tuned system on # paranoia level 1 and add rules from paranoia level 2 without having to fear # the new rules would lead to false positives that raise your score above the # threshold. # This optional feature is enabled by uncommenting the following rule and # setting the tx.executing_paranoia_level. # Technically, rules up to the level defined in tx.executing_paranoia_level # will be executed, but only the rules up to tx.paranoia_level affect the # anomaly scores. # By default, tx.executing_paranoia_level is set to tx.paranoia_level. # tx.executing_paranoia_level must not be lower than tx.paranoia_level. # # Please notice that setting tx.executing_paranoia_level to a higher paranoia # level results in a performance impact that is equally high as setting # tx.paranoia_level to said level. # #SecAction \ # "id:900001,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.executing_paranoia_level=1" # # -- [[ Enforce Body Processor URLENCODED ]] ----------------------------------- # # ModSecurity selects the body processor based on the Content-Type request # header. But clients are not always setting the Content-Type header for their # request body payloads. This will leave ModSecurity with limited vision into # the payload. The variable tx.enforce_bodyproc_urlencoded lets you force the # URLENCODED body processor in these situations. This is off by default, as it # implies a change of the behaviour of ModSecurity beyond CRS (the body # processor applies to all rules, not only CRS) and because it may lead to # false positives already on paranoia level 1. However, enabling this variable # closes a possible bypass of CRS so it should be considered. # # Uncomment this rule to change the default: # #SecAction \ # "id:900010,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.enforce_bodyproc_urlencoded=1" # # -- [[ Anomaly Mode Severity Levels ]] ---------------------------------------- # # Each rule in the CRS has an associated severity level. # These are the default scoring points for each severity level. # These settings will be used to increment the anomaly score if a rule matches. # You may adjust these points to your liking, but this is usually not needed. # # - CRITICAL severity: Anomaly Score of 5. # Mostly generated by the application attack rules (93x and 94x files). # - ERROR severity: Anomaly Score of 4. # Generated mostly from outbound leakage rules (95x files). # - WARNING severity: Anomaly Score of 3. # Generated mostly by malicious client rules (91x files). # - NOTICE severity: Anomaly Score of 2. # Generated mostly by the protocol rules (92x files). # # In anomaly mode, these scores are cumulative. # So it's possible for a request to hit multiple rules. # # (Note: In this file, we use 'phase:1' to set CRS configuration variables. # In general, 'phase:request' is used. However, we want to make absolutely sure # that all configuration variables are set before the CRS rules are processed.) # #SecAction \ # "id:900100,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.critical_anomaly_score=5,\ # setvar:tx.error_anomaly_score=4,\ # setvar:tx.warning_anomaly_score=3,\ # setvar:tx.notice_anomaly_score=2" # # -- [[ Anomaly Mode Blocking Threshold Levels ]] ------------------------------ # # Here, you can specify at which cumulative anomaly score an inbound request, # or outbound response, gets blocked. # # Most detected inbound threats will give a critical score of 5. # Smaller violations, like violations of protocol/standards, carry lower scores. # # [ At default value ] # If you keep the blocking thresholds at the defaults, the CRS will work # similarly to previous CRS versions: a single critical rule match will cause # the request to be blocked and logged. # # [ Using higher values ] # If you want to make the CRS less sensitive, you can increase the blocking # thresholds, for instance to 7 (which would require multiple rule matches # before blocking) or 10 (which would require at least two critical alerts - or # a combination of many lesser alerts), or even higher. However, increasing the # thresholds might cause some attacks to bypass the CRS rules or your policies. # # [ New deployment strategy: Starting high and decreasing ] # It is a common practice to start a fresh CRS installation with elevated # anomaly scoring thresholds (>100) and then lower the limits as your # confidence in the setup grows. You may also look into the Sampling # Percentage section below for a different strategy to ease into a new # CRS installation. # # [ Anomaly Threshold / Paranoia Level Quadrant ] # # High Anomaly Limit | High Anomaly Limit # Low Paranoia Level | High Paranoia Level # -> Fresh Site | -> Experimental Site # ------------------------------------------------------ # Low Anomaly Limit | Low Anomaly Limit # Low Paranoia Level | High Paranoia Level # -> Standard Site | -> High Security Site # # Uncomment this rule to change the defaults: # #SecAction \ # "id:900110,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.inbound_anomaly_score_threshold=5,\ # setvar:tx.outbound_anomaly_score_threshold=4" # # -- [[ Application Specific Rule Exclusions ]] ---------------------------------------- # # Some well-known applications may undertake actions that appear to be # malicious. This includes actions such as allowing HTML or Javascript within # parameters. In such cases the CRS aims to prevent false positives by allowing # administrators to enable prebuilt, application specific exclusions on an # application by application basis. # These application specific exclusions are distinct from the rules that would # be placed in the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS configuration file as # they are prebuilt for specific applications. The 'REQUEST-900' file is # designed for users to add their own custom exclusions. Note, using these # application specific exclusions may loosen restrictions of the CRS, # especially if used with an application they weren't designed for. As a result # they should be applied with care. # To use this functionality you must specify a supported application. To do so # uncomment rule 900130. In addition to uncommenting the rule you will need to # specify which application(s) you'd like to enable exclusions for. Only a # (very) limited set of applications are currently supported, please use the # filenames prefixed with 'REQUEST-903' to guide you in your selection. # Such filenames use the following convention: # REQUEST-903.9XXX-{APPNAME}-EXCLUSIONS-RULES.conf # # It is recommended if you run multiple web applications on your site to limit # the effects of the exclusion to only the path where the excluded webapp # resides using a rule similar to the following example: # SecRule REQUEST_URI "@beginsWith /wordpress/" setvar:tx.crs_exclusions_wordpress=1 # # Modify and uncomment this rule to select which application: # #SecAction \ # "id:900130,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.crs_exclusions_cpanel=1,\ # setvar:tx.crs_exclusions_drupal=1,\ # setvar:tx.crs_exclusions_dokuwiki=1,\ # setvar:tx.crs_exclusions_nextcloud=1,\ # setvar:tx.crs_exclusions_wordpress=1,\ # setvar:tx.crs_exclusions_xenforo=1" # # -- [[ HTTP Policy Settings ]] ------------------------------------------------ # # This section defines your policies for the HTTP protocol, such as: # - allowed HTTP versions, HTTP methods, allowed request Content-Types # - forbidden file extensions (e.g. .bak, .sql) and request headers (e.g. Proxy) # # These variables are used in the following rule files: # - REQUEST-911-METHOD-ENFORCEMENT.conf # - REQUEST-912-DOS-PROTECTION.conf # - REQUEST-920-PROTOCOL-ENFORCEMENT.conf # HTTP methods that a client is allowed to use. # Default: GET HEAD POST OPTIONS # Example: for RESTful APIs, add the following methods: PUT PATCH DELETE # Example: for WebDAV, add the following methods: CHECKOUT COPY DELETE LOCK # MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK # Uncomment this rule to change the default. #SecAction \ # "id:900200,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" # Content-Types that a client is allowed to send in a request. # Default: application/x-www-form-urlencoded|multipart/form-data|text/xml|\ # application/xml|application/soap+xml|application/x-amf|application/json|\ # application/octet-stream|application/csp-report|\ # application/xss-auditor-report|text/plain # Uncomment this rule to change the default. #SecAction \ # "id:900220,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/soap+xml|application/x-amf|application/json|application/octet-stream|application/csp-report|application/xss-auditor-report|text/plain'" # Allowed HTTP versions. # Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 # Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 # Note that some web server versions use 'HTTP/2', some 'HTTP/2.0', so # we include both version strings by default. # Uncomment this rule to change the default. #SecAction \ # "id:900230,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'" # Forbidden file extensions. # Guards against unintended exposure of development/configuration files. # Default: .asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/ # Example: .bak/ .config/ .conf/ .db/ .ini/ .log/ .old/ .pass/ .pdb/ .rdb/ .sql/ # Uncomment this rule to change the default. #SecAction \ # "id:900240,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" # Forbidden request headers. # Header names should be lowercase, enclosed by /slashes/ as delimiters. # Blocking Proxy header prevents 'httpoxy' vulnerability: https://httpoxy.org # Default: /proxy/ /lock-token/ /content-range/ /translate/ /if/ # Uncomment this rule to change the default. #SecAction \ # "id:900250,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.restricted_headers=/proxy/ /lock-token/ /content-range/ /translate/ /if/'" # File extensions considered static files. # Extensions include the dot, lowercase, enclosed by /slashes/ as delimiters. # Used in DoS protection rule. See section "Anti-Automation / DoS Protection". # Default: /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/ # Uncomment this rule to change the default. #SecAction \ # "id:900260,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'" # Content-Types charsets that a client is allowed to send in a request. # Default: utf-8|iso-8859-1|iso-8859-15|windows-1252 # Uncomment this rule to change the default. # Use "|" to separate multiple charsets like in the rule defining # tx.allowed_request_content_type. #SecAction \ # "id:900280,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" # # -- [[ HTTP Argument/Upload Limits ]] ----------------------------------------- # # Here you can define optional limits on HTTP get/post parameters and uploads. # This can help to prevent application specific DoS attacks. # # These values are checked in REQUEST-920-PROTOCOL-ENFORCEMENT.conf. # Beware of blocking legitimate traffic when enabling these limits. # # Block request if number of arguments is too high # Default: unlimited # Example: 255 # Uncomment this rule to set a limit. #SecAction \ # "id:900300,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.max_num_args=255" # Block request if the length of any argument name is too high # Default: unlimited # Example: 100 # Uncomment this rule to set a limit. #SecAction \ # "id:900310,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.arg_name_length=100" # Block request if the length of any argument value is too high # Default: unlimited # Example: 400 # Uncomment this rule to set a limit. #SecAction \ # "id:900320,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.arg_length=400" # Block request if the total length of all combined arguments is too high # Default: unlimited # Example: 64000 # Uncomment this rule to set a limit. #SecAction \ # "id:900330,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.total_arg_length=64000" # Block request if the file size of any individual uploaded file is too high # Default: unlimited # Example: 1048576 # Uncomment this rule to set a limit. #SecAction \ # "id:900340,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.max_file_size=1048576" # Block request if the total size of all combined uploaded files is too high # Default: unlimited # Example: 1048576 # Uncomment this rule to set a limit. #SecAction \ # "id:900350,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.combined_file_sizes=1048576" # # -- [[ Easing In / Sampling Percentage ]] ------------------------------------- # # Adding the Core Rule Set to an existing productive site can lead to false # positives, unexpected performance issues and other undesired side effects. # # It can be beneficial to test the water first by enabling the CRS for a # limited number of requests only and then, when you have solved the issues (if # any) and you have confidence in the setup, to raise the ratio of requests # being sent into the ruleset. # # Adjust the percentage of requests that are funnelled into the Core Rules by # setting TX.sampling_percentage below. The default is 100, meaning that every # request gets checked by the CRS. The selection of requests, which are going # to be checked, is based on a pseudo random number generated by ModSecurity. # # If a request is allowed to pass without being checked by the CRS, there is no # entry in the audit log (for performance reasons), but an error log entry is # written. If you want to disable the error log entry, then issue the # following directive somewhere after the inclusion of the CRS # (E.g., RESPONSE-999-EXCEPTIONS.conf). # # SecRuleUpdateActionById 901150 "nolog" # # ATTENTION: If this TX.sampling_percentage is below 100, then some of the # requests will bypass the Core Rules completely and you lose the ability to # protect your service with ModSecurity. # # Uncomment this rule to enable this feature: # #SecAction "id:900400,\ # phase:1,\ # pass,\ # nolog,\ # setvar:tx.sampling_percentage=100" # # -- [[ Project Honey Pot HTTP Blacklist ]] ------------------------------------ # # Optionally, you can check the client IP address against the Project Honey Pot # HTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a # free API key. Set it here with SecHttpBlKey. # # Project Honeypot returns multiple different malicious IP types. # You may specify which you want to block by enabling or disabling them below. # # Ref: https://www.projecthoneypot.org/httpbl.php # Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey # # Uncomment these rules to use this feature: # #SecHttpBlKey XXXXXXXXXXXXXXXXX #SecAction "id:900500,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.block_search_ip=1,\ # setvar:tx.block_suspicious_ip=1,\ # setvar:tx.block_harvester_ip=1,\ # setvar:tx.block_spammer_ip=1" # # -- [[ GeoIP Database ]] ------------------------------------------------------ # # There are some rulesets that inspect geolocation data of the client IP address # (geoLookup). The CRS uses geoLookup to implement optional country blocking. # # To use geolocation, we make use of the MaxMind GeoIP database. # This database is not included with the CRS and must be downloaded. # You should also update the database regularly, for instance every month. # The CRS contains a tool to download it to util/geo-location/GeoIP.dat: # util/upgrade.py --geoip # # This product includes GeoLite data created by MaxMind, available from: # http://www.maxmind.com. # # Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html # Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html # # Uncomment this rule to use this feature: # #SecGeoLookupDB util/geo-location/GeoIP.dat # # -=[ Block Countries ]=- # # Rules in the IP Reputation file can check the client against a list of high # risk country codes. These countries have to be defined in the variable # tx.high_risk_country_codes via their ISO 3166 two-letter country code: # https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements # # If you are sure that you are not getting any legitimate requests from a given # country, then you can disable all access from that country via this variable. # The rule performing the test has the rule id 910100. # # This rule requires SecGeoLookupDB to be enabled and the GeoIP database to be # downloaded (see the section "GeoIP Database" above.) # # By default, the list is empty. A list used by some sites was the following: # setvar:'tx.high_risk_country_codes=UA ID YU LT EG RO BG TR RU PK MY CN'" # # Uncomment this rule to use this feature: # #SecAction \ # "id:900600,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.high_risk_country_codes='" # # -- [[ Anti-Automation / DoS Protection ]] ------------------------------------ # # Optional DoS protection against clients making requests too quickly. # # When a client is making more than 100 requests (excluding static files) within # 60 seconds, this is considered a 'burst'. After two bursts, the client is # blocked for 600 seconds. # # Requests to static files are not counted towards DoS; they are listed in the # 'tx.static_extensions' setting, which you can change in this file (see # section "HTTP Policy Settings"). # # For a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf. # # Uncomment this rule to use this feature: # #SecAction \ # "id:900700,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:'tx.dos_burst_time_slice=60',\ # setvar:'tx.dos_counter_threshold=100',\ # setvar:'tx.dos_block_timeout=600'" # # -- [[ Check UTF-8 encoding ]] ------------------------------------------------ # # The CRS can optionally check request contents for invalid UTF-8 encoding. # We only want to apply this check if UTF-8 encoding is actually used by the # site; otherwise it will result in false positives. # # Uncomment this rule to use this feature: # #SecAction \ # "id:900950,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.crs_validate_utf8_encoding=1" # # -- [[ Blocking Based on IP Reputation ]] ------------------------------------ # # Blocking based on reputation is permanent in the CRS. Unlike other rules, # which look at the indvidual request, the blocking of IPs is based on # a persistent record in the IP collection, which remains active for a # certain amount of time. # # There are two ways an individual client can become flagged for blocking: # - External information (RBL, GeoIP, etc.) # - Internal information (Core Rules) # # The record in the IP collection carries a flag, which tags requests from # individual clients with a flag named IP.reput_block_flag. # But the flag alone is not enough to have a client blocked. There is also # a global switch named tx.do_reput_block. This is off by default. If you set # it to 1 (=On), requests from clients with the IP.reput_block_flag will # be blocked for a certain duration. # # Variables # ip.reput_block_flag Blocking flag for the IP collection record # ip.reput_block_reason Reason (= rule message) that caused to blocking flag # tx.do_reput_block Switch deciding if we really block based on flag # tx.reput_block_duration Setting to define the duration of a block # # It may be important to know, that all the other core rules are skipped for # requests, when it is clear that they carry the blocking flag in question. # # Uncomment this rule to use this feature: # #SecAction \ # "id:900960,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.do_reput_block=1" # # Uncomment this rule to change the blocking time: # Default: 300 (5 minutes) # #SecAction \ # "id:900970,\ # phase:1,\ # nolog,\ # pass,\ # t:none,\ # setvar:tx.reput_block_duration=300" # # -- [[ Collection timeout ]] -------------------------------------------------- # # Set the SecCollectionTimeout directive from the ModSecurity default (1 hour) # to a lower setting which is appropriate to most sites. # This increases performance by cleaning out stale collection (block) entries. # # This value should be greater than or equal to: # tx.reput_block_duration (see section "Blocking Based on IP Reputation") and # tx.dos_block_timeout (see section "Anti-Automation / DoS Protection"). # # Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecCollectionTimeout # Please keep this directive uncommented. # Default: 600 (10 minutes) SecCollectionTimeout 600 # # -- [[ End of setup ]] -------------------------------------------------------- # # The CRS checks the tx.crs_setup_version variable to ensure that the setup # has been loaded. If you are not planning to use this setup template, # you must manually set the tx.crs_setup_version variable before including # the CRS rules/* files. # # The variable is a numerical representation of the CRS version number. # E.g., v3.0.0 is represented as 300. # SecAction \ "id:900990,\ phase:1,\ nolog,\ pass,\ t:none,\ setvar:tx.crs_setup_version=320" modsecurity-crs-3.2.0/documentation/000077500000000000000000000000001355660542300175325ustar00rootroot00000000000000modsecurity-crs-3.2.0/documentation/README000066400000000000000000000011311355660542300204060ustar00rootroot00000000000000Welcome to the OWASP Core Rule Set (CRS) documentation. The OWASP CRS documentation is generated as a Sphinx project and is stored in a separate Github repository. While the documentation is available as part of the CRS project it is provided in the form of a git-submodule. Using a git-submodule allow us to update the documentation without making changes to the main rule repository. You can download the documentation using git: $ git submodule init $ git submodule update Alternatively, the latest version of the documentation is available at https://www.modsecurity.org/CRS/Documentation/modsecurity-crs-3.2.0/rules/000077500000000000000000000000001355660542300160135ustar00rootroot00000000000000modsecurity-crs-3.2.0/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example000066400000000000000000000166441355660542300256110ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # The purpose of this file is to hold LOCAL exceptions for your site. The # types of rules that would go into this file are one where you want to # short-circuit inspection and allow certain transactions to pass through # inspection or if you want to alter rules that are applied. # # This file is named REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example for a # very specific reason. Files affixed with the .example extension are designed # to contain user created/modified data. The '.example'. extension should be # renamed to end in .conf. The advantage of this is that when OWASP CRS is # updated, the updates will not overwrite a user generated configuration file. # # As a result of this design paradigm users are encouraged NOT to directly # modify rules. Instead they should use this # REQUEST-900-EXCLUSION-RULES-BEFORE-CRS and the # RESPONSE-999-EXCLUSION-RULES-AFTER-CRS file to modify OWASP rules using # methods similar to the examples specified below. # # REQUEST-900-EXCLUSION-RULES-BEFORE-CRS and # RESPONSE-999-EXCLUSION-RULES-AFTER-CRS serve different purposes. ModSecurity # effectively maintains two different context: startup, and per transaction. # As a rule, directives are processed within the startup context. While they # can affect the per transaction context they generally remain fixed during the # execution of ModSecurity. # # As a result if one wanted to disable a rule at bootup the SecRuleRemoveById # directive or one of its siblings would have to be placed AFTER the rule is # listed, otherwise it will not have knowledge of the rules existence (since # these rules are read in at the same time). This means that when using # directives that effect SecRules, these exceptions should be placed AFTER all # the existing rules. This is why RESPONSE-999-EXCLUSION-RULES-AFTER-CRS is # designed such that it loads LAST. # # Conversely, ModSecurity supports several actions that can change the state of # the underlying configuration during the per transaction context, this is when # rules are being processed. Generally, these are accomplished by using the # 'ctl' action. As these are part of a rule, they will be evaluated in the # order rules are applied (by physical location, considering phases). As a # result of this ordering a 'ctl' action should be placed with consideration to # when it will be executed. This is particularly relevant for the 'ctl' options # that involve modifying ID's (such as ruleRemoveById). In these cases it is # important that such rules are placed BEFORE the rule ID they will affect. # Unlike the setup context, by the time we process rules in the per-transaction # context, we are already aware of all the rule ID's. It is by this logic that # we include rules such as this BEFORE all the remaining rules. As a result # REQUEST-900-EXCLUSION-RULES-BEFORE-CRS is designed to load FIRST. # # As a general rule: # ctl:ruleEngine -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveTargetById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveTargetByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # ctl:ruleRemoveTargetByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS # # SecRuleRemoveById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleRemoveByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleRemoveByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleUpdateActionById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleUpdateTargetById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleUpdateTargetByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # SecRuleUpdateTargetByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS # # # What follows are a group of examples that show you how to perform rule # exclusions. # # # Example Exclusion Rule: Disable inspection for an authorized client # # This ruleset allows you to control how ModSecurity will handle traffic # originating from Authorized Vulnerability Scanning (AVS) sources. See # related blog post - # http://blog.spiderlabs.com/2010/12/advanced-topic-of-the-week-handling-authorized-scanning-traffic.html # # White-list ASV network block (no blocking or logging of AVS traffic) Update # IP network block as appropriate for your AVS traffic # # ModSec Rule Exclusion: Disable Rule Engine for known ASV IP # SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" \ # "id:1000,\ # phase:1,\ # pass,\ # nolog,\ # ctl:ruleEngine=Off" # # # Example Exclusion Rule: Removing a specific ARGS parameter from inspection # for an individual rule # # This rule shows how to conditionally exclude the "password" # parameter for rule 942100 when the REQUEST_URI is /index.php # ModSecurity Rule Exclusion: 942100 SQL Injection Detected via libinjection # # SecRule REQUEST_URI "@beginsWith /index.php" \ # "id:1001,\ # phase:1,\ # pass,\ # nolog,\ # ctl:ruleRemoveTargetById=942100;ARGS:password" # # # Example Exclusion Rule: Removing a specific ARGS parameter from inspection # for only certain attacks # # Attack rules within the CRS are tagged, with tags such as 'attack-lfi', # 'attack-sqli', 'attack-xss', 'attack-injection-php', et cetera. # # ModSecurity Rule Exclusion: Disable inspection of ARGS:pwd # for all rules tagged attack-sqli # SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ # "id:1002,\ # phase:2,\ # pass,\ # nolog,\ # ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:pwd" # # Example Exclusion Rule: Removing a specific ARGS parameter from inspection # for all CRS rules # # This rule illustrates that we can use tagging very effectively to whitelist a # common false positive across an entire ModSecurity instance. This can be done # because every rule in OWASP_CRS is tagged with OWASP_CRS. This will NOT # affect custom rules. # # ModSecurity Rule Exclusion: Disable inspection of ARGS:pwd # for all CRS rules # SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ # "id:1003,\ # phase:2,\ # pass,\ # nolog,\ # ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd" # # Example Exclusion Rule: Removing a range of rules # # This rule illustrates that we can remove a rule range via a ctl action. # This uses the fact, that rules are grouped by topic in rule files covering # a certain id range. # # ModSecurity Rule Exclusion: Disable all SQLi and XSS rules # SecRule REQUEST_FILENAME "@beginsWith /admin" \ # "id:1004,\ # phase:2,\ # pass,\ # nolog,\ # ctl:ruleRemoveById=941000-942999" # # # The application specific rule exclusion files # REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf # REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf # bring additional examples which can be useful then tuning a service. modsecurity-crs-3.2.0/rules/REQUEST-901-INITIALIZATION.conf000066400000000000000000000304441355660542300224530ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # This file REQUEST-901-INITIALIZATION.conf initializes the Core Rules # and performs preparatory actions. It also fixes errors and omissions # of variable definitions in the file crs-setup.conf. # The setup.conf can and should be edited by the user, this file # is part of the CRS installation and should not be altered. # # # -=[ Rules Version ]=- # # Rule version data is added to the "Producer" line of Section H of the Audit log: # # - Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/); OWASP_CRS/3.1.0. # # Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecComponentSignature # SecComponentSignature "OWASP_CRS/3.2.0" # # -=[ Default setup values ]=- # # The CRS checks the tx.crs_setup_version variable to ensure that the setup # file is included at the correct time. This detects situations where # necessary settings are not defined, for instance if the file # inclusion order is incorrect, or if the user has forgotten to # include the crs-setup.conf file. # # If you are upgrading from an earlier version of the CRS and you are # getting this error, please make a new copy of the setup template # crs-setup.conf.example to crs-setup.conf, and re-apply your policy # changes. There have been many changes in settings syntax from CRS2 # to CRS3, so an old setup file may cause unwanted behavior. # # If you are not planning to use the crs-setup.conf template, you must # manually set the tx.crs_setup_version variable before including # the CRS rules/* files. # # The variable is a numerical representation of the CRS version number. # E.g., v3.0.0 is represented as 300. # SecRule &TX:crs_setup_version "@eq 0" \ "id:901001,\ phase:1,\ deny,\ status:500,\ log,\ auditlog,\ msg:'ModSecurity Core Rule Set is deployed without configuration! Please copy the crs-setup.conf.example template to crs-setup.conf, and include the crs-setup.conf file in your webserver configuration before including the CRS rules. See the INSTALL file in the CRS directory for detailed instructions.',\ severity:'CRITICAL'" # # -=[ Default setup values ]=- # # Some constructs or individual rules will fail if certain parameters # are not set in the setup.conf file. The following rules will catch # these cases and assign sane default values. # # Default Inbound Anomaly Threshold Level (rule 900110 in setup.conf) SecRule &TX:inbound_anomaly_score_threshold "@eq 0" \ "id:901100,\ phase:1,\ pass,\ nolog,\ setvar:'tx.inbound_anomaly_score_threshold=5'" # Default Outbound Anomaly Threshold Level (rule 900110 in setup.conf) SecRule &TX:outbound_anomaly_score_threshold "@eq 0" \ "id:901110,\ phase:1,\ pass,\ nolog,\ setvar:'tx.outbound_anomaly_score_threshold=4'" # Default Paranoia Level (rule 900000 in setup.conf) SecRule &TX:paranoia_level "@eq 0" \ "id:901120,\ phase:1,\ pass,\ nolog,\ setvar:'tx.paranoia_level=1'" # Default Executing Paranoia Level (rule 900000 in setup.conf) SecRule &TX:executing_paranoia_level "@eq 0" \ "id:901125,\ phase:1,\ pass,\ nolog,\ setvar:'tx.executing_paranoia_level=%{TX.PARANOIA_LEVEL}'" # Default Sampling Percentage (rule 900400 in setup.conf) SecRule &TX:sampling_percentage "@eq 0" \ "id:901130,\ phase:1,\ pass,\ nolog,\ setvar:'tx.sampling_percentage=100'" # Default Anomaly Scores (rule 900100 in setup.conf) SecRule &TX:critical_anomaly_score "@eq 0" \ "id:901140,\ phase:1,\ pass,\ nolog,\ setvar:'tx.critical_anomaly_score=5'" SecRule &TX:error_anomaly_score "@eq 0" \ "id:901141,\ phase:1,\ pass,\ nolog,\ setvar:'tx.error_anomaly_score=4'" SecRule &TX:warning_anomaly_score "@eq 0" \ "id:901142,\ phase:1,\ pass,\ nolog,\ setvar:'tx.warning_anomaly_score=3'" SecRule &TX:notice_anomaly_score "@eq 0" \ "id:901143,\ phase:1,\ pass,\ nolog,\ setvar:'tx.notice_anomaly_score=2'" # Default do_reput_block SecRule &TX:do_reput_block "@eq 0" \ "id:901150,\ phase:1,\ pass,\ nolog,\ setvar:'tx.do_reput_block=0'" # Default block duration SecRule &TX:reput_block_duration "@eq 0" \ "id:901152,\ phase:1,\ pass,\ nolog,\ setvar:'tx.reput_block_duration=300'" # Default HTTP policy: allowed_methods (rule 900200) SecRule &TX:allowed_methods "@eq 0" \ "id:901160,\ phase:1,\ pass,\ nolog,\ setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'" # Default HTTP policy: allowed_request_content_type (rule 900220) SecRule &TX:allowed_request_content_type "@eq 0" \ "id:901162,\ phase:1,\ pass,\ nolog,\ setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/soap+xml|application/x-amf|application/json|application/octet-stream|application/csp-report|application/xss-auditor-report|text/plain'" # Default HTTP policy: allowed_request_content_type_charset (rule 900270) SecRule &TX:allowed_request_content_type_charset "@eq 0" \ "id:901168,\ phase:1,\ pass,\ nolog,\ setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'" # Default HTTP policy: allowed_http_versions (rule 900230) SecRule &TX:allowed_http_versions "@eq 0" \ "id:901163,\ phase:1,\ pass,\ nolog,\ setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'" # Default HTTP policy: restricted_extensions (rule 900240) SecRule &TX:restricted_extensions "@eq 0" \ "id:901164,\ phase:1,\ pass,\ nolog,\ setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'" # Default HTTP policy: restricted_headers (rule 900250) SecRule &TX:restricted_headers "@eq 0" \ "id:901165,\ phase:1,\ pass,\ nolog,\ setvar:'tx.restricted_headers=/proxy/ /lock-token/ /content-range/ /translate/ /if/'" # Default HTTP policy: static_extensions (rule 900260) SecRule &TX:static_extensions "@eq 0" \ "id:901166,\ phase:1,\ pass,\ nolog,\ setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'" # Default enforcing of body processor URLENCODED SecRule &TX:enforce_bodyproc_urlencoded "@eq 0" \ "id:901167,\ phase:1,\ pass,\ nolog,\ setvar:'tx.enforce_bodyproc_urlencoded=0'" # # -=[ Initialize internal variables ]=- # # Initialize anomaly scoring variables. # All _score variables start at 0, and are incremented by the various rules # upon detection of a possible attack. # sql_error_match is used for shortcutting rules for performance reasons. SecAction \ "id:901200,\ phase:1,\ pass,\ t:none,\ nolog,\ setvar:'tx.anomaly_score=0',\ setvar:'tx.anomaly_score_pl1=0',\ setvar:'tx.anomaly_score_pl2=0',\ setvar:'tx.anomaly_score_pl3=0',\ setvar:'tx.anomaly_score_pl4=0',\ setvar:'tx.sql_injection_score=0',\ setvar:'tx.xss_score=0',\ setvar:'tx.rfi_score=0',\ setvar:'tx.lfi_score=0',\ setvar:'tx.rce_score=0',\ setvar:'tx.php_injection_score=0',\ setvar:'tx.http_violation_score=0',\ setvar:'tx.session_fixation_score=0',\ setvar:'tx.inbound_anomaly_score=0',\ setvar:'tx.outbound_anomaly_score=0',\ setvar:'tx.outbound_anomaly_score_pl1=0',\ setvar:'tx.outbound_anomaly_score_pl2=0',\ setvar:'tx.outbound_anomaly_score_pl3=0',\ setvar:'tx.outbound_anomaly_score_pl4=0',\ setvar:'tx.sql_error_match=0'" # # -=[ Initialize collections ]=- # # Create both Global and IP collections for rules to use. # There are some CRS rules that assume that these two collections # have already been initiated. # SecRule REQUEST_HEADERS:User-Agent "@rx ^.*$" \ "id:901318,\ phase:1,\ pass,\ t:none,t:sha1,t:hexEncode,\ nolog,\ setvar:'tx.ua_hash=%{MATCHED_VAR}'" SecAction \ "id:901321,\ phase:1,\ pass,\ t:none,\ nolog,\ initcol:global=global,\ initcol:ip=%{remote_addr}_%{tx.ua_hash},\ setvar:'tx.real_ip=%{remote_addr}'" # # -=[ Initialize Correct Body Processing ]=- # # Force request body variable and optionally request body processor # # Force body variable SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ "id:901340,\ phase:1,\ pass,\ nolog,\ noauditlog,\ msg:'Enabling body inspection',\ tag:'paranoia-level/1',\ ctl:forceRequestBodyVariable=On,\ ver:'OWASP_CRS/3.2.0'" # Force body processor URLENCODED SecRule TX:enforce_bodyproc_urlencoded "@eq 1" \ "id:901350,\ phase:1,\ pass,\ t:none,t:urlDecodeUni,\ nolog,\ noauditlog,\ msg:'Enabling forced body inspection for ASCII content',\ ver:'OWASP_CRS/3.2.0',\ chain" SecRule REQBODY_PROCESSOR "!@rx (?:URLENCODED|MULTIPART|XML|JSON)" \ "ctl:requestBodyProcessor=URLENCODED" # # -=[ Easing In / Sampling Percentage ]=- # # This is used to send only a limited percentage of requests into the Core # Rule Set. The selection is based on TX.sampling_percentage and a pseudo # random number calculated below. # # Use this to ease into a new Core Rules installation with an existing # productive service. # # See # https://www.netnea.com/cms/2016/04/26/easing-in-conditional-modsecurity-rule-execution-based-on-pseudo-random-numbers/ # # # Generate the pseudo random number # # ATTENTION: This is no cryptographically secure random number. It's just # a cheap way to get some random number suitable for sampling. # # We take the entropy contained in the UNIQUE_ID. We hash that variable and # take the first integer numbers out of it. Theoretically, it is possible # there are no integers in a sha1 hash. We make sure we get two # integer numbers by taking the last two digits from the DURATION counter # (in microseconds). # Finally, leading zeros are removed from the two-digit random number. # SecRule TX:sampling_percentage "@eq 100" \ "id:901400,\ phase:1,\ pass,\ nolog,\ skipAfter:END-SAMPLING" SecRule UNIQUE_ID "@rx ^." \ "id:901410,\ phase:1,\ pass,\ t:sha1,t:hexEncode,\ nolog,\ setvar:'TX.sampling_rnd100=%{MATCHED_VAR}'" SecRule DURATION "@rx (..)$" \ "id:901420,\ phase:1,\ pass,\ capture,\ nolog,\ setvar:'TX.sampling_rnd100=%{TX.sampling_rnd100}%{TX.1}'" SecRule TX:sampling_rnd100 "@rx ^[a-f]*([0-9])[a-f]*([0-9])" \ "id:901430,\ phase:1,\ pass,\ capture,\ nolog,\ setvar:'TX.sampling_rnd100=%{TX.1}%{TX.2}'" SecRule TX:sampling_rnd100 "@rx ^0([0-9])" \ "id:901440,\ phase:1,\ pass,\ capture,\ nolog,\ setvar:'TX.sampling_rnd100=%{TX.1}'" # # Sampling decision # # If a request is allowed to pass without being checked by the CRS, there is no # entry in the audit log (for performance reasons), but an error log entry is # being written. If you want to disable the error log entry, then issue the # following directive somewhere after the inclusion of the CRS # (E.g., RESPONSE-999-EXCEPTIONS.conf). # # SecRuleUpdateActionById 901450 "nolog" # SecRule TX:sampling_rnd100 "!@lt %{tx.sampling_percentage}" \ "id:901450,\ phase:1,\ pass,\ log,\ noauditlog,\ msg:'Sampling: Disable the rule engine based on sampling_percentage \ %{TX.sampling_percentage} and random number %{TX.sampling_rnd100}.',\ ctl:ruleEngine=Off" SecMarker "END-SAMPLING" # # Configuration Plausibility Checks # # Make sure executing paranoia level is not lower than paranoia level SecRule TX:executing_paranoia_level "@lt %{tx.paranoia_level}" \ "id:901500,\ phase:1,\ deny,\ status:500,\ t:none,\ log,\ msg:'Executing paranoia level configured is lower than the paranoia level itself. This is illegal. Blocking request. Aborting.'" modsecurity-crs-3.2.0/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf000066400000000000000000000301211355660542300241340ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default Drupal install. # The exclusions are only active if crs_exclusions_drupal=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. # # [ POLICY ] # # Drupal is a complex application that is hard to secure with the CRS. This set # of exclusion rules aims to sanitise the CRS in a way that allows a default # Drupal setup to be installed and configured without much hassle as far as # ModSecurity and the CRS are concerned. # # The exclusion rules are fairly straight forward in the sense that they # disable CRS on a set of well-known parameter fields that are often the source # of false positives / false alarms of the CRS. This includes namely the # session cookie, the password fields and article/node bodies. # # This is based on two assumptions: - You have a basic trust in your # authenticated users who are allowed to edit nodes. - Drupal allows html # content in nodes and it protects your users from attacks via these fields. # # If you think these assumptions are wrong or if you would prefer a more # careful/secure approach, you can disable the exclusion rules handling of said # node body false positives. Do this by placing the following directive in # RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf. # # SecRuleRemoveById 9001200-9001299 # # This will mean the CRS remain intact for the editing of node bodies. # # The exclusion rules in this file work without the need to define a Drupal # installation path prefix. Instead they look at the URI from the end - or # they use regular expressions when targeting dynamic URL. This is all not # totally foolproof. In some cases, an advanced attacker might be able to # doctor a request in a way that one of these exclusion rules is triggered # and the request will bypass all further inspection despite not being a # Drupal request at all. These exclusion rules could thus be leveraged to # disable the CRS completely. This is why these rules are off by default. # # The CRS rules covered by this ruleset are the rules with Paranoia Level 1 and # 2. If you chose to run Paranoia Level 3 or 4, you will be facing additional # false positives which you need to handle yourself. # # This set of exclusion rules does not cover any additional Drupal modules # outside of core. # # The exclusion rules are based on Drupal 8.1.10. # # And finally: This set of exclusion rules is in an experimental state. If you # encounter false positives with the basic Drupal functionality and they are # not covered by this rule file, then please report them. The aim is to be able # to install and run Drupal core in a seamless manner protected by # ModSecurity / CRS up to the paranoia level 2. SecRule &TX:crs_exclusions_drupal|TX:crs_exclusions_drupal "@eq 0" \ "id:9001000,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-DRUPAL-RULE-EXCLUSIONS" # [ Table of Contents ] # # 9001100 Session Cookie # 9001110 Password # 9001120 FREE for use # 9001130 FREE for use # 9001140 Content and Descriptions # 9001150 FREE for use # 9001160 Form Token # 9001170 Text Formats and Editors # 9001180 WYSIWYG/CKEditor Assets and Upload # 9001190 FREE for use # 9001200 Content and Descriptions # # The rule id range from 9001200 to 9001999 is reserved for future # use (Drupal plugins / modules). # [ Session Cookie ] # # Giving the session cookie a dynamic name is most unfortunate # from a ModSecurity perspective. The rule language does not allow # us to disable rules in a granular way for individual cookies with # dynamic names. So we need to disable rule causing false positives # for all cookies and their names. # # Rule Exclusion Session Cookie: 942450 SQL Hex Encoding Identified # SecAction "id:9001100,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetById=942450;REQUEST_COOKIES_NAMES,\ ctl:ruleRemoveTargetById=942450;REQUEST_COOKIES" # # [ Password ] # # Disable the CRS completely for all occurrences of passwords. # SecRule REQUEST_FILENAME "@endsWith /core/install.php" \ "id:9001110,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:account[pass][pass1],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:account[pass][pass2]" SecRule REQUEST_FILENAME "@endsWith /user/login" \ "id:9001112,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass" SecRule REQUEST_FILENAME "@endsWith /admin/people/create" \ "id:9001114,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass1],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass2]" SecRule REQUEST_FILENAME "@rx /user/[0-9]+/edit$" \ "id:9001116,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:current_pass,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass1],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass[pass2]" # # [ Admin Settings (general) ] # # Disable known false positives for various fields used on admin pages. # # Rule Exclusion: 920271 Invalid character in request on multiple fields/paths # Rule Exclusion: 942430 Restricted SQL Character Anomaly Detection (args) # Disabled completely for admin/config pages # For the people/accounts page, we disable the CRS completely for a number of # freeform text fields. # SecRule REQUEST_FILENAME "@contains /admin/config/" \ "id:9001122,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveById=942430" SecRule REQUEST_FILENAME "@endsWith /admin/config/people/accounts" \ "id:9001124,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveById=920271,\ ctl:ruleRemoveById=942440,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_cancel_confirm_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_password_reset_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_admin_created_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_no_approval_required_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_register_pending_approval_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_activated_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_blocked_body,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:user_mail_status_canceled_body" SecRule REQUEST_FILENAME "@endsWith /admin/config/development/configuration/single/import" \ "id:9001126,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveById=920271,\ ctl:ruleRemoveById=942440" SecRule REQUEST_FILENAME "@endsWith /admin/config/development/maintenance" \ "id:9001128,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveById=942440" # # # [ Content and Descriptions ] # # Disable known false positives for field "ids[]". # # Rule Exclusion: 942130 SQL Injection Attack: SQL Tautology Detected # SecRule REQUEST_FILENAME "@endsWith /contextual/render" \ "id:9001140,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetById=942130;ARGS:ids[]" # # [ Form Token / Build ID ] # # Rule Exclusion for form_build_id: 942440 SQL Comment Sequence Detected on ... # Rule Exclusion for form_token: 942450 SQL Hex Encoding # Rule Exclusion for form_build_id: 942450 SQL Hex Encoding # # This is applied site-wide. # SecAction "id:9001160,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetById=942440;ARGS:form_build_id,\ ctl:ruleRemoveTargetById=942450;ARGS:form_token,\ ctl:ruleRemoveTargetById=942450;ARGS:form_build_id" # # [ Text Formats and Editors ] # # Disable the CRS completely for two fields triggering many, many rules # # Rule Exclusion for two fields: 942440 SQL Comment Sequence Detected # SecRule REQUEST_FILENAME "@endsWith /admin/config/content/formats/manage/full_html" \ "id:9001170,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:editor[settings][toolbar][button_groups],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:filters[filter_html][settings][allowed_html]" # # [ WYSIWYG/CKEditor Assets and Upload ] # # Disable the unnecessary requestBodyAccess and for binary uploads # bigger than an arbitrary limit of 31486341 bytes. # # Extensive checks make sure these uploads are really legitimate. # SecRule REQUEST_METHOD "@streq POST" \ "id:9001180,\ phase:1,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule REQUEST_FILENAME "@rx /admin/content/assets/add/[a-z]+$" \ "chain" SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \ "ctl:requestBodyAccess=Off" SecRule REQUEST_METHOD "@streq POST" \ "id:9001182,\ phase:1,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule REQUEST_FILENAME "@rx /admin/content/assets/manage/[0-9]+$" \ "chain" SecRule ARGS:destination "@streq admin/content/assets" \ "chain" SecRule REQUEST_HEADERS:Content-Length "@gt 31486341" \ "chain" SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \ "ctl:requestBodyAccess=Off" SecRule REQUEST_METHOD "@streq POST" \ "id:9001184,\ phase:1,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule REQUEST_FILENAME "@rx /file/ajax/field_asset_[a-z0-9_]+/[ua]nd/0/form-[a-z0-9A-Z_-]+$" \ "chain" SecRule REQUEST_HEADERS:Content-Length "@gt 31486341" \ "chain" SecRule REQUEST_HEADERS:Content-Type "@rx ^(?i)multipart/form-data" \ "chain" SecRule REQUEST_COOKIES:/S?SESS[a-f0-9]+/ "@rx ^[a-zA-Z0-9_-]+" \ "ctl:requestBodyAccess=Off" # # [ Content and Descriptions ] # # Disable the CRS completely for node bodies and other free text fields. # Other rules are disabled individually. # # Rule Exclusion for ARGS:uid[0][target_id]: 942410 SQL Injection Attack # Rule Exclusion for ARGS:destination: 932110 RCE: Windows Command Inj. # SecRule REQUEST_FILENAME "@endsWith /node/add/article" \ "id:9001200,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\ ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id]" SecRule REQUEST_FILENAME "@endsWith /node/add/page" \ "id:9001202,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\ ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id]" SecRule REQUEST_FILENAME "@rx /node/[0-9]+/edit$" \ "id:9001204,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value],\ ctl:ruleRemoveTargetById=942410;ARGS:uid[0][target_id],\ ctl:ruleRemoveTargetById=932110;ARGS:destination" SecRule REQUEST_FILENAME "@endsWith /block/add" \ "id:9001206,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:body[0][value]" SecRule REQUEST_FILENAME "@endsWith /admin/structure/block/block-content/manage/basic" \ "id:9001208,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:description" SecRule REQUEST_FILENAME "@rx /editor/filter_xss/(?:full|basic)_html$" \ "id:9001210,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:value" SecRule REQUEST_FILENAME "@rx /user/[0-9]+/contact$" \ "id:9001212,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message[0][value]" SecRule REQUEST_FILENAME "@endsWith /admin/config/development/maintenance" \ "id:9001214,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:maintenance_mode_message" SecRule REQUEST_FILENAME "@endsWith /admin/config/services/rss-publishing" \ "id:9001216,\ phase:2,\ pass,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:feed_description" SecMarker "END-DRUPAL-RULE-EXCLUSIONS" modsecurity-crs-3.2.0/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf000066400000000000000000000553661355660542300245600ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default WordPress install. # The exclusions are only active if crs_exclusions_wordpress=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. # # Note that the WordPress comment field itself is currently NOT excluded # from checking. The reason is that malicious content is regularly being # posted to WordPress comment forms, and there have been various cases # of XSS and even RCE vulnerabilities exploited by WordPress comments. SecRule &TX:crs_exclusions_wordpress|TX:crs_exclusions_wordpress "@eq 0" \ "id:9002000,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-WORDPRESS" SecRule &TX:crs_exclusions_wordpress|TX:crs_exclusions_wordpress "@eq 0" \ "id:9002001,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-WORDPRESS" # # -=[ WordPress Front-End ]=- # # # [ Login form ] # # User login password SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ "id:9002100,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd" # Reset password SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \ "id:9002120,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq resetpass" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # # [ Comments ] # # Post comment SecRule REQUEST_FILENAME "@endsWith /wp-comments-post.php" \ "id:9002130,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931130;ARGS:url" # # [ Gutenberg Editor ] # Used when a user (auto)saves a post/page with Gutenberg. # # Gutenberg SecRule REQUEST_FILENAME "@rx ^/wp\-json/wp/v[0-9]+/(?:posts|pages)" \ "id:9002140,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:json.content" # Gutenberg via rest_route for sites without pretty permalinks SecRule REQUEST_FILENAME "@endsWith /index.php" \ "id:9002141,\ phase:1,\ pass,\ t:none,\ nolog,\ chain" SecRule &ARGS:rest_route "@eq 1" \ "t:none,\ nolog,\ chain" SecRule ARGS:rest_route "@rx ^/wp/v[0-9]+/(?:posts|pages)" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:json.content" # # [ Live preview ] # Used when an administrator customizes the site and previews the result # as a normal user. # # Theme select # Example: wp_customize=on&theme=twentyfifteen&customized= # {"old_sidebars_widgets_data":{"wp_inactive_widgets":[], # "sidebar-1":["search-2","recent-posts-2","recent-comments-2", # "archives-2","categories-2","meta-2"]}}&nonce=XXX& # customize_messenger_channel=preview-0 SecRule ARGS:wp_customize "@streq on" \ "id:9002150,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule &ARGS:action "@eq 0" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:customized,\ ctl:ruleRemoveTargetById=942260;ARGS:customized,\ ctl:ruleRemoveTargetById=942300;ARGS:customized,\ ctl:ruleRemoveTargetById=942330;ARGS:customized,\ ctl:ruleRemoveTargetById=942340;ARGS:customized,\ ctl:ruleRemoveTargetById=942370;ARGS:customized,\ ctl:ruleRemoveTargetById=942430;ARGS:customized,\ ctl:ruleRemoveTargetById=942431;ARGS:customized,\ ctl:ruleRemoveTargetById=942460;ARGS:customized" # Appearance -> Widgets -> Live Preview SecRule ARGS:wp_customize "@streq on" \ "id:9002160,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@rx ^(?:|customize_save|update-widget)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:customized,\ ctl:ruleRemoveTargetById=942260;ARGS:customized,\ ctl:ruleRemoveTargetById=942300;ARGS:customized,\ ctl:ruleRemoveTargetById=942330;ARGS:customized,\ ctl:ruleRemoveTargetById=942340;ARGS:customized,\ ctl:ruleRemoveTargetById=942370;ARGS:customized,\ ctl:ruleRemoveTargetById=942430;ARGS:customized,\ ctl:ruleRemoveTargetById=942431;ARGS:customized,\ ctl:ruleRemoveTargetById=942460;ARGS:customized,\ ctl:ruleRemoveTargetById=920230;ARGS:partials,\ ctl:ruleRemoveTargetById=941320;ARGS:partials,\ ctl:ruleRemoveTargetById=942180;ARGS:partials,\ ctl:ruleRemoveTargetById=942200;ARGS:partials,\ ctl:ruleRemoveTargetById=942260;ARGS:partials,\ ctl:ruleRemoveTargetById=942330;ARGS:partials,\ ctl:ruleRemoveTargetById=942340;ARGS:partials,\ ctl:ruleRemoveTargetById=942370;ARGS:partials,\ ctl:ruleRemoveTargetById=942430;ARGS:partials,\ ctl:ruleRemoveTargetById=942431;ARGS:partials,\ ctl:ruleRemoveTargetById=942460;ARGS:partials" # Self calls to wp-cron.php?doing_wp_cron=[timestamp] # These requests may be missing Accept, Content-Length headers. # This rule must run in phase:1. SecRule REQUEST_FILENAME "@endsWith /wp-cron.php" \ "id:9002200,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=920180,\ ctl:ruleRemoveById=920300" # # [ Cookies ] # WP Session Manager # Cookie: _wp_session=[hex]||[timestamp]||[timestamp] # detected SQLi using libinjection with fingerprint 'n&1' SecRule REQUEST_COOKIES:_wp_session "@rx ^[0-9a-f]+\|\|\d+\|\|\d+$" \ "id:9002300,\ phase:1,\ pass,\ t:none,\ nolog,\ chain" SecRule &REQUEST_COOKIES:_wp_session "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:_wp_session" # # -=[ WordPress Administration Back-End (wp-admin) ]=- # # Skip this section for performance unless /wp-admin/ is in filename SecRule REQUEST_FILENAME "!@contains /wp-admin/" \ "id:9002400,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-WORDPRESS-ADMIN" SecRule REQUEST_FILENAME "!@contains /wp-admin/" \ "id:9002401,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-WORDPRESS-ADMIN" # # [ Installation ] # # WordPress installation: exclude database password SecRule REQUEST_FILENAME "@endsWith /wp-admin/setup-config.php" \ "id:9002410,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:step "@streq 2" \ "t:none,\ chain" SecRule &ARGS:step "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd" # WordPress installation: exclude admin password SecRule REQUEST_FILENAME "@endsWith /wp-admin/install.php" \ "id:9002420,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:step "@streq 2" \ "t:none,\ chain" SecRule &ARGS:step "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:admin_password,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:admin_password2,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text" # # [ User management ] # # Edit logged-in user SecRule REQUEST_FILENAME "@endsWith /wp-admin/profile.php" \ "id:9002520,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetById=931130;ARGS:facebook,\ ctl:ruleRemoveTargetById=931130;ARGS:googleplus,\ ctl:ruleRemoveTargetById=931130;ARGS:instagram,\ ctl:ruleRemoveTargetById=931130;ARGS:linkedin,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # Edit user SecRule REQUEST_FILENAME "@endsWith /wp-admin/user-edit.php" \ "id:9002530,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # Create user SecRule REQUEST_FILENAME "@endsWith /wp-admin/user-new.php" \ "id:9002540,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq createuser" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # # [ General exclusions ] # # _wp_http_referer and wp_http_referer are passed on a lot of wp-admin pages SecAction \ "id:9002600,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=920230;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=931130;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=932150;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=941100;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942130;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942200;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942260;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942431;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=942440;ARGS:_wp_http_referer,\ ctl:ruleRemoveTargetById=920230;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=931130;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=932150;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=941100;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942130;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942200;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942260;ARGS:wp_http_referer,\ ctl:ruleRemoveTargetById=942431;ARGS:wp_http_referer" # # [ Content editing ] # # Edit posts and pages # /wp-admin/post.php, /wp-admin/post.php?t=[timestamp] # - Themes do not properly escape post_title in HTML, so beware of XSS # and be conservative in excluding this parameter. # - Parameter _wp_http_referer can appear multiple times. SecRule REQUEST_FILENAME "@endsWith /wp-admin/post.php" \ "id:9002700,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@rx ^(?:edit|editpost)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:post_title,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:content,\ ctl:ruleRemoveById=920272,\ ctl:ruleRemoveById=921180" # Autosave posts and pages # ARGS_NAMES:data[wp-check-locked-posts][] can appear multiple times SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002710,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq heartbeat" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:data[wp_autosave][post_title],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:data[wp_autosave][content],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-refresh-post-lock][post_id],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-refresh-post-lock][lock],\ ctl:ruleRemoveTargetById=942431;ARGS_NAMES:data[wp-check-locked-posts][],\ ctl:ruleRemoveById=921180,\ ctl:ruleRemoveById=920272" # Edit menus SecRule REQUEST_FILENAME "@endsWith /wp-admin/nav-menus.php" \ "id:9002720,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942460;ARGS:menu-name,\ ctl:ruleRemoveTargetById=941330;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=941340;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942200;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942260;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942330;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942340;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942430;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942431;ARGS:nav-menu-data,\ ctl:ruleRemoveTargetById=942460;ARGS:nav-menu-data" # Edit text widgets (can contain custom HTML) SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002730,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@rx ^(?:save-widget|update-widget)$" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[0][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[1][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[2][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[3][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[4][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[5][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[6][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[7][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[8][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[9][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[10][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[11][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[12][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[13][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[14][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[15][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[16][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[17][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[18][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[19][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[20][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[21][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[22][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[23][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[24][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[25][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[26][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[27][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[28][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[29][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[30][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[31][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[32][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[33][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[34][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[35][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[36][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[37][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[38][text],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:widget-text[39][text]" # Reorder widgets SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002740,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq widgets-order" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-1],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-1],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-2],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-2],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-3],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-3],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-4],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-4],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-5],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-5],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-6],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-6],\ ctl:ruleRemoveTargetById=942430;ARGS:sidebars[sidebar-7],\ ctl:ruleRemoveTargetById=942431;ARGS:sidebars[sidebar-7]" # Create permalink sample for new post SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002750,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq sample-permalink" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:new_title" # Add external link to menu SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002760,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq add-menu-item" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:menu-item[-1][menu-item-url]" # Editor: Add Media, Insert Media, Insert into page SecRule REQUEST_FILENAME "@endsWith /wp-admin/admin-ajax.php" \ "id:9002770,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq send-attachment-to-editor" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:html" # # [ Options and Settings ] # # Change site URL SecRule REQUEST_FILENAME "@endsWith /wp-admin/options.php" \ "id:9002800,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:option_page "@streq general" \ "t:none,\ chain" SecRule &ARGS:option_page "@eq 1" \ "t:none,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetById=931130;ARGS:home,\ ctl:ruleRemoveTargetById=931130;ARGS:siteurl" # Permalink settings # permalink_structure=/index.php/%year%/%monthnum%/%day%/%postname%/ SecRule REQUEST_FILENAME "@endsWith /wp-admin/options-permalink.php" \ "id:9002810,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=920230;ARGS:selection,\ ctl:ruleRemoveTargetById=920272;ARGS:selection,\ ctl:ruleRemoveTargetById=942431;ARGS:selection,\ ctl:ruleRemoveTargetById=920230;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=920272;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=942431;ARGS:permalink_structure,\ ctl:ruleRemoveTargetById=920272;REQUEST_BODY" # Comments blacklist and moderation list SecRule REQUEST_FILENAME "@endsWith /wp-admin/options.php" \ "id:9002820,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:option_page "@streq discussion" \ "t:none,\ chain" SecRule &ARGS:option_page "@eq 1" \ "t:none,\ chain" SecRule ARGS:action "@streq update" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:blacklist_keys,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:moderation_keys" # Posts/pages overview search SecRule REQUEST_FILENAME "@endsWith /wp-admin/edit.php" \ "id:9002830,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:s" # # [ Helpers ] # # /wp-admin/load-scripts.php?c=0&load%5B%5D=hoverIntent,common, # admin-bar,wp-ajax-response,jquery-color,wp-lists,quicktags, # jquery-query,admin-comments,svg-painter,heartbeat,&load%5B%5D= # wp-auth-check,wp-a11y,wplink,jquery-ui-core,jquery-ui-widget, # jquery-ui-position,jquery-ui-menu,jquery-ui-autocomplete&ver=4.6.1 # # /wp-admin/load-styles.php?c=0&dir=ltr&load%5B%5D=dashicons, # admin-bar,buttons,media-views,common,forms,admin-menu,dashboard, # list-tables,edit,revisions,media,themes,about,nav-menu&load%5B%5D= # s,widgets,site-icon,l10n,wp-auth-check&ver=4.6.1 # # /wp-admin/load-scripts.php?c=0&load%5B%5D=hoverIntent,common, # admin-bar,jquery-ui-widget,jquery-ui-position,wp-pointer, # wp-ajax-response,jquery-color,wp-lists,quicktags, # jqu&load%5B%5D=ery-query,admin-comments,jquery-ui-core, # jquery-ui-mouse,jquery-ui-sortable,postbox,dashboard,underscore, # customize-base,customize&load%5B%5D=-loader,thickbox,plugin-install, # wp-util,wp-a11y,updates,shortcode,media-upload,svg-painter, # jquery-ui-accordion&ver=3f9999390861a0133beda3ee8acf152e SecRule REQUEST_FILENAME "@rx /wp-admin/load-(?:scripts|styles)\.php$" \ "id:9002900,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=921180,\ ctl:ruleRemoveTargetById=920273;ARGS_NAMES:load[],\ ctl:ruleRemoveTargetById=942432;ARGS_NAMES:load[],\ ctl:ruleRemoveTargetById=942360;ARGS:load[],\ ctl:ruleRemoveTargetById=942430;ARGS:load[],\ ctl:ruleRemoveTargetById=942431;ARGS:load[],\ ctl:ruleRemoveTargetById=942432;ARGS:load[]" SecMarker "END-WORDPRESS-ADMIN" SecMarker "END-WORDPRESS" modsecurity-crs-3.2.0/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf000066400000000000000000000215621355660542300245250ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default NextCloud install. # They will likely work with OwnCloud too, but you may have to modify them. # The exclusions are only active if crs_exclusions_nextcloud=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. # # To relax upload restrictions for only the php files that need it, # you put something like this in crs-setup.conf: # # SecRule REQUEST_FILENAME "@rx /(?:remote.php|index.php)/" \ # "id:9003330,\ # phase:1,\ # t:none,\ # nolog,\ # pass,\ # tx.restricted_extensions='.bak/ .config/ .conf/'" # # Large uploads can be modified with SecRequestBodyLimit. Or they # can be more controlled by using the following: # # SecRule REQUEST_URI "@endsWith /index.php/apps/files/ajax/upload.php" \ # "id:9003610,\ # phase:1,\ # t:none,\ # nolog,\ # ctl:requestBodyLimit=1073741824" # # --------------------- SecRule &TX:crs_exclusions_nextcloud|TX:crs_exclusions_nextcloud "@eq 0" \ "id:9003000,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-NEXTCLOUD" SecRule &TX:crs_exclusions_nextcloud|TX:crs_exclusions_nextcloud "@eq 0" \ "id:9003001,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-NEXTCLOUD" # # [ File Manager ] # # # The web interface uploads files, and interacts with the user. SecRule REQUEST_FILENAME "@contains /remote.php/webdav" \ "id:9003100,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveByTag=attack-injection-php,\ ctl:ruleRemoveById=941000-942999,\ ctl:ruleRemoveById=951000-951999,\ ctl:ruleRemoveById=953100-953130,\ ctl:ruleRemoveById=920420,\ ctl:ruleRemoveById=920440" # Skip PUT parsing for invalid encoding / protocol violations in binary files. SecRule REQUEST_METHOD "@streq PUT" \ "id:9003105,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_FILENAME "@contains /remote.php/webdav" \ "t:none,\ ctl:ruleRemoveById=920000-920999,\ ctl:ruleRemoveById=932000-932999,\ ctl:ruleRemoveById=921150,\ ctl:ruleRemoveById=930110,\ ctl:ruleRemoveById=930120" # Allow the data type 'text/vcard' SecRule REQUEST_FILENAME "@contains /remote.php/dav/files/" \ "id:9003110,\ phase:2,\ pass,\ t:none,\ nolog,\ setvar:'tx.allowed_request_content_type=%{tx.allowed_request_content_type}|text/vcard'" # Allow the data type 'application/octet-stream' SecRule REQUEST_METHOD "@rx ^(?:PUT|MOVE)$" \ "id:9003115,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_FILENAME "@rx /remote\.php/dav/(?:files|uploads)/" \ "setvar:'tx.allowed_request_content_type=%{tx.allowed_request_content_type}|application/octet-stream'" # Allow data types like video/mp4 SecRule REQUEST_METHOD "@streq PUT" \ "id:9003116,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_FILENAME "@rx (?:/public\.php/webdav/|/remote\.php/dav/uploads/)" \ "ctl:ruleRemoveById=920340,\ ctl:ruleRemoveById=920420" # Allow characters like /../ in files. # Allow all kind of filetypes. # Allow source code. SecRule REQUEST_FILENAME "@contains /remote.php/dav/files/" \ "id:9003120,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=930100-930110,\ ctl:ruleRemoveById=951000-951999,\ ctl:ruleRemoveById=953100-953130,\ ctl:ruleRemoveById=920440" # [ Searchengine ] # # NexCloud uses a search field for filename or content queries. SecRule REQUEST_FILENAME "@contains /index.php/core/search" \ "id:9003125,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=attack-injection-php;ARGS:query,\ ctl:ruleRemoveTargetById=941000-942999;ARGS:query,\ ctl:ruleRemoveTargetById=932000-932999;ARGS:query" # [ DAV ] # # NextCloud uses DAV methods with index.php and remote.php to do many things # The default ones in ModSecurity are: GET HEAD POST OPTIONS # # Looking through the code, and via testing, I found these: # # File manager: PUT DELETE MOVE PROPFIND PROPPATCH # Calendars: REPORT # Others in the code or js files: PATCH MKCOL MOVE TRACE # Others that I added just in case, and they seem related: # CHECKOUT COPY LOCK MERGE MKACTIVITY UNLOCK. SecRule REQUEST_FILENAME "@rx /(?:remote|index|public)\.php/" \ "id:9003130,\ phase:2,\ pass,\ t:none,\ nolog,\ setvar:'tx.allowed_methods=%{tx.allowed_methods} PUT PATCH CHECKOUT COPY DELETE LOCK MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH UNLOCK REPORT TRACE jsonp'" # We need to allow DAV methods for sharing files, and removing shares # DELETE - when the share is removed # PUT - when setting a password / expiration time SecRule REQUEST_FILENAME "@rx /ocs/v[0-9]+\.php/apps/files_sharing/" \ "id:9003140,\ phase:2,\ pass,\ t:none,\ nolog,\ setvar:'tx.allowed_methods=%{tx.allowed_methods} PUT DELETE'" # [ Preview and Thumbnails ] SecRule REQUEST_FILENAME "@contains /index.php/core/preview.png" \ "id:9003150,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=932150;ARGS:file" # Filepreview for trashbin SecRule REQUEST_FILENAME "@contains /index.php/apps/files_trashbin/ajax/preview.php" \ "id:9003155,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=932150;ARGS:file,\ ctl:ruleRemoveTargetById=942190;ARGS:file" SecRule REQUEST_FILENAME "@rx /index\.php/(?:apps/gallery/thumbnails|logout$)" \ "id:9003160,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=941120;ARGS:requesttoken" # [ Ownnote ] SecRule REQUEST_FILENAME "@contains /index.php/apps/ownnote/" \ "id:9003300,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=941150" # [ Text Editor ] # # This file can save anything, and it's name could be lots of things. SecRule REQUEST_FILENAME "@contains /index.php/apps/files_texteditor/" \ "id:9003310,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:filecontents,\ ctl:ruleRemoveTargetById=921110-921160;ARGS:filecontents,\ ctl:ruleRemoveTargetById=932150;ARGS:filename,\ ctl:ruleRemoveTargetById=920370-920390;ARGS:filecontents,\ ctl:ruleRemoveTargetById=920370-920390;ARGS_COMBINED_SIZE" # [ Address Book ] # # Allow the data type 'text/vcard' SecRule REQUEST_FILENAME "@contains /remote.php/dav/addressbooks/" \ "id:9003320,\ phase:2,\ pass,\ t:none,\ nolog,\ setvar:'tx.allowed_request_content_type=%{tx.allowed_request_content_type}|text/vcard'" # [ Calendar ] # # Allow the data type 'text/calendar' SecRule REQUEST_FILENAME "@contains /remote.php/dav/calendars/" \ "id:9003330,\ phase:2,\ pass,\ t:none,\ nolog,\ setvar:'tx.allowed_request_content_type=%{tx.allowed_request_content_type}|text/calendar'" # [ Notes ] # # We want to allow a lot of things as the user is # allowed to note on anything. SecRule REQUEST_FILENAME "@contains /index.php/apps/notes/" \ "id:9003340,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveByTag=attack-injection-php" # [ Bookmarks ] # # Allow urls in data. SecRule REQUEST_FILENAME "@contains /index.php/apps/bookmarks/" \ "id:9003350,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=931130" # # [ Login forms ] # # This removes checks on the 'password' and related fields: # User login password. SecRule REQUEST_FILENAME "@contains /index.php/login" \ "id:9003400,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=941100;ARGS:requesttoken,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:password" # Reset password. SecRule REQUEST_FILENAME "@endsWith /index.php/login" \ "id:9003410,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule ARGS:action "@streq resetpass" \ "t:none,\ chain" SecRule &ARGS:action "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # Change Password and Setting up a new user/password SecRule REQUEST_FILENAME "@endsWith /index.php/settings/users" \ "id:9003500,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:newuserpassword,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:password" SecMarker "END-NEXTCLOUD-ADMIN" SecMarker "END-NEXTCLOUD" modsecurity-crs-3.2.0/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf000066400000000000000000000165331355660542300244110ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default Dokuwiki install. # The exclusions are only active if crs_exclusions_dokuwiki=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. # # Note, if you want to relax the upload restrictions, # see rule 900240. For Dokuwiki you can limit the exception # to the ajax.php file: # # SecRule REQUEST_FILENAME "@endsWith /lib/exe/ajax.php" ... # SecRule &TX:crs_exclusions_dokuwiki|TX:crs_exclusions_dokuwiki "@eq 0" \ "id:9004000,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-DOKUWIKI" SecRule &TX:crs_exclusions_dokuwiki|TX:crs_exclusions_dokuwiki "@eq 0" \ "id:9004001,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-DOKUWIKI" # # -=[ Dokuwiki Front-End ]=- # # Note on files specified: # /doku.php: shows pages, saves, edits, admin # /lib/exe/ajax.php: autosave, uploads # # Allow pages to be edited, and ajax to save drafts. # # ARGS 'wikitext', 'suffix', and 'prefix' must allow the same things, # as the page (in part or whole) is passed via 'suffix/prefix' at times. # attack-protocol (921110-921160/920230): Allows odd characters on the page. # CRS: (still need attack-protocol specified.) # attack-injection-php (930000-933999): Allows code on page. # attack-sqli (940000-942999): Allows SQL expressions on page. # # Others: # 930100-930110;REQUEST_BODY: if there's a /../ in the text. # # ARGS:summary (the text in the 'summary' box on page edits.): # Allowing 930120-930130 lets user save summaries with # system file names. This should not be needed in normal # use. But leaving a note here of how to allow in rule below: # ctl:ruleRemoveTargetById=930120;ARGS:summary # ctl:ruleRemoveTargetById=930130;ARGS:summary # # Also, can't specify: # SecRule ARGS:do "@streq edit" \ # SecRule REQUEST_FILENAME "@endsWith /lib/exe/ajax.php"\ # because at times the do=edit can get dropped, so if we use # above the edit will get blocked when the page is saved. # Hint: those using .htaccess rewrites can remove/replace # this first 'SecRule...' line with 'SecAction \' (unsupported). SecRule REQUEST_FILENAME "@rx (?:/doku.php|/lib/exe/ajax.php)$" \ "id:9004100,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_METHOD "@streq POST" \ "t:none,\ chain" SecRule REQUEST_COOKIES:/S?DW[a-f0-9]+/ "@rx ^[%a-zA-Z0-9_-]+" \ "t:none,\ ctl:ruleRemoveTargetByTag=attack-protocol;ARGS:wikitext,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:wikitext,\ ctl:ruleRemoveTargetByTag=attack-protocol;ARGS:suffix,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:suffix,\ ctl:ruleRemoveTargetByTag=attack-protocol;ARGS:prefix,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:prefix,\ ctl:ruleRemoveTargetById=930100-930110;REQUEST_BODY" # Allow it to upload files. But check for cookies just to make sure. SecRule REQUEST_FILENAME "@endsWith /lib/exe/ajax.php" \ "id:9004110,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule REQUEST_METHOD "@streq POST" \ "t:none,\ chain" SecRule REQUEST_COOKIES:/S?DW[a-f0-9]+/ "@rx ^[%a-zA-Z0-9_-]+" \ "t:none,\ setvar:'tx.allowed_request_content_type=%{tx.allowed_request_content_type}|application/octet-stream'" # Show the index, even if things like "postgresql" or other things show up. SecRule REQUEST_FILENAME "@endsWith /doku.php" \ "id:9004130,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule ARGS:do "@streq index" \ "t:none,\ chain" SecRule &ARGS:do "@eq 1" \ "t:none,\ ctl:ruleRemoveById=951240,\ ctl:ruleRemoveById=953110" # # [ Login form ] # # Turn off checks for password. SecRule REQUEST_FILENAME "@endsWith /doku.php" \ "id:9004200,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule ARGS:do "@streq login" \ "t:none,\ chain" SecRule &ARGS:do "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:p" # # [ Admin Area ] # # Skip this section for performance unless do=admin is in request SecRule ARGS:do "!@streq admin" \ "id:9004300,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-DOKUWIKI-ADMIN" SecRule ARGS:do "!@streq admin" \ "id:9004310,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-DOKUWIKI-ADMIN" # [ Reset password ] # # Turn off checks for pass1, pass1-text, pass2 SecRule REQUEST_FILENAME "@endsWith /doku.php" \ "id:9004320,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule ARGS:do "@streq login" \ "t:none,\ chain" SecRule &ARGS:do "@eq 1" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass1-text,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pass2" # [ Save config ] # # Allow the config to be saved: # 942200: If the user adds "..." to tagline: ARGS:config[tagline] # 942430: if ARGS:config[hidepages] has pages looking like sql statements # 942430,942440: "--- //[[@MAIL@|@NAME@]] @DATE@//"]" in ARGS:config[signature] SecRule REQUEST_FILENAME "@endsWith /doku.php" \ "id:9004370,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule ARGS:page "@streq config" \ "t:none,\ chain" SecRule &ARGS:page "@eq 1" \ "t:none,\ chain" SecRule REQUEST_METHOD "@streq POST" \ "t:none,\ chain" SecRule REQUEST_COOKIES:/S?DW[a-f0-9]+/ "@rx ^[%a-zA-Z0-9_-]+" \ "t:none,\ ctl:ruleRemoveTargetById=920230;ARGS:config[dformat],\ ctl:ruleRemoveTargetById=942200;ARGS:config[tagline],\ ctl:ruleRemoveTargetById=942430;ARGS:config[hidepages],\ ctl:ruleRemoveTargetById=942430-942440;ARGS:config[signature]" # When the config loads after a save, it gets blocked because # it has 'readdir' and lines that look like sql # 942430,942440: "--- //[[@MAIL@|@NAME@]] @DATE@//"]" in ARGS:config[signature] # 951240,953110: When the page reloads, it triggers # postgress and php code disclosure rules. SecRule REQUEST_FILENAME "@endsWith /doku.php" \ "id:9004380,\ phase:2,\ pass,\ t:none,\ nolog,\ noauditlog,\ chain" SecRule ARGS:page "@streq config" \ "t:none,\ chain" SecRule &ARGS:page "@eq 1" \ "t:none,\ chain" SecRule REQUEST_COOKIES:/S?DW[a-f0-9]+/ "@rx ^[%a-zA-Z0-9_-]+" \ "t:none,\ ctl:ruleRemoveById=951240,\ ctl:ruleRemoveById=953110" # End [ Admin Area ] SecMarker "END-DOKUWIKI-ADMIN" SecMarker "END-DOKUWIKI" modsecurity-crs-3.2.0/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf000066400000000000000000000034001355660542300241130ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default cPanel environment. # The exclusions are only active if crs_exclusions_cpanel=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. SecRule &TX:crs_exclusions_cpanel|TX:crs_exclusions_cpanel "@eq 0" \ "id:9005000,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-CPANEL" SecRule &TX:crs_exclusions_cpanel|TX:crs_exclusions_cpanel "@eq 0" \ "id:9005001,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-CPANEL" # # [ cPanel whm-server-status ] # # Cpanel's WHM auto generates requests to /whm-server-status from # 127.0.0.1 (triggers rule 920280, non-blocking, log only) Once every 5 minutes. # These false positives have a low impact (logged, non-blocking) to a large number of users (all cPanel admins). # # # Rule to allow cPanel whm-server-status requests from localhost without log entry. # SecRule REQUEST_LINE "@rx ^GET /whm-server-status(?:/|/\?auto)? HTTP/[12]\.[01]$" \ "id:9005100,\ phase:1,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-apache',\ tag:'attack-generic',\ chain" SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ "t:none,\ ctl:ruleRemoveById=920280,\ ctl:ruleRemoveById=920350" SecMarker "END-CPANEL" modsecurity-crs-3.2.0/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf000066400000000000000000000372351355660542300243070ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # These exclusions remedy false positives in a default XenForo install. # The exclusions are only active if crs_exclusions_xenforo=1 is set. # See rule 900130 in crs-setup.conf.example for instructions. SecRule &TX:crs_exclusions_xenforo|TX:crs_exclusions_xenforo "@eq 0" \ "id:9006000,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-XENFORO" SecRule &TX:crs_exclusions_xenforo|TX:crs_exclusions_xenforo "@eq 0" \ "id:9006001,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-XENFORO" # # -=[ XenForo Front-End ]=- # # Proxy for images and remote content embedded in forum posts # GET /xf/proxy.php?image=https://example.com/some.jpg&hash=foo # GET /xf/proxy.php?link=https://example.com&hash=foo # POST /xf/proxy.php, body: referrer=... SecRule REQUEST_FILENAME "@endsWith /proxy.php" \ "id:9006100,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:image,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:link,\ ctl:ruleRemoveTargetById=931130;ARGS:referrer,\ ctl:ruleRemoveTargetById=942230;ARGS:referrer" # Store drafts for private message, forum post, thread reply # POST /xf/conversations/draft # POST /xf/conversations/convo-title.12345/draft # POST /xf/forums/forum-title.12345/draft # POST /xf/threads/thread-title-%E2%98%85.12345/draft # # attachment_hash_combined example: # {"type":"post","context":{"post_id":12345},"hash":"0123456789abcdef..."} SecRule REQUEST_FILENAME "@rx /(?:conversations|(?:conversations|forums|threads)/.*\.\d+)/draft$" \ "id:9006110,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931130;ARGS:href,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message_html,\ ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined" # Send PM, edit post, create thread, reply to thread # POST /xf/conversations/add # POST /xf/conversations/add-preview # POST /xf/conversations/messages/1463947/edit # POST /xf/posts/12345/edit # POST /xf/posts/12345/preview # POST /xf/conversations/convo-title.12345/add-reply # POST /xf/threads/thread-title.12345/add-reply # POST /xf/threads/thread-title.12345/reply-preview # POST /xf/forums/forum-title.12345/post-thread # POST /xf/forums/forum-title.12345/thread-preview SecRule REQUEST_FILENAME "@rx /(?:conversations/add(?:-preview)?|conversations/messages/\d+/edit|posts/\d+/(?:edit|preview)|(?:conversations|threads)/.*\.\d+/(?:add-reply|reply-preview)|forums/.*\.\d+/(?:post-thread|thread-preview))$" \ "id:9006120,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message_html,\ ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined" # Quote # POST /xf/posts/12345/quote SecRule REQUEST_FILENAME "@rx /posts/\d+/quote$" \ "id:9006130,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:quoteHtml" # Multi quote # POST /xf/conversations/convo-title.12345/multi-quote # POST /xf/threads/thread-title.12345/multi-quote # quotes={"12345":["quote-html"]} SecRule REQUEST_FILENAME "@rx /(?:conversations|threads)/.*\.\d+/multi-quote$" \ "id:9006140,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:quotes,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[0][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[1][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[2][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[3][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[4][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[5][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[6][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[7][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[8][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:insert[9][value]" # Delete thread SecRule REQUEST_FILENAME "@rx /threads/.*\.\d+/delete$" \ "id:9006150,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=942130;ARGS:starter_alert_reason" # Inline moderate thread # POST /xf/inline-mod/ SecRule REQUEST_FILENAME "@streq /inline-mod/" \ "id:9006160,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message" # Warn member # POST /xf/members/name.12345/warn SecRule REQUEST_FILENAME "@rx /members/\*\.\d+/warn$" \ "id:9006170,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:conversation_message,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:notes" # Editor SecRule REQUEST_URI "@endsWith /index.php?editor/to-html" \ "id:9006200,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:bb_code,\ ctl:ruleRemoveTargetById=942200;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942260;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942340;ARGS:attachment_hash_combined,\ ctl:ruleRemoveTargetById=942370;ARGS:attachment_hash_combined" # Editor SecRule REQUEST_URI "@endsWith /index.php?editor/to-bb-code" \ "id:9006210,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:html" # Post attachment # POST /xf/account/avatar # POST /xf/attachments/upload?type=post&context[thread_id]=12345&hash=foo SecRule REQUEST_FILENAME "@rx /(?:account/avatar|attachments/upload)$" \ "id:9006220,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveById=200003,\ ctl:ruleRemoveTargetById=942220;ARGS:flowChunkSize,\ ctl:ruleRemoveTargetById=942440;ARGS:flowIdentifier,\ ctl:ruleRemoveTargetById=942440;ARGS:flowFilename,\ ctl:ruleRemoveTargetById=942440;ARGS:flowRelativePath" # Media # POST /xf/index.php?editor/media SecRule REQUEST_URI "@endsWith /index.php?editor/media" \ "id:9006230,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931130;ARGS:url,\ ctl:ruleRemoveTargetById=942130;ARGS:url" # Emoji # GET /xf/index.php?misc/find-emoji&q=(%0A%0A SecRule REQUEST_URI "@rx /index\.php\?misc/find-emoji&q=" \ "id:9006240,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=921151;ARGS:q" # Login # POST /xf/login/login SecRule REQUEST_FILENAME "@endsWith /login/login" \ "id:9006300,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:password" # Register account # POST /xf/register/register # The password is passed in a variable-name form parameter. We don't # want to exclude all parameters completely as this would cause an # unacceptable bypass. So, we exclude only commonly hit rules. SecRule REQUEST_FILENAME "@endsWith /register/register" \ "id:9006310,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=942130;ARGS,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:reg_key" # Edit account # POST /xf/account/account-details SecRule REQUEST_FILENAME "@endsWith /account/account-details" \ "id:9006320,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931130;ARGS:custom_fields[picture],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:about_html" # Lost password # POST /xf/lost-password/user-name.12345/confirm?c=foo SecRule REQUEST_FILENAME "@rx /lost-password/.*\.\d+/confirm$" \ "id:9006330,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:c" # Set forum signature # POST /xf/account/signature SecRule REQUEST_FILENAME "@endsWith /account/signature" \ "id:9006340,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:signature_html" # Search # POST /xf/search/search SecRule REQUEST_FILENAME "@endsWith /search/search" \ "id:9006400,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:keywords,\ ctl:ruleRemoveTargetById=942200;ARGS:constraints,\ ctl:ruleRemoveTargetById=942260;ARGS:constraints,\ ctl:ruleRemoveTargetById=942340;ARGS:constraints,\ ctl:ruleRemoveTargetById=942370;ARGS:constraints" # Search within thread # GET /xf/threads/foo.12345/page12?highlight=foo SecRule REQUEST_FILENAME "@rx /threads/.*\.\d+/(?:page\d+)?$" \ "id:9006410,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:highlight" # Search within search result # GET /xf/search/12345/?q=foo SecRule REQUEST_FILENAME "@rx /search/\d+/$" \ "id:9006420,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:q" # Contact form # POST /xf/misc/contact SecRule REQUEST_FILENAME "@endsWith /misc/contact" \ "id:9006500,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:subject" # Report post # POST /xf/posts/12345/report SecRule REQUEST_FILENAME "@rx /posts/\d+/report$" \ "id:9006510,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message" # Alternate thread view route # /xf/index.php?threads/title-having-some-sql.12345/ # # Especially threads with the HAVING sql keyword are FP prone. # This rule has some chains to narrow down the exclusion, # making it harder for an attacker to abuse the ARGS_NAMES # exclusion on other endpoints. SecRule REQUEST_FILENAME "@endsWith /index.php" \ "id:9006600,\ phase:1,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_METHOD "@streq GET" \ "t:none,\ chain" SecRule &ARGS "@eq 1" \ "t:none,\ chain" SecRule REQUEST_URI "@rx /index\.php\?threads/.*\.\d+/$" \ "t:none,\ ctl:ruleRemoveTargetById=942100;ARGS_NAMES,\ ctl:ruleRemoveTargetById=942230;ARGS_NAMES" # Browser fingerprint (DBTech security extension) # May Contain various javascript/XSS false positives SecRule REQUEST_URI "@endsWith /index.php?dbtech-security/fingerprint" \ "id:9006700,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[14][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[15][value],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:components[16][value]" # Get location info SecRule REQUEST_FILENAME "@endsWith /misc/location-info" \ "id:9006710,\ phase:2,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:location" # # -=[ XenForo Global Exclusions ]=- # # _xfRedirect, _xfRequestUri can appear on various endpoints. # Cookies can appear on all endpoints. SecAction \ "id:9006800,\ phase:1,\ pass,\ t:none,\ nolog,\ ctl:ruleRemoveTargetById=931120;ARGS:_xfRedirect,\ ctl:ruleRemoveTargetById=941150;ARGS:_xfRedirect,\ ctl:ruleRemoveTargetById=931120;ARGS:_xfRequestUri,\ ctl:ruleRemoveTargetById=941150;ARGS:_xfRequestUri,\ ctl:ruleRemoveTargetById=942130;ARGS:_xfRequestUri,\ ctl:ruleRemoveTargetById=942230;ARGS:_xfRequestUri,\ ctl:ruleRemoveTargetById=942260;ARGS:_xfRequestUri,\ ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_csrf,\ ctl:ruleRemoveTargetById=942210;REQUEST_COOKIES:xf_csrf,\ ctl:ruleRemoveTargetById=942440;REQUEST_COOKIES:xf_csrf,\ ctl:ruleRemoveTargetById=942150;REQUEST_COOKIES:xf_emoji_usage,\ ctl:ruleRemoveTargetById=942410;REQUEST_COOKIES:xf_emoji_usage,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;REQUEST_COOKIES:xf_ls,\ ctl:ruleRemoveTargetById=942100;REQUEST_COOKIES:xf_user" # # -=[ XenForo Administration Back-End ]=- # # Skip this section for performance unless requested file is admin.php SecRule REQUEST_FILENAME "!@endsWith /admin.php" \ "id:9006900,\ phase:1,\ pass,\ t:none,\ nolog,\ skipAfter:END-XENFORO-ADMIN" SecRule REQUEST_FILENAME "!@endsWith /admin.php" \ "id:9006901,\ phase:2,\ pass,\ t:none,\ nolog,\ skipAfter:END-XENFORO-ADMIN" # Admin edit user # POST /xf/admin.php?users/the-user-name.12345/edit SecRule REQUEST_FILENAME "@endsWith /admin.php" \ "id:9006910,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_URI "@rx /admin\.php\?users/.*\.\d+/edit$" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[about],\ ctl:ruleRemoveTargetById=931130;ARGS:profile[website]" # Admin save user # POST /xf/admin.php?users/the-user-name.12345/save SecRule REQUEST_FILENAME "@endsWith /admin.php" \ "id:9006920,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_URI "@rx /admin\.php\?users/.*\.\d+/save$" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[occupation],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[personal_quote],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[about],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:profile[signature],\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:custom_fields[sexuality],\ ctl:ruleRemoveTargetById=931130;ARGS:custom_fields[picture],\ ctl:ruleRemoveTargetById=931130;ARGS:profile[website]" # Admin edit forum notice # POST /xf/admin.php?notices/0/save # POST /xf/admin.php?notices/forum-name.12345/save SecRule REQUEST_FILENAME "@endsWith /admin.php" \ "id:9006930,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_URI "@rx /admin\.php\?notices/(?:.*\.)?\d+/save$" \ "t:none,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:message,\ ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:title" # Admin batch thread update # POST /xf/admin.php?threads/batch-update/action SecRule REQUEST_FILENAME "@endsWith /admin.php" \ "id:9006940,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_URI "@rx /admin\.php\?threads/batch-update/action$" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:criteria,\ ctl:ruleRemoveTargetById=942260;ARGS:criteria,\ ctl:ruleRemoveTargetById=942330;ARGS:criteria,\ ctl:ruleRemoveTargetById=942340;ARGS:criteria,\ ctl:ruleRemoveTargetById=942370;ARGS:criteria" # Edit forum theme # POST /xf/admin.php?styles/title.1234/style-properties/group&group=basic SecRule REQUEST_FILENAME "@endsWith /admin.php" \ "id:9006950,\ phase:2,\ pass,\ t:none,\ nolog,\ chain" SecRule REQUEST_URI "@rx /admin\.php\?styles/" \ "t:none,\ ctl:ruleRemoveTargetById=942200;ARGS:json,\ ctl:ruleRemoveTargetById=942260;ARGS:json,\ ctl:ruleRemoveTargetById=942330;ARGS:json,\ ctl:ruleRemoveTargetById=942340;ARGS:json,\ ctl:ruleRemoveTargetById=942370;ARGS:json" SecMarker "END-XENFORO-ADMIN" SecMarker "END-XENFORO" modsecurity-crs-3.2.0/rules/REQUEST-905-COMMON-EXCEPTIONS.conf000066400000000000000000000027331355660542300227770ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # This file is used as an exception mechanism to remove common false positives # that may be encountered. # # Exception for Apache SSL pinger # SecRule REQUEST_LINE "@streq GET /" \ "id:905100,\ phase:1,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-apache',\ tag:'attack-generic',\ chain" SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ "t:none,\ ctl:ruleEngine=Off,\ ctl:auditEngine=Off" # # Exception for Apache internal dummy connection # SecRule REQUEST_LINE "@rx ^(?:GET /|OPTIONS \*) HTTP/[12]\.[01]$" \ "id:905110,\ phase:1,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-apache',\ tag:'attack-generic',\ chain" SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ "t:none,\ chain" SecRule REQUEST_HEADERS:User-Agent "@rx ^.*\(internal dummy connection\)$" \ "t:none,\ ctl:ruleEngine=Off,\ ctl:auditEngine=Off" modsecurity-crs-3.2.0/rules/REQUEST-910-IP-REPUTATION.conf000066400000000000000000000227401355660542300223240ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:910011,phase:1,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:910012,phase:2,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ IP Reputation Block Flag Check ]=- # # The first check we do is to see if the client IP address has already # been blacklisted by rules from previous requests. # # If the rule matches, it will do a skipAfter and pick up processing # at the end of the request phase for actual blocking. # SecRule TX:DO_REPUT_BLOCK "@eq 1" \ "id:910000,\ phase:2,\ block,\ t:none,\ msg:'Request from Known Malicious Client (Based on previous traffic violations).',\ logdata:'Previous Block Reason: %{ip.reput_block_reason}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ tag:'IP_REPUTATION/MALICIOUS_CLIENT',\ severity:'CRITICAL',\ chain,\ skipAfter:BEGIN-REQUEST-BLOCKING-EVAL" SecRule IP:REPUT_BLOCK_FLAG "@eq 1" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ GeoIP Checks ]=- # # This rule requires activating the SecGeoLookupDB directive # in the crs-setup.conf file and specifying # the list of blocked countries (tx.high_risk_country_codes). # # This rule does a GeoIP resolution on the client IP address. # SecRule TX:HIGH_RISK_COUNTRY_CODES "!@rx ^$" \ "id:910100,\ phase:2,\ block,\ t:none,\ msg:'Client IP is from a HIGH Risk Country Location.',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ severity:'CRITICAL',\ chain" SecRule TX:REAL_IP "@geoLookup" \ "chain" SecRule GEO:COUNTRY_CODE "@within %{tx.high_risk_country_codes}" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" # # -=[ IP Reputation Checks ]=- # # ModSecurity Rules from Trustwave SpiderLabs: IP Blacklist Alert # Ref: http://www.modsecurity.org/projects/commercial/rules/ # # This rule checks the client IP address against a list of recent IPs captured # from the SpiderLabs web honeypot systems (last 48 hours). # #SecRule TX:REAL_IP "@ipMatchFromFile ip_blacklist.data" \ # "id:910110,\ # phase:2,\ # block,\ # t:none,\ # msg:'Client IP in Trustwave SpiderLabs IP Reputation Blacklist.',\ # tag:'application-multi',\ # tag:'language-multi',\ # tag:'platform-multi',\ # tag:'attack-reputation-ip',\ # severity:'CRITICAL',\ # setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ # setvar:'ip.reput_block_flag=1',\ # setvar:'ip.reput_block_reason=%{rule.msg}',\ # expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" # # First check if we have already run an @rbl check for this IP by checking in IP collection. # If we have, then skip doing another check. # SecRule IP:PREVIOUS_RBL_CHECK "@eq 1" \ "id:910120,\ phase:2,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ skipAfter:END-RBL-LOOKUP" # # Check Client IP against ProjectHoneypot's HTTP Blacklist # Ref: http://www.projecthoneypot.org/httpbl_api.php # # To use the blacklist, you must register for an HttpBL API Key # and choose the traffic types to block. See section # "Project Honey Pot HTTP Blacklist" in crs-setup.conf. # # Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey # # Skip HttpBL checks if user has not defined one of the TX:block_* variables. # This prevents error "Operator error: RBL httpBl called but no key defined: set SecHttpBlKey" SecRule &TX:block_suspicious_ip "@eq 0" \ "id:910130,\ phase:2,\ pass,\ t:none,\ nolog,\ chain,\ skipAfter:END-RBL-CHECK" SecRule &TX:block_harvester_ip "@eq 0" \ "chain" SecRule &TX:block_spammer_ip "@eq 0" \ "chain" SecRule &TX:block_search_ip "@eq 0" SecRule TX:REAL_IP "@rbl dnsbl.httpbl.org" \ "id:910140,\ phase:2,\ pass,\ capture,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ setvar:'tx.httpbl_msg=%{tx.0}',\ chain" SecRule TX:httpbl_msg "@rx RBL lookup of .*?.dnsbl.httpbl.org succeeded at TX:checkip. (.*?): .*" \ "capture,\ t:none,\ setvar:'tx.httpbl_msg=%{tx.1}'" # The following regexs are generated based off re_operators.c SecRule TX:block_search_ip "@eq 1" \ "id:910150,\ phase:2,\ block,\ t:none,\ msg:'HTTP Blacklist match for search engine IP',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ severity:'CRITICAL',\ chain,\ skipAfter:END-RBL-CHECK" SecRule TX:httpbl_msg "@rx Search Engine" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ setvar:'ip.previous_rbl_check=1',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}',\ expirevar:'ip.previous_rbl_check=86400'" SecRule TX:block_spammer_ip "@eq 1" \ "id:910160,\ phase:2,\ block,\ t:none,\ msg:'HTTP Blacklist match for spammer IP',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ severity:'CRITICAL',\ chain,\ skipAfter:END-RBL-CHECK" SecRule TX:httpbl_msg "@rx (?i)^.*? spammer .*?$" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ setvar:'ip.previous_rbl_check=1',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}',\ expirevar:'ip.previous_rbl_check=86400'" SecRule TX:block_suspicious_ip "@eq 1" \ "id:910170,\ phase:2,\ block,\ t:none,\ msg:'HTTP Blacklist match for suspicious IP',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ severity:'CRITICAL',\ chain,\ skipAfter:END-RBL-CHECK" SecRule TX:httpbl_msg "@rx (?i)^.*? suspicious .*?$" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ setvar:'ip.previous_rbl_check=1',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}',\ expirevar:'ip.previous_rbl_check=86400'" SecRule TX:block_harvester_ip "@eq 1" \ "id:910180,\ phase:2,\ block,\ t:none,\ msg:'HTTP Blacklist match for harvester IP',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ severity:'CRITICAL',\ chain,\ skipAfter:END-RBL-CHECK" SecRule TX:httpbl_msg "@rx (?i)^.*? harvester .*?$" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ setvar:'ip.previous_rbl_check=1',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}',\ expirevar:'ip.previous_rbl_check=86400'" SecAction \ "id:910190,\ phase:2,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-ip',\ setvar:'ip.previous_rbl_check=1',\ expirevar:'ip.previous_rbl_check=86400'" SecMarker "END-RBL-LOOKUP" SecMarker "END-RBL-CHECK" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:910013,phase:1,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:910014,phase:2,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:910015,phase:1,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:910016,phase:2,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:910017,phase:1,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:910018,phase:2,pass,nolog,skipAfter:END-REQUEST-910-IP-REPUTATION" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-910-IP-REPUTATION" modsecurity-crs-3.2.0/rules/REQUEST-911-METHOD-ENFORCEMENT.conf000066400000000000000000000051711355660542300230470ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:911011,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:911012,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Allowed Request Methods ]=- # # tx.allowed_methods is defined in the crs-setup.conf file # SecRule REQUEST_METHOD "!@within %{tx.allowed_methods}" \ "id:911100,\ phase:2,\ block,\ msg:'Method is not allowed by policy',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-generic',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/POLICY/METHOD_NOT_ALLOWED',\ tag:'WASCTC/WASC-15',\ tag:'OWASP_TOP_10/A6',\ tag:'OWASP_AppSensor/RE1',\ tag:'PCI/12.1',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:911013,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:911014,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:911015,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:911016,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:911017,phase:1,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:911018,phase:2,pass,nolog,skipAfter:END-REQUEST-911-METHOD-ENFORCEMENT" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-911-METHOD-ENFORCEMENT" modsecurity-crs-3.2.0/rules/REQUEST-912-DOS-PROTECTION.conf000066400000000000000000000232051355660542300224340ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # Anti-Automation rules to detect Denial of Service attacks. # # Description of mechanics: # When a request hits a non-static resource (TX:STATIC_EXTENSIONS), then a counter for the IP # address is being raised (IP:DOS_COUNTER). If the counter (IP:DOS_COUNTER) hits a limit # (TX:DOS_COUNTER_THRESHOLD), then a burst is identified (IP:DOS_BURST_COUNTER) and the # counter (IP:DOS_COUNTER) is reset. The burst counter expires within a timeout period # (TX:DOS_BURST_TIME_SLICE). # If the burst counter (IP:DOS_BURST_COUNTER) is greater equal 2, then the blocking flag # is being set (IP:DOS_BLOCK). The blocking flag (IP:DOS_BLOCK) expires within a timeout # period (TX:DOS_BLOCK_TIMEOUT). All this counting happens in phase 5. # There is a stricter sibling to this rule (912170) in paranoia level 2, where the # burst counter check (IP:DOS_BURST_COUNTER) hits at greater equal 1. # # The blocking is done in phase 1: When the blocking flag is encountered (IP:DOS_BLOCK), # then the request is dropped without sending a response. If this happens, then a # counter is # raised (IP:DOS_BLOCK_COUNTER). # When an IP address is blocked for the first time, then the blocking is reported in a # message and a flag (IP:DOS_BLOCK_FLAG) is set. This flag expires in 60 seconds. # When an IP address is blocked and the flag (IP:DOS_BLOCK_FLAG) is set, then the # blocking is not being reported (to prevent a flood of alerts). When the flag # (IP:DOS_BLOCK_FLAG) has expired and a new request is being blocked, then the # counter (IP:DOS_BLOCK_COUNTER) is being reset to 0 and the block is being treated # as the first block (-> alert). # In order to be able to display the counter (IP:DOS_BLOCK_COUNTER) and resetting # it at the same time, we copy the counter (IP:DOS_BLOCK_COUNTER) into a different # variable (TX:DOS_BLOCK_COUNTER), which is then displayed in turn. # # Variables: # IP:DOS_BLOCK Flag if an IP address should be blocked # IP:DOS_BLOCK_COUNTER Counter of blocked requests # IP:DOS_BLOCK_FLAG Flag keeping track of alert. Flag expires after 60 seconds. # IP:DOS_BURST_COUNTER Burst counter # IP:DOS_COUNTER Request counter (static resources are ignored) # TX:DOS_BLOCK_COUNTER Copy of IP:DOS_BLOCK_COUNTER (needed for display reasons) # TX:DOS_BLOCK_TIMEOUT Period in seconds a blocked IP will be blocked # TX:DOS_COUNTER_THRESHOLD Limit of requests, where a burst is identified # TX:DOS_BURST_TIME_SLICE Period in seconds when we will forget a burst # TX:STATIC_EXTENSIONS Paths which can be ignored with regards to DoS # # As a precondition for these rules, please set the following three variables: # - TX:DOS_BLOCK_TIMEOUT # - TX:DOS_COUNTER_THRESHOLD # - TX:DOS_BURST_TIME_SLICE # # And make sure that TX:STATIC_EXTENSIONS is also set. # # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # # # Skip if variables defining DoS protection are not set # SecRule &TX:dos_burst_time_slice "@eq 0" \ "id:912100,\ phase:1,\ pass,\ t:none,\ nolog,\ chain,\ skipAfter:END-DOS-PROTECTION-CHECKS" SecRule &TX:dos_counter_threshold "@eq 0" \ "chain" SecRule &TX:dos_block_timeout "@eq 0" SecRule &TX:dos_burst_time_slice "@eq 0" \ "id:912110,\ phase:5,\ pass,\ t:none,\ nolog,\ chain,\ skipAfter:END-DOS-PROTECTION-CHECKS" SecRule &TX:dos_counter_threshold "@eq 0" \ "chain" SecRule &TX:dos_block_timeout "@eq 0" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:912011,phase:1,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:912012,phase:2,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Anti-Automation / DoS Protection : Block ]=- # # # Block and track # of requests and log # SecRule IP:DOS_BLOCK "@eq 1" \ "id:912120,\ phase:1,\ drop,\ msg:'Denial of Service (DoS) attack identified from %{tx.real_ip} (%{tx.dos_block_counter} hits since last alert)',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ chain" SecRule &IP:DOS_BLOCK_FLAG "@eq 0" \ "setvar:'ip.dos_block_counter=+1',\ setvar:'ip.dos_block_flag=1',\ setvar:'tx.dos_block_counter=%{ip.dos_block_counter}',\ setvar:'ip.dos_block_counter=0',\ expirevar:'ip.dos_block_flag=60'" # # Block and track # of requests but don't log # SecRule IP:DOS_BLOCK "@eq 1" \ "id:912130,\ phase:1,\ drop,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ setvar:'ip.dos_block_counter=+1'" # # -=[ Anti-Automation / DoS Protection: Count requests ]=- # # # Skip if we have blocked the request # SecRule IP:DOS_BLOCK "@eq 1" \ "id:912140,\ phase:5,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ skipAfter:END-DOS-PROTECTION-CHECKS" # # DOS Counter: Count the number of requests to non-static resources # SecRule REQUEST_BASENAME "@rx .*?(\.[a-z0-9]{1,10})?$" \ "id:912150,\ phase:5,\ pass,\ capture,\ t:none,t:lowercase,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ setvar:'tx.extension=/%{TX.1}/',\ chain" SecRule TX:EXTENSION "!@within %{tx.static_extensions}" \ "setvar:'ip.dos_counter=+1'" # # Check DOS Counter # If the request count is greater than or equal to user settings, # we raise the burst counter. This happens via two separate rules: # - 912160: raise from 0 to 1 # - 912161: raise from 1 to 2 # # This approach with two rules avoids raising the burst counter # from 0 to 2 via two concurrent requests. We do not raise the # burst counter beyond 2. # # SecRule IP:DOS_COUNTER "@ge %{tx.dos_counter_threshold}" \ "id:912160,\ phase:5,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ chain" SecRule &IP:DOS_BURST_COUNTER "@eq 0" \ "setvar:'ip.dos_burst_counter=1',\ setvar:'!ip.dos_counter',\ expirevar:'ip.dos_burst_counter=%{tx.dos_burst_time_slice}'" SecRule IP:DOS_COUNTER "@ge %{tx.dos_counter_threshold}" \ "id:912161,\ phase:5,\ pass,\ t:none,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ chain" SecRule &IP:DOS_BURST_COUNTER "@ge 1" \ "setvar:'ip.dos_burst_counter=2',\ setvar:'!ip.dos_counter',\ expirevar:'ip.dos_burst_counter=%{tx.dos_burst_time_slice}'" # # Check DOS Burst Counter and set Block # Check the burst counter - if greater than or equal to 2, then we set the IP # block variable for a given expiry and issue an alert. # SecRule IP:DOS_BURST_COUNTER "@ge 2" \ "id:912170,\ phase:5,\ pass,\ t:none,\ log,\ msg:'Potential Denial of Service (DoS) Attack from %{tx.real_ip} - # of Request Bursts: %{ip.dos_burst_counter}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ setvar:'ip.dos_block=1',\ expirevar:'ip.dos_block=%{tx.dos_block_timeout}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:912013,phase:1,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:912014,phase:2,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:912019,phase:5,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # # Check DOS Burst Counter and set Block # Check the burst counter - if greater than or equal to 1, then we set the IP # block variable for a given expiry and issue an alert. # # This is a stricter sibling of rule 912170. # SecRule IP:DOS_BURST_COUNTER "@ge 1" \ "id:912171,\ phase:5,\ pass,\ t:none,\ log,\ msg:'Potential Denial of Service (DoS) Attack from %{tx.real_ip} - # of Request Bursts: %{ip.dos_burst_counter}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-dos',\ tag:'paranoia-level/2',\ setvar:'ip.dos_block=1',\ expirevar:'ip.dos_block=%{tx.dos_block_timeout}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:912015,phase:1,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:912016,phase:2,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:912017,phase:1,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:912018,phase:2,pass,nolog,skipAfter:END-REQUEST-912-DOS-PROTECTION" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-912-DOS-PROTECTION" SecMarker "END-DOS-PROTECTION-CHECKS" modsecurity-crs-3.2.0/rules/REQUEST-913-SCANNER-DETECTION.conf000066400000000000000000000162001355660542300227260ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:913011,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:913012,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Vulnerability Scanner Checks ]=- # # These rules inspect the default User-Agent and Header values sent by # various commercial and open source vuln scanners. # # The following rules contain User-Agent lists: # 913100 - security scanners (data file scanners-user-agents.data) # 913101 - scripting/generic HTTP clients (data file scripting-user-agents.data) # 913102 - web crawlers/bots (data file crawlers-user-agents.data) # SecRule REQUEST_HEADERS:User-Agent "@pmFromFile scanners-user-agents.data" \ "id:913100,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Found User-Agent associated with security scanner',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-scanner',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/AUTOMATION/SECURITY_SCANNER',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" SecRule REQUEST_HEADERS_NAMES|REQUEST_HEADERS "@pmFromFile scanners-headers.data" \ "id:913110,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Found request header associated with security scanner',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-scanner',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/AUTOMATION/SECURITY_SCANNER',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" SecRule REQUEST_FILENAME|ARGS "@pmFromFile scanners-urls.data" \ "id:913120,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Found request filename/argument associated with security scanner',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-scanner',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/AUTOMATION/SECURITY_SCANNER',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:913013,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:913014,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # # -=[ Scripting/Generic User-Agents ]=- # # This rule detects user-agents associated with various HTTP client libraries # and scripting languages. Detection suggests attempted access by some # automated tool. # # This rule is a sibling of rule 913100. # SecRule REQUEST_HEADERS:User-Agent "@pmFromFile scripting-user-agents.data" \ "id:913101,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Found User-Agent associated with scripting/generic HTTP client',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-scripting',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/AUTOMATION/SCRIPTING',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" # # -=[ Crawler User-Agents ]=- # # This rule detects user-agents associated with various crawlers, SEO tools, # and bots, which have been reported to potentially misbehave. # These crawlers can have legitimate uses when used with authorization. # # This rule is a sibling of rule 913100. # SecRule REQUEST_HEADERS:User-Agent "@pmFromFile crawlers-user-agents.data" \ "id:913102,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Found User-Agent associated with web crawler/bot',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-reputation-crawler',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/AUTOMATION/CRAWLER',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}',\ setvar:'ip.reput_block_flag=1',\ setvar:'ip.reput_block_reason=%{rule.msg}',\ expirevar:'ip.reput_block_flag=%{tx.reput_block_duration}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:913015,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:913016,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:913017,phase:1,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:913018,phase:2,pass,nolog,skipAfter:END-REQUEST-913-SCANNER-DETECTION" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-913-SCANNER-DETECTION" modsecurity-crs-3.2.0/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf000066400000000000000000001342631355660542300233350ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # Some protocol violations are common in application layer attacks. # Validating HTTP requests eliminates a large number of application layer attacks. # # The purpose of this rules file is to enforce HTTP RFC requirements that state how # the client is supposed to interact with the server. # https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:920011,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:920012,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # Validate request line against the format specified in the HTTP RFC # # -=[ Rule Logic ]=- # # Uses rule negation against the regex for positive security. The regex specifies the proper # construction of URI request lines such as: # # "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] # # It also outlines proper construction for CONNECT, OPTIONS and GET requests. # # -=[ References ]=- # https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.1 # http://capec.mitre.org/data/definitions/272.html # SecRule REQUEST_LINE "!@rx ^(?i:(?:[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+)?)?/[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?|connect (?:\d{1,3}\.){3}\d{1,3}\.?(?::\d+)?|options \*)\s+[\w\./]+|get /[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?)$" \ "id:920100,\ phase:2,\ block,\ t:none,\ msg:'Invalid HTTP Request Line',\ logdata:'%{request_line}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ',\ tag:'CAPEC-272',\ ver:'OWASP_CRS/3.2.0',\ severity:'WARNING',\ setvar:'tx.anomaly_score_pl1=+%{tx.notice_anomaly_score}'" # # Identify multipart/form-data name evasion attempts # # There are possible impedance mismatches between how # ModSecurity interprets multipart file names and how # a destination app server such as PHP might parse the # Content-Disposition data: # # filename-parm := "filename" "=" value # # -=[ Rule Logic ]=- # These rules check for the existence of the ' " ; = meta-characters in # either the file or file name variables. # HTML entities may lead to false positives, why they are allowed on PL1. # Negative look behind assertions allow frequently used entities &_; # # -=[ Targets, characters and html entities ]=- # # 920120: PL1 : FILES_NAMES, FILES # ['\";=] but allowed: # &[aAoOuUyY]uml); &[aAeEiIoOuU]circ; &[eEiIoOuUyY]acute; # &[aAeEiIoOuU]grave; &[cC]cedil; &[aAnNoO]tilde; & ' # # 920121: PL2 : FILES_NAMES, FILES # ['\";=] : ' " ; = meta-characters # # Not supported by re2 (? /range/) is not matching the restricted header # /content-range/ for example. # # This is a chained rule, where the first rule fills a set of variables of the # form TX.header_name_. The second rule is then executed for all # variables of the form TX.header_name_. # # As a consequence of the construction of the rule, the alert message and the # alert data will not display the original header name Content-Range, but # /content-range/ instead. # # # -=[ References ]=- # https://access.redhat.com/security/vulnerabilities/httpoxy (Header Proxy) # SecRule REQUEST_HEADERS_NAMES "@rx ^.*$" \ "id:920450,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'HTTP header is restricted by policy (%{MATCHED_VAR})',\ logdata:'Restricted header detected: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/POLICY/HEADER_RESTRICTED',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/12.1',\ tag:'WASCTC/WASC-15',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/12.1',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.header_name_%{tx.0}=/%{tx.0}/',\ chain" SecRule TX:/^HEADER_NAME_/ "@within %{tx.restricted_headers}" \ "setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:920013,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:920014,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # # -=[ Rule Logic ]=- # # Check the number of range fields in the Range request header. # # An excessive number of Range request headers can be used to DoS a server. # The original CVE proposed an arbitrary upper limit of 5 range fields. # # Several clients are known to request PDF fields with up to 62 range # fields. Therefore the standard rule does not cover PDF files. This is # performed in two separate (stricter) siblings of this rule. # # 920200: PL2: Limit of 5 range header fields for all filenames outside of PDFs # 920201: PL2: Limit of 62 range header fields for PDFs # 920202: PL4: Limit of 5 range header fields for PDFs # # -=[ References ]=- # https://httpd.apache.org/security/CVE-2011-3192.txt SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?\-(?:\d+)?\s*,?\s*){6}" \ "id:920200,\ phase:2,\ block,\ t:none,\ msg:'Range: Too many fields (6 or more)',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'WARNING',\ chain" SecRule REQUEST_BASENAME "!@endsWith .pdf" \ "setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" # # This is a sibling of rule 920200 # SecRule REQUEST_BASENAME "@endsWith .pdf" \ "id:920201,\ phase:2,\ block,\ t:none,\ msg:'Range: Too many fields for pdf request (63 or more)',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'WARNING',\ chain" SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?\-(?:\d+)?\s*,?\s*){63}" \ "setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" SecRule ARGS "@rx %[0-9a-fA-F]{2}" \ "id:920230,\ phase:2,\ block,\ t:none,\ msg:'Multiple URL Encoding Detected',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'WARNING',\ setvar:'tx.anomaly_score_pl2=+%{tx.warning_anomaly_score}'" # # Missing Accept Header # # -=[ Rule Logic ]=- # This rule generates a notice if the Accept header is missing. # SecRule &REQUEST_HEADERS:Accept "@eq 0" \ "id:920300,\ phase:2,\ pass,\ t:none,\ msg:'Request Missing an Accept Header',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/MISSING_HEADER_ACCEPT',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'NOTICE',\ chain" SecRule REQUEST_METHOD "!@rx ^OPTIONS$" \ "chain" SecRule REQUEST_HEADERS:User-Agent "!@pm AppleWebKit Android" \ "t:none,\ setvar:'tx.anomaly_score_pl2=+%{tx.notice_anomaly_score}'" # # PL2: This is a stricter sibling of 920270. # SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@validateByteRange 9,10,13,32-126,128-255" \ "id:920271,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request (non printable characters)',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # # Missing User-Agent Header # # -=[ Rule Logic ]=- # This rules will check to see if there is a User-Agent header or not. # SecRule &REQUEST_HEADERS:User-Agent "@eq 0" \ "id:920320,\ phase:2,\ pass,\ t:none,\ msg:'Missing User Agent Header',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/MISSING_HEADER_UA',\ tag:'WASCTC/WASC-21',\ tag:'OWASP_TOP_10/A7',\ tag:'PCI/6.5.10',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'NOTICE',\ setvar:'tx.anomaly_score_pl2=+%{tx.notice_anomaly_score}'" # # PL2: This is a stricter sibling of 920120. # SecRule FILES_NAMES|FILES "@rx ['\";=]" \ "id:920121,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Attempted multipart/form-data bypass',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_REQ',\ tag:'CAPEC-272',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # # PL2: Block on Missing Content-Type Header with Request Body # This is a stricter sibling of rule 920340. # # -=[ References ]=- # http://httpwg.org/specs/rfc7231.html#header.content-type SecRule REQUEST_HEADERS:Content-Length "!@rx ^0$" \ "id:920341,\ phase:2,\ block,\ t:none,\ msg:'Request Containing Content Requires Content-Type header',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'paranoia-level/2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ chain" SecRule &REQUEST_HEADERS:Content-Type "@eq 0" \ "t:none,\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:920015,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:920016,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # # # PL 3: This is a stricter sibling of 920270. Ascii range: Printable characters in the low range # # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 32-36,38-126" \ "id:920272,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request (outside of printable chars below ascii 127)',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # PL3: The little known x-up-devcap-post-charset request header can be used to submit # a request with a different encoding as an alternative to the charset parameter in # the Content-Type header. This can be used to circumvent charset restrictions on # the Content-Type header in ASP.NET. # Note that this only works in combination with a User-Agent prefix. # # This rule is based on a blog post by Soroush Dalili at # https://soroush.secproject.com/blog/2019/05/x-up-devcap-post-charset-header-in-aspnet-to-bypass-wafs-again/ # SecRule &REQUEST_HEADERS:x-up-devcap-post-charset "@ge 1" \ "id:920490,\ phase:1,\ block,\ t:none,\ msg:'Request header x-up-devcap-post-charset detected in combination with prefix \'UP\' to User-Agent',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'language-aspnet',\ tag:'platform-windows',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/3',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ chain" SecRule REQUEST_HEADERS:User-Agent "@rx ^(?i)up" \ "t:none,\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:920017,phase:1,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:920018,phase:2,pass,nolog,skipAfter:END-REQUEST-920-PROTOCOL-ENFORCEMENT" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # This is a stricter sibling of rule 920200 # SecRule REQUEST_BASENAME "@endsWith .pdf" \ "id:920202,\ phase:2,\ block,\ t:none,\ msg:'Range: Too many fields for pdf request (6 or more)',\ logdata:'%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/INVALID_HREQ',\ tag:'paranoia-level/4',\ ver:'OWASP_CRS/3.2.0',\ severity:'WARNING',\ chain" SecRule REQUEST_HEADERS:Range|REQUEST_HEADERS:Request-Range "@rx ^bytes=(?:(?:\d+)?\-(?:\d+)?\s*,?\s*){6}" \ "setvar:'tx.anomaly_score_pl4=+%{tx.warning_anomaly_score}'" # # This is a stricter sibling of 920270. # # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # SecRule ARGS|ARGS_NAMES|REQUEST_BODY "@validateByteRange 38,44-46,48-58,61,65-90,95,97-122" \ "id:920273,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request (outside of very strict set)',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/4',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # This is a stricter sibling of 920270. # SecRule REQUEST_HEADERS|!REQUEST_HEADERS:User-Agent|!REQUEST_HEADERS:Referer|!REQUEST_HEADERS:Cookie|!REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,65-90,95,97-122" \ "id:920274,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request headers (outside of very strict set)',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/4',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # This is a stricter sibling of 920270. # The 'Sec-Fetch-User' header may contain the '?' (63) character. # Therefore we exclude this header from rule 920274 which forbids '?'. # https://www.w3.org/TR/fetch-metadata/#http-headerdef-sec-fetch-user # SecRule REQUEST_HEADERS:Sec-Fetch-User "@validateByteRange 32,34,38,42-59,61,63,65-90,95,97-122" \ "id:920275,\ phase:2,\ block,\ t:none,t:urlDecodeUni,\ msg:'Invalid character in request headers (outside of very strict set)',\ logdata:'%{MATCHED_VAR_NAME}=%{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/PROTOCOL_VIOLATION/EVASION',\ tag:'paranoia-level/4',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # -=[ Abnormal Character Escapes ]=- # # [ Rule Logic ] # Consider the following payload: arg=cat+/e\tc/pa\ssw\d # Here, \s and \d were only used to obfuscate the string passwd and a lot of # parsers will silently ignore the non-necessary escapes. The case with \t is # a bit different though, as \t is a natural escape for the TAB character, # so we will avoid this (and \n, \r, etc.). # # This rule aims to detect non-necessary, abnormal escapes. You could say it is # a nice way to forbid the backslash character where it is not needed. # # This is a new rule at paranoia level 4. We expect quite a few false positives # for this rule and we will later evaluate if the rule makes any sense at all. # The rule is redundant with 920273 and 920274 in PL4. But if the rule proofs # to be useful and false positives remain at a reasonable level, then it might # be shifted to PL3 in a future release, where it would be the only rule # covering the backslash escape. # # We forbid backslashes followed by a list of basic ascii characters - unless # the backslash is preceded by another backslash. # # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # SecRule REQUEST_URI|REQUEST_HEADERS|ARGS|ARGS_NAMES "@rx (?:^|[^\\\\])\\\\[cdeghijklmpqwxyz123456789]" \ "id:920460,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ log,\ msg:'Abnormal character escapes in request',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'paranoia-level/4',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl4=+%{tx.critical_anomaly_score}'" # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-920-PROTOCOL-ENFORCEMENT" modsecurity-crs-3.2.0/rules/REQUEST-921-PROTOCOL-ATTACK.conf000066400000000000000000000253301355660542300225320ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:921011,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:921012,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ HTTP Request Smuggling ]=- # # [ Rule Logic ] # This rule looks for a CR/LF character in combination with a HTTP / WEBDAV method name. # This would point to an attempt to inject a 2nd request into the request, thus bypassing # tests carried out on the primary request. # # [ References ] # http://projects.webappsec.org/HTTP-Request-Smuggling # SecRule ARGS_NAMES|ARGS|XML:/* "@rx [\n\r]+(?:get|post|head|options|connect|put|delete|trace|track|patch|propfind|propatch|mkcol|copy|move|lock|unlock)\s+[^\s]+(?:\s+http|[\r\n])" \ "id:921110,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Request Smuggling Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/REQUEST_SMUGGLING',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ HTTP Response Splitting ]=- # # [ Rule Logic ] # These rules look for Carriage Return (CR) %0d and Linefeed (LF) %0a characters. # These characters may cause problems if the data is returned in a respones header and # may be interpreted by an intermediary proxy server and treated as two separate # responses. # # [ References ] # http://projects.webappsec.org/HTTP-Response-Splitting # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx [\r\n]\W*?(?:content-(?:type|length)|set-cookie|location):" \ "id:921120,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:lowercase,\ msg:'HTTP Response Splitting Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RESPONSE_SPLITTING',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\bhttp\/(?:0\.9|1\.[01])|<(?:html|meta)\b)" \ "id:921130,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Response Splitting Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RESPONSE_SPLITTING',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ HTTP Header Injection ]=- # # [ Rule Logic ] # These rules look for Carriage Return (CR) %0d and Linefeed (LF) %0a characters, # on their own or in combination with header field names. # These characters may cause problems if the data is returned in a respones header # and interpreted by the client. # The rules are similar to rules defending against the HTTP Request Splitting and # Request Smuggling rules. # # [ References ] # https://en.wikipedia.org/wiki/HTTP_header_injection # SecRule REQUEST_HEADERS_NAMES|REQUEST_HEADERS "@rx [\n\r]" \ "id:921140,\ phase:2,\ block,\ capture,\ t:none,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Header Injection Attack via headers',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/HEADER_INJECTION',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Detect newlines in argument names. # Checking for GET arguments has been moved to paranoia level 2 (921151) # in order to mitigate possible false positives. # # This rule is also triggered by the following exploit(s): # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # SecRule ARGS_NAMES "@rx [\n\r]" \ "id:921150,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,\ msg:'HTTP Header Injection Attack via payload (CR/LF detected)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/HEADER_INJECTION',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS_GET_NAMES|ARGS_GET "@rx (?:\n|\r)+(?:\s|location|refresh|(?:set-)?cookie|(?:x-)?(?:forwarded-(?:for|host|server)|host|via|remote-ip|remote-addr|originating-IP))\s*:" \ "id:921160,\ phase:1,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase,\ msg:'HTTP Header Injection Attack via payload (CR/LF and header-name detected)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/HEADER_INJECTION',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:921013,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:921014,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # Detect newlines in GET argument values. # These may point to a HTTP header injection attack, but can also sometimes # occur in benign query parameters. # # See also: rule 921140, 921150 # SecRule ARGS_GET "@rx [\n\r]" \ "id:921151,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:htmlEntityDecode,\ msg:'HTTP Header Injection Attack via payload (CR/LF detected)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'paranoia-level/2',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/HEADER_INJECTION',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:921015,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:921016,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # # # -=[ HTTP Parameter Polution ]=- # # [ Rule Logic ] # These rules look for multiple parameters with the same name. # 921170 counts the occurrences of the individual parameters. # 921180 checks if any counter is > 1. # # One HPP attack vector is to try evade signature filters by distributing the # attack payload across multiple parameters with the same name. # This works as many security devices only apply signatures to individual # parameter payloads, however the back-end web application may (in the case # of ASP.NET) consolidate all of the payloads into one thus making the # attack payload active. # # [ References ] # http://tacticalwebappsec.blogspot.com/2009/05/http-parameter-pollution.html # https://capec.mitre.org/data/definitions/460.html # SecRule ARGS_NAMES "@rx ." \ "id:921170,\ phase:2,\ pass,\ nolog,\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'paranoia-level/3',\ tag:'CAPEC-460',\ ver:'OWASP_CRS/3.2.0',\ setvar:'TX.paramcounter_%{MATCHED_VAR_NAME}=+1'" SecRule TX:/paramcounter_.*/ "@gt 1" \ "id:921180,\ phase:2,\ pass,\ msg:'HTTP Parameter Pollution (%{TX.1})',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-protocol',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/HTTP_PARAMETER_POLLUTION',\ tag:'paranoia-level/3',\ tag:'CAPEC-460',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ chain" SecRule MATCHED_VARS_NAMES "@rx TX:paramcounter_(.*)" \ "capture,\ setvar:'tx.http_violation_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:921017,phase:1,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:921018,phase:2,pass,nolog,skipAfter:END-REQUEST-921-PROTOCOL-ATTACK" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-921-PROTOCOL-ATTACK" modsecurity-crs-3.2.0/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf000066400000000000000000000136021355660542300234430ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:930011,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:930012,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Directory Traversal Attacks ]=- # # Ref: https://github.com/wireghoul/dotdotpwn # # [ Encoded /../ Payloads ] # SecRule REQUEST_URI_RAW|REQUEST_BODY|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|XML:/* "@rx (?i)(?:\x5c|(?:%(?:c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|2(?:5(?:c(?:0%25af|1%259c)|2f|5c)|%46|f)|(?:(?:f(?:8%8)?0%8|e)0%80%a|bg%q)f|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|u(?:221[56]|002f|EFC8|F025)|1u|5c)|0x(?:2f|5c)|\/))(?:%(?:(?:f(?:(?:c%80|8)%8)?0%8|e)0%80%ae|2(?:(?:5(?:c0%25a|2))?e|%45)|u(?:(?:002|ff0)e|2024)|%32(?:%(?:%6|4)5|E)|c0(?:%[256aef]e|\.))|\.(?:%0[01]|\?)?|\?\.?|0x2e){2}(?:\x5c|(?:%(?:c(?:0%(?:[2aq]f|5c|9v)|1%(?:[19p]c|8s|af))|2(?:5(?:c(?:0%25af|1%259c)|2f|5c)|%46|f)|(?:(?:f(?:8%8)?0%8|e)0%80%a|bg%q)f|%3(?:2(?:%(?:%6|4)6|F)|5%%63)|u(?:221[56]|002f|EFC8|F025)|1u|5c)|0x(?:2f|5c)|\/))" \ "id:930100,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Path Traversal Attack (/../)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-lfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}'" # # [ Decoded /../ Payloads ] # SecRule REQUEST_URI|REQUEST_BODY|REQUEST_HEADERS|!REQUEST_HEADERS:Referer|XML:/* "@rx (?:^|[\\/])\.\.(?:[\\/]|$)" \ "id:930110,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine,\ msg:'Path Traversal Attack (/../)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-lfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/DIR_TRAVERSAL',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ multiMatch,\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}',\ setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}'" # # -=[ OS File Access ]=- # # Ref: https://github.com/lightos/Panoptic/blob/master/cases.xml # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile lfi-os-files.data" \ "id:930120,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,\ msg:'OS File Access Attempt',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-lfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/FILE_INJECTION',\ tag:'WASCTC/WASC-33',\ tag:'OWASP_TOP_10/A4',\ tag:'PCI/6.5.4',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ Restricted File Access ]=- # # Detects attempts to retrieve application source code, metadata, # credentials and version control history possibly reachable in a web root. # SecRule REQUEST_FILENAME "@pmFromFile restricted-files.data" \ "id:930130,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:normalizePathWin,t:lowercase,\ msg:'Restricted File Access Attempt',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-lfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/FILE_INJECTION',\ tag:'WASCTC/WASC-33',\ tag:'OWASP_TOP_10/A4',\ tag:'PCI/6.5.4',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:930013,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:930014,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:930015,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:930016,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:930017,phase:1,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:930018,phase:2,pass,nolog,skipAfter:END-REQUEST-930-APPLICATION-ATTACK-LFI" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-930-APPLICATION-ATTACK-LFI" modsecurity-crs-3.2.0/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf000066400000000000000000000127321355660542300234550ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # RFI Attacks # # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:931011,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:931012,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # -=[ Rule Logic ]=- # These rules look for common types of Remote File Inclusion (RFI) attack methods. # - URL Contains an IP Address # - The PHP "include()" Function # - RFI Data Ends with Question Mark(s) (?) # - RFI Host Doesn't Match Local Host # # -=[ References ]=- # http://projects.webappsec.org/Remote-File-Inclusion # http://tacticalwebappsec.blogspot.com/2009/06/generic-remote-file-inclusion-attack.html # SecRule ARGS "@rx ^(?i:file|ftps?|https?):\/\/(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" \ "id:931100,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Possible Remote File Inclusion (RFI) Attack: URL Parameter using IP Address',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-rfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RFI',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule QUERY_STRING|REQUEST_BODY "@rx (?i)(?:\binclude\s*\([^)]*|mosConfig_absolute_path|_CONF\[path\]|_SERVER\[DOCUMENT_ROOT\]|GALLERY_BASEDIR|path\[docroot\]|appserv_root|config\[root_dir\])=(?:file|ftps?|https?):\/\/" \ "id:931110,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,\ msg:'Possible Remote File Inclusion (RFI) Attack: Common RFI Vulnerable Parameter Name used w/URL Payload',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-rfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RFI',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS "@rx ^(?i:file|ftps?|https?).*?\?+$" \ "id:931120,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Possible Remote File Inclusion (RFI) Attack: URL Payload Used w/Trailing Question Mark Character (?)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-rfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RFI',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:931013,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:931014,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule ARGS "@rx ^(?i:file|ftps?|https?)://(.*)$" \ "id:931130,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Possible Remote File Inclusion (RFI) Attack: Off-Domain Reference/Link',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-rfi',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/RFI',\ tag:'paranoia-level/2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rfi_parameter_%{MATCHED_VAR_NAME}=%{tx.1}',\ chain" SecRule TX:/rfi_parameter_.*/ "!@beginsWith %{request_headers.host}" \ "setvar:'tx.rfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:931015,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:931016,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:931017,phase:1,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:931018,phase:2,pass,nolog,skipAfter:END-REQUEST-931-APPLICATION-ATTACK-RFI" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-931-APPLICATION-ATTACK-RFI" modsecurity-crs-3.2.0/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf000066400000000000000000001513211355660542300234450ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:932011,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:932012,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # [ Unix command injection ] # # This rule detects Unix command injections. # A command injection takes a form such as: # # foo.jpg;uname -a # foo.jpg||uname -a # # The vulnerability exists when an application executes a shell command # without proper input escaping/validation. # # This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: # [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] # # To prevent false positives, we look for a 'starting sequence' that # precedes a command in shell syntax, such as: ; | & $( ` <( >( # Anatomy of the regexp with examples of patterns caught: # # 1. Starting tokens # # ; ;ifconfig # \{ {ifconfig} # \| |ifconfig # \|\| ||ifconfig # & &ifconfig # && &&ifconfig # \n ;\nifconfig # \r ;\rifconfig # \$\( $(ifconfig) # $\(\( $((ifconfig)) # ` `ifconfig` # \${ ${ifconfig} # <\( <( ifconfig ) # >\( >( ifconfig ) # \(\s*\) a() ( ifconfig; ); a # # 2. Command prefixes # # { { ifconfig } # \s*\(\s* ( ifconfig ) # \w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+ VARNAME=xyz ifconfig # !\s* ! ifconfig # \$ $ifconfig # # 3. Quoting # # ' 'ifconfig' # \" "ifconfig" # # 4. Paths # # [\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/ /sbin/ifconfig, /s?in/./ifconfig, /s[a-b]in/ifconfig etc. # # This rule is case-sensitive to prevent FP ("Cat" vs. "cat"). # # An effort was made to combat evasions by shell quoting (e.g. 'ls', # 'l'"s", \l\s are all valid). ModSecurity has a t:cmdLine # transformation built-in to deal with this, but unfortunately, it # replaces ';' characters and lowercases the payload, which is less # useful for this case. However, emulating the transformation makes # the regexp more complex. # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932100.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]* # [regexp assembled from util/regexp-assemble/regexp-932100.txt] # \b" \ # # This is the base Rule to prevent Unix Command Injection # Please refer other rules 932105,932106 to know more. # # .932100 # ├── 932105 # ├── 932106 # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]*(?:l[\\\\'\"]*(?:w[\\\\'\"]*p[\\\\'\"]*-[\\\\'\"]*(?:d[\\\\'\"]*(?:o[\\\\'\"]*w[\\\\'\"]*n[\\\\'\"]*l[\\\\'\"]*o[\\\\'\"]*a[\\\\'\"]*d|u[\\\\'\"]*m[\\\\'\"]*p)|r[\\\\'\"]*e[\\\\'\"]*q[\\\\'\"]*u[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*t|m[\\\\'\"]*i[\\\\'\"]*r[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*r)|s(?:[\\\\'\"]*(?:b[\\\\'\"]*_[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*l[\\\\'\"]*e[\\\\'\"]*a[\\\\'\"]*s[\\\\'\"]*e|c[\\\\'\"]*p[\\\\'\"]*u|m[\\\\'\"]*o[\\\\'\"]*d|p[\\\\'\"]*c[\\\\'\"]*i|u[\\\\'\"]*s[\\\\'\"]*b|-[\\\\'\"]*F|h[\\\\'\"]*w|o[\\\\'\"]*f))?|z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|m[\\\\'\"]*(?:o[\\\\'\"]*r[\\\\'\"]*e|a)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s)|e[\\\\'\"]*s[\\\\'\"]*s[\\\\'\"]*(?:(?:f[\\\\'\"]*i[\\\\'\"]*l|p[\\\\'\"]*i[\\\\'\"]*p)[\\\\'\"]*e|e[\\\\'\"]*c[\\\\'\"]*h[\\\\'\"]*o|(?:\s|<|>).*)|a[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*(?:l[\\\\'\"]*o[\\\\'\"]*g(?:[\\\\'\"]*i[\\\\'\"]*n)?|c[\\\\'\"]*o[\\\\'\"]*m[\\\\'\"]*m|(?:\s|<|>).*)|o[\\\\'\"]*(?:c[\\\\'\"]*a[\\\\'\"]*(?:t[\\\\'\"]*e|l)[\\\\'\"]*(?:\s|<|>).*|g[\\\\'\"]*n[\\\\'\"]*a[\\\\'\"]*m[\\\\'\"]*e)|d[\\\\'\"]*(?:c[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*f[\\\\'\"]*i[\\\\'\"]*g|d[\\\\'\"]*(?:\s|<|>).*)|f[\\\\'\"]*t[\\\\'\"]*p(?:[\\\\'\"]*g[\\\\'\"]*e[\\\\'\"]*t)?|(?:[np]|y[\\\\'\"]*n[\\\\'\"]*x)[\\\\'\"]*(?:\s|<|>).*)|b[\\\\'\"]*(?:z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e|c[\\\\'\"]*a[\\\\'\"]*t|i[\\\\'\"]*p[\\\\'\"]*2)|s[\\\\'\"]*d[\\\\'\"]*(?:c[\\\\'\"]*a[\\\\'\"]*t|i[\\\\'\"]*f[\\\\'\"]*f|t[\\\\'\"]*a[\\\\'\"]*r)|a[\\\\'\"]*(?:t[\\\\'\"]*c[\\\\'\"]*h[\\\\'\"]*(?:\s|<|>).*|s[\\\\'\"]*h)|r[\\\\'\"]*e[\\\\'\"]*a[\\\\'\"]*k[\\\\'\"]*s[\\\\'\"]*w|u[\\\\'\"]*i[\\\\'\"]*l[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*n)|c[\\\\'\"]*(?:o[\\\\'\"]*(?:m[\\\\'\"]*(?:p[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*a[\\\\'\"]*n[\\\\'\"]*d)[\\\\'\"]*(?:\s|<|>).*|p[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*c)|h[\\\\'\"]*(?:d[\\\\'\"]*i[\\\\'\"]*r[\\\\'\"]*(?:\s|<|>).*|f[\\\\'\"]*l[\\\\'\"]*a[\\\\'\"]*g[\\\\'\"]*s|a[\\\\'\"]*t[\\\\'\"]*t[\\\\'\"]*r|m[\\\\'\"]*o[\\\\'\"]*d)|r[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*t[\\\\'\"]*a[\\\\'\"]*b|(?:[cp]|a[\\\\'\"]*t)[\\\\'\"]*(?:\s|<|>).*|u[\\\\'\"]*r[\\\\'\"]*l|s[\\\\'\"]*h)|f[\\\\'\"]*(?:i(?:[\\\\'\"]*(?:l[\\\\'\"]*e[\\\\'\"]*(?:t[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*t|(?:\s|<|>).*)|n[\\\\'\"]*d[\\\\'\"]*(?:\s|<|>).*))?|t[\\\\'\"]*p[\\\\'\"]*(?:s[\\\\'\"]*t[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*s|w[\\\\'\"]*h[\\\\'\"]*o|(?:\s|<|>).*)|u[\\\\'\"]*n[\\\\'\"]*c[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*o[\\\\'\"]*n|(?:e[\\\\'\"]*t[\\\\'\"]*c[\\\\'\"]*h|c)[\\\\'\"]*(?:\s|<|>).*|o[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*h|g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p)|e[\\\\'\"]*(?:n[\\\\'\"]*(?:v(?:[\\\\'\"]*-[\\\\'\"]*u[\\\\'\"]*p[\\\\'\"]*d[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*e)?|d[\\\\'\"]*(?:i[\\\\'\"]*f|s[\\\\'\"]*w))|x[\\\\'\"]*(?:p[\\\\'\"]*(?:a[\\\\'\"]*n[\\\\'\"]*d|o[\\\\'\"]*r[\\\\'\"]*t|r)|e[\\\\'\"]*c[\\\\'\"]*(?:\s|<|>).*)|c[\\\\'\"]*h[\\\\'\"]*o[\\\\'\"]*(?:\s|<|>).*|g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|s[\\\\'\"]*a[\\\\'\"]*c|v[\\\\'\"]*a[\\\\'\"]*l)|h[\\\\'\"]*(?:t[\\\\'\"]*(?:d[\\\\'\"]*i[\\\\'\"]*g[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*t|p[\\\\'\"]*a[\\\\'\"]*s[\\\\'\"]*s[\\\\'\"]*w[\\\\'\"]*d)|o[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*(?:n[\\\\'\"]*a[\\\\'\"]*m[\\\\'\"]*e|i[\\\\'\"]*d)|(?:e[\\\\'\"]*a[\\\\'\"]*d|u[\\\\'\"]*p)[\\\\'\"]*(?:\s|<|>).*|i[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*y)|i[\\\\'\"]*(?:p[\\\\'\"]*(?:(?:6[\\\\'\"]*)?t[\\\\'\"]*a[\\\\'\"]*b[\\\\'\"]*l[\\\\'\"]*e[\\\\'\"]*s|c[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*f[\\\\'\"]*i[\\\\'\"]*g)|r[\\\\'\"]*b(?:[\\\\'\"]*(?:1(?:[\\\\'\"]*[89])?|2[\\\\'\"]*[012]))?|f[\\\\'\"]*c[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*f[\\\\'\"]*i[\\\\'\"]*g|d[\\\\'\"]*(?:\s|<|>).*)|g[\\\\'\"]*(?:(?:e[\\\\'\"]*t[\\\\'\"]*f[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*l|r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*c|i[\\\\'\"]*t)[\\\\'\"]*(?:\s|<|>).*|z[\\\\'\"]*(?:c[\\\\'\"]*a[\\\\'\"]*t|i[\\\\'\"]*p)|u[\\\\'\"]*n[\\\\'\"]*z[\\\\'\"]*i[\\\\'\"]*p|d[\\\\'\"]*b)|a[\\\\'\"]*(?:(?:l[\\\\'\"]*i[\\\\'\"]*a[\\\\'\"]*s|w[\\\\'\"]*k)[\\\\'\"]*(?:\s|<|>).*|d[\\\\'\"]*d[\\\\'\"]*u[\\\\'\"]*s[\\\\'\"]*e[\\\\'\"]*r|p[\\\\'\"]*t[\\\\'\"]*-[\\\\'\"]*g[\\\\'\"]*e[\\\\'\"]*t|r[\\\\'\"]*(?:c[\\\\'\"]*h[\\\\'\"]*(?:\s|<|>).*|p))|d[\\\\'\"]*(?:h[\\\\'\"]*c[\\\\'\"]*l[\\\\'\"]*i[\\\\'\"]*e[\\\\'\"]*n[\\\\'\"]*t|(?:i[\\\\'\"]*f[\\\\'\"]*f|u)[\\\\'\"]*(?:\s|<|>).*|(?:m[\\\\'\"]*e[\\\\'\"]*s|p[\\\\'\"]*k)[\\\\'\"]*g|o[\\\\'\"]*(?:a[\\\\'\"]*s|n[\\\\'\"]*e)|a[\\\\'\"]*s[\\\\'\"]*h)|m[\\\\'\"]*(?:(?:k[\\\\'\"]*d[\\\\'\"]*i[\\\\'\"]*r|o[\\\\'\"]*r[\\\\'\"]*e)[\\\\'\"]*(?:\s|<|>).*|a[\\\\'\"]*i[\\\\'\"]*l[\\\\'\"]*(?:x[\\\\'\"]*(?:\s|<|>).*|q)|l[\\\\'\"]*o[\\\\'\"]*c[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*e)|j[\\\\'\"]*(?:(?:a[\\\\'\"]*v[\\\\'\"]*a|o[\\\\'\"]*b[\\\\'\"]*s)[\\\\'\"]*(?:\s|<|>).*|e[\\\\'\"]*x[\\\\'\"]*e[\\\\'\"]*c)|k[\\\\'\"]*i[\\\\'\"]*l[\\\\'\"]*l[\\\\'\"]*(?:a[\\\\'\"]*l[\\\\'\"]*l|(?:\s|<|>).*)|(?:G[\\\\'\"]*E[\\\\'\"]*T[\\\\'\"]*(?:\s|<|>)|\.\s).*|7[\\\\'\"]*z(?:[\\\\'\"]*[ar])?)\b" \ "id:932100,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Unix Command Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Apache 2.2 requires configuration file lines to be under 8kB. # Therefore, some remaining commands have been split off to a separate rule. # For explanation of this rule, see rule 932100. # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932105.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]* # [regexp assembled from util/regexp-assemble/regexp-932105.txt] # \b" \ # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]*(?:s[\\\\'\"]*(?:e[\\\\'\"]*(?:t[\\\\'\"]*(?:(?:f[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*l[\\\\'\"]*)?(?:\s|<|>).*|e[\\\\'\"]*n[\\\\'\"]*v|s[\\\\'\"]*i[\\\\'\"]*d)|n[\\\\'\"]*d[\\\\'\"]*m[\\\\'\"]*a[\\\\'\"]*i[\\\\'\"]*l|d[\\\\'\"]*(?:\s|<|>).*)|h[\\\\'\"]*(?:\.[\\\\'\"]*d[\\\\'\"]*i[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*r[\\\\'\"]*i[\\\\'\"]*b|u[\\\\'\"]*t[\\\\'\"]*d[\\\\'\"]*o[\\\\'\"]*w[\\\\'\"]*n|(?:\s|<|>).*)|o[\\\\'\"]*(?:(?:u[\\\\'\"]*r[\\\\'\"]*c[\\\\'\"]*e|r[\\\\'\"]*t)[\\\\'\"]*(?:\s|<|>).*|c[\\\\'\"]*a[\\\\'\"]*t)|c[\\\\'\"]*(?:h[\\\\'\"]*e[\\\\'\"]*d|p[\\\\'\"]*(?:\s|<|>).*)|t[\\\\'\"]*r[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*g[\\\\'\"]*s|(?:l[\\\\'\"]*e[\\\\'\"]*e|f[\\\\'\"]*t)[\\\\'\"]*p|y[\\\\'\"]*s[\\\\'\"]*c[\\\\'\"]*t[\\\\'\"]*l|u[\\\\'\"]*(?:(?:\s|<|>).*|d[\\\\'\"]*o)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|s[\\\\'\"]*h|v[\\\\'\"]*n)|p[\\\\'\"]*(?:k[\\\\'\"]*(?:g(?:(?:[\\\\'\"]*_)?[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*f[\\\\'\"]*o)?|e[\\\\'\"]*x[\\\\'\"]*e[\\\\'\"]*c|i[\\\\'\"]*l[\\\\'\"]*l)|t[\\\\'\"]*a[\\\\'\"]*r(?:[\\\\'\"]*(?:d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p))?|a[\\\\'\"]*(?:t[\\\\'\"]*c[\\\\'\"]*h[\\\\'\"]*(?:\s|<|>).*|s[\\\\'\"]*s[\\\\'\"]*w[\\\\'\"]*d)|r[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*t[\\\\'\"]*(?:e[\\\\'\"]*n[\\\\'\"]*v|f[\\\\'\"]*(?:\s|<|>).*)|y[\\\\'\"]*t[\\\\'\"]*h[\\\\'\"]*o[\\\\'\"]*n(?:[\\\\'\"]*(?:3(?:[\\\\'\"]*m)?|2))?|e[\\\\'\"]*r[\\\\'\"]*(?:l(?:[\\\\'\"]*(?:s[\\\\'\"]*h|5))?|m[\\\\'\"]*s)|(?:g[\\\\'\"]*r[\\\\'\"]*e|f[\\\\'\"]*t)[\\\\'\"]*p|(?:u[\\\\'\"]*s[\\\\'\"]*h|o[\\\\'\"]*p)[\\\\'\"]*d|h[\\\\'\"]*p(?:[\\\\'\"]*[57])?|i[\\\\'\"]*n[\\\\'\"]*g|s[\\\\'\"]*(?:\s|<|>).*)|n[\\\\'\"]*(?:c[\\\\'\"]*(?:\.[\\\\'\"]*(?:t[\\\\'\"]*r[\\\\'\"]*a[\\\\'\"]*d[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*a[\\\\'\"]*l|o[\\\\'\"]*p[\\\\'\"]*e[\\\\'\"]*n[\\\\'\"]*b[\\\\'\"]*s[\\\\'\"]*d)|(?:\s|<|>).*|a[\\\\'\"]*t)|e[\\\\'\"]*t[\\\\'\"]*(?:k[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*-[\\\\'\"]*f[\\\\'\"]*t[\\\\'\"]*p|(?:s[\\\\'\"]*t|c)[\\\\'\"]*a[\\\\'\"]*t|(?:\s|<|>).*)|s[\\\\'\"]*(?:l[\\\\'\"]*o[\\\\'\"]*o[\\\\'\"]*k[\\\\'\"]*u[\\\\'\"]*p|t[\\\\'\"]*a[\\\\'\"]*t)|(?:a[\\\\'\"]*n[\\\\'\"]*o|i[\\\\'\"]*c[\\\\'\"]*e)[\\\\'\"]*(?:\s|<|>).*|(?:o[\\\\'\"]*h[\\\\'\"]*u|m[\\\\'\"]*a)[\\\\'\"]*p|p[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*g)|r[\\\\'\"]*(?:e[\\\\'\"]*(?:(?:p[\\\\'\"]*(?:l[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e|e[\\\\'\"]*a[\\\\'\"]*t)|n[\\\\'\"]*a[\\\\'\"]*m[\\\\'\"]*e)[\\\\'\"]*(?:\s|<|>).*|a[\\\\'\"]*l[\\\\'\"]*p[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*h)|m[\\\\'\"]*(?:(?:d[\\\\'\"]*i[\\\\'\"]*r[\\\\'\"]*)?(?:\s|<|>).*|u[\\\\'\"]*s[\\\\'\"]*e[\\\\'\"]*r)|u[\\\\'\"]*b[\\\\'\"]*y(?:[\\\\'\"]*(?:1(?:[\\\\'\"]*[89])?|2[\\\\'\"]*[012]))?|(?:a[\\\\'\"]*r|c[\\\\'\"]*p|p[\\\\'\"]*m)[\\\\'\"]*(?:\s|<|>).*|n[\\\\'\"]*a[\\\\'\"]*n[\\\\'\"]*o|o[\\\\'\"]*u[\\\\'\"]*t[\\\\'\"]*e|s[\\\\'\"]*y[\\\\'\"]*n[\\\\'\"]*c)|t[\\\\'\"]*(?:c[\\\\'\"]*(?:p[\\\\'\"]*(?:t[\\\\'\"]*r[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*u[\\\\'\"]*t[\\\\'\"]*e|i[\\\\'\"]*n[\\\\'\"]*g)|s[\\\\'\"]*h)|r[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*u[\\\\'\"]*t[\\\\'\"]*e(?:[\\\\'\"]*6)?|e[\\\\'\"]*(?:l[\\\\'\"]*n[\\\\'\"]*e[\\\\'\"]*t|e[\\\\'\"]*(?:\s|<|>).*)|i[\\\\'\"]*m[\\\\'\"]*e[\\\\'\"]*(?:o[\\\\'\"]*u[\\\\'\"]*t|(?:\s|<|>).*)|a[\\\\'\"]*(?:i[\\\\'\"]*l(?:[\\\\'\"]*f)?|r[\\\\'\"]*(?:\s|<|>).*)|o[\\\\'\"]*(?:u[\\\\'\"]*c[\\\\'\"]*h[\\\\'\"]*(?:\s|<|>).*|p))|u[\\\\'\"]*(?:n[\\\\'\"]*(?:l[\\\\'\"]*(?:i[\\\\'\"]*n[\\\\'\"]*k[\\\\'\"]*(?:\s|<|>).*|z[\\\\'\"]*m[\\\\'\"]*a)|c[\\\\'\"]*o[\\\\'\"]*m[\\\\'\"]*p[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|a[\\\\'\"]*m[\\\\'\"]*e|r[\\\\'\"]*a[\\\\'\"]*r|s[\\\\'\"]*e[\\\\'\"]*t|z[\\\\'\"]*i[\\\\'\"]*p|x[\\\\'\"]*z)|s[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*(?:(?:a[\\\\'\"]*d|m[\\\\'\"]*o)[\\\\'\"]*d|d[\\\\'\"]*e[\\\\'\"]*l)|l[\\\\'\"]*i[\\\\'\"]*m[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*(?:\s|<|>).*)|m[\\\\'\"]*(?:y[\\\\'\"]*s[\\\\'\"]*q[\\\\'\"]*l(?:[\\\\'\"]*(?:d[\\\\'\"]*u[\\\\'\"]*m[\\\\'\"]*p(?:[\\\\'\"]*s[\\\\'\"]*l[\\\\'\"]*o[\\\\'\"]*w)?|h[\\\\'\"]*o[\\\\'\"]*t[\\\\'\"]*c[\\\\'\"]*o[\\\\'\"]*p[\\\\'\"]*y|a[\\\\'\"]*d[\\\\'\"]*m[\\\\'\"]*i[\\\\'\"]*n|s[\\\\'\"]*h[\\\\'\"]*o[\\\\'\"]*w))?|(?:(?:o[\\\\'\"]*u[\\\\'\"]*n|u[\\\\'\"]*t)[\\\\'\"]*t|v)[\\\\'\"]*(?:\s|<|>).*)|x[\\\\'\"]*(?:z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|d[\\\\'\"]*(?:i[\\\\'\"]*f[\\\\'\"]*f|e[\\\\'\"]*c)|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e|(?:\s|<|>).*)|a[\\\\'\"]*r[\\\\'\"]*g[\\\\'\"]*s|t[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*m|x[\\\\'\"]*d[\\\\'\"]*(?:\s|<|>).*)|z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|i[\\\\'\"]*p[\\\\'\"]*(?:\s|<|>).*|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e|r[\\\\'\"]*u[\\\\'\"]*n|s[\\\\'\"]*h)|o[\\\\'\"]*(?:p[\\\\'\"]*e[\\\\'\"]*n[\\\\'\"]*s[\\\\'\"]*s[\\\\'\"]*l|n[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*t[\\\\'\"]*r)|w[\\\\'\"]*(?:h[\\\\'\"]*o[\\\\'\"]*(?:a[\\\\'\"]*m[\\\\'\"]*i|(?:\s|<|>).*)|g[\\\\'\"]*e[\\\\'\"]*t|3[\\\\'\"]*m)|v[\\\\'\"]*i[\\\\'\"]*(?:m[\\\\'\"]*(?:\s|<|>).*|g[\\\\'\"]*r|p[\\\\'\"]*w)|y[\\\\'\"]*u[\\\\'\"]*m)\b" \ "id:932105,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Unix Command Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Windows command injection ] # # This rule detects Windows shell command injections. # If you are not running Windows, it is safe to disable this rule. # # A command injection takes a form such as: # # foo.jpg&ver /r # foo.jpg|ver /r # # The vulnerability exists when an application executes a shell command # without proper input escaping/validation. # # To prevent false positives, we look for a 'starting sequence' that # precedes a command in CMD syntax, such as: ; | & ` # # Anatomy of the regexp: # # 1. Starting tokens # # ; ;cmd # \{ {cmd # \| |cmd # \|\| ||cmd # & &cmd # && &&cmd # \n \ncmd # \r \rcmd # ` `cmd # # 2. Command prefixes # # ( (cmd) # , ,cmd # @ @cmd # ' 'cmd' # " "cmd" # \s spacing+cmd # # 3. Paths # # [\w'\"\./]+/ /path/cmd # [\\\\'\"\^]*\w[\\\\'\"\^]*:.*\\\\ C:\Program Files\cmd # [\^\.\w '\"/\\\\]*\\\\)?[\"\^]* \\net\share\dir\cmd # # 4. Quoting # # \" "cmd" # \^ ^cmd # # 5. Extension/switches # # \.[\"\^]*\w+ cmd.com, cmd.exe, etc. # /b cmd/h # # An effort is made to combat evasions by CMD syntax; for example, # the following strings are valid: c^md, @cmd, "c"md. ModSecurity # has a t:cmdLine transformation built-in to deal with some of these, # but unfortunately, that transformation replaces ';' characters (so # we cannot match on the start of a command) and '\' characters (so we # have trouble matching paths). This makes the regexp more complex. # # This rule is case-insensitive. # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932110.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:;|\{|\||\|\||&|&&|\n|\r|`)\s*[\(,@\'\"\s]*(?:[\w'\"\./]+/|[\\\\'\"\^]*\w[\\\\'\"\^]*:.*\\\\|[\^\.\w '\"/\\\\]*\\\\)?[\"\^]* # [regexp assembled from util/regexp-assemble/regexp-932110.txt] # (?:\.[\"\^]*\w+)?\b" \ # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:;|\{|\||\|\||&|&&|\n|\r|`)\s*[\(,@\'\"\s]*(?:[\w'\"\./]+/|[\\\\'\"\^]*\w[\\\\'\"\^]*:.*\\\\|[\^\.\w '\"/\\\\]*\\\\)?[\"\^]*(?:m[\"\^]*(?:y[\"\^]*s[\"\^]*q[\"\^]*l(?:[\"\^]*(?:d[\"\^]*u[\"\^]*m[\"\^]*p(?:[\"\^]*s[\"\^]*l[\"\^]*o[\"\^]*w)?|h[\"\^]*o[\"\^]*t[\"\^]*c[\"\^]*o[\"\^]*p[\"\^]*y|a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n|s[\"\^]*h[\"\^]*o[\"\^]*w))?|s[\"\^]*(?:i[\"\^]*(?:n[\"\^]*f[\"\^]*o[\"\^]*3[\"\^]*2|e[\"\^]*x[\"\^]*e[\"\^]*c)|c[\"\^]*o[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*g|g[\"\^]*(?:[\s,;]|\.|/|<|>).*|t[\"\^]*s[\"\^]*c)|o[\"\^]*(?:u[\"\^]*n[\"\^]*t[\"\^]*(?:(?:[\s,;]|\.|/|<|>).*|v[\"\^]*o[\"\^]*l)|v[\"\^]*e[\"\^]*u[\"\^]*s[\"\^]*e[\"\^]*r|[dr][\"\^]*e[\"\^]*(?:[\s,;]|\.|/|<|>).*)|k[\"\^]*(?:d[\"\^]*i[\"\^]*r[\"\^]*(?:[\s,;]|\.|/|<|>).*|l[\"\^]*i[\"\^]*n[\"\^]*k)|d[\"\^]*(?:s[\"\^]*c[\"\^]*h[\"\^]*e[\"\^]*d|(?:[\s,;]|\.|/|<|>).*)|a[\"\^]*p[\"\^]*i[\"\^]*s[\"\^]*e[\"\^]*n[\"\^]*d|b[\"\^]*s[\"\^]*a[\"\^]*c[\"\^]*l[\"\^]*i|e[\"\^]*a[\"\^]*s[\"\^]*u[\"\^]*r[\"\^]*e|m[\"\^]*s[\"\^]*y[\"\^]*s)|d[\"\^]*(?:i[\"\^]*(?:s[\"\^]*k[\"\^]*(?:(?:m[\"\^]*g[\"\^]*m|p[\"\^]*a[\"\^]*r)[\"\^]*t|s[\"\^]*h[\"\^]*a[\"\^]*d[\"\^]*o[\"\^]*w)|r[\"\^]*(?:(?:[\s,;]|\.|/|<|>).*|u[\"\^]*s[\"\^]*e)|f[\"\^]*f[\"\^]*(?:[\s,;]|\.|/|<|>).*)|e[\"\^]*(?:l[\"\^]*(?:p[\"\^]*r[\"\^]*o[\"\^]*f|t[\"\^]*r[\"\^]*e[\"\^]*e|(?:[\s,;]|\.|/|<|>).*)|v[\"\^]*(?:m[\"\^]*g[\"\^]*m[\"\^]*t|c[\"\^]*o[\"\^]*n)|(?:f[\"\^]*r[\"\^]*a|b[\"\^]*u)[\"\^]*g)|s[\"\^]*(?:a[\"\^]*(?:c[\"\^]*l[\"\^]*s|d[\"\^]*d)|q[\"\^]*u[\"\^]*e[\"\^]*r[\"\^]*y|m[\"\^]*o[\"\^]*(?:v[\"\^]*e|d)|g[\"\^]*e[\"\^]*t|r[\"\^]*m)|(?:r[\"\^]*i[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*q[\"\^]*u[\"\^]*e[\"\^]*r|o[\"\^]*s[\"\^]*k[\"\^]*e)[\"\^]*y|(?:c[\"\^]*o[\"\^]*m[\"\^]*c[\"\^]*n[\"\^]*f|x[\"\^]*d[\"\^]*i[\"\^]*a)[\"\^]*g|a[\"\^]*t[\"\^]*e[\"\^]*(?:[\s,;]|\.|/|<|>).*|n[\"\^]*s[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*t)|c[\"\^]*(?:o[\"\^]*(?:m[\"\^]*(?:p[\"\^]*(?:(?:a[\"\^]*c[\"\^]*t[\"\^]*)?(?:[\s,;]|\.|/|<|>).*|m[\"\^]*g[\"\^]*m[\"\^]*t)|e[\"\^]*x[\"\^]*p)|n[\"\^]*(?:2[\"\^]*p|v[\"\^]*e)[\"\^]*r[\"\^]*t|p[\"\^]*y)|l[\"\^]*(?:e[\"\^]*a[\"\^]*(?:n[\"\^]*m[\"\^]*g[\"\^]*r|r[\"\^]*m[\"\^]*e[\"\^]*m)|u[\"\^]*s[\"\^]*t[\"\^]*e[\"\^]*r)|h[\"\^]*(?:k[\"\^]*(?:n[\"\^]*t[\"\^]*f[\"\^]*s|d[\"\^]*s[\"\^]*k)|d[\"\^]*i[\"\^]*r[\"\^]*(?:[\s,;]|\.|/|<|>).*)|s[\"\^]*(?:c[\"\^]*(?:r[\"\^]*i[\"\^]*p[\"\^]*t|c[\"\^]*m[\"\^]*d)|v[\"\^]*d[\"\^]*e)|e[\"\^]*r[\"\^]*t[\"\^]*(?:u[\"\^]*t[\"\^]*i[\"\^]*l|r[\"\^]*e[\"\^]*q)|a[\"\^]*(?:l[\"\^]*l[\"\^]*(?:[\s,;]|\.|/|<|>).*|c[\"\^]*l[\"\^]*s)|m[\"\^]*d(?:[\"\^]*k[\"\^]*e[\"\^]*y)?|i[\"\^]*p[\"\^]*h[\"\^]*e[\"\^]*r|u[\"\^]*r[\"\^]*l)|f[\"\^]*(?:o[\"\^]*r[\"\^]*(?:m[\"\^]*a[\"\^]*t[\"\^]*(?:[\s,;]|\.|/|<|>).*|f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*s|e[\"\^]*a[\"\^]*c[\"\^]*h)|i[\"\^]*n[\"\^]*d[\"\^]*(?:(?:[\s,;]|\.|/|<|>).*|s[\"\^]*t[\"\^]*r)|s[\"\^]*(?:m[\"\^]*g[\"\^]*m[\"\^]*t|u[\"\^]*t[\"\^]*i[\"\^]*l)|t[\"\^]*(?:p[\"\^]*(?:[\s,;]|\.|/|<|>).*|y[\"\^]*p[\"\^]*e)|r[\"\^]*e[\"\^]*e[\"\^]*d[\"\^]*i[\"\^]*s[\"\^]*k|c[\"\^]*(?:[\s,;]|\.|/|<|>).*|g[\"\^]*r[\"\^]*e[\"\^]*p)|n[\"\^]*(?:e[\"\^]*t[\"\^]*(?:s[\"\^]*(?:t[\"\^]*a[\"\^]*t|v[\"\^]*c|h)|(?:[\s,;]|\.|/|<|>).*|c[\"\^]*a[\"\^]*t|d[\"\^]*o[\"\^]*m)|t[\"\^]*(?:b[\"\^]*a[\"\^]*c[\"\^]*k[\"\^]*u[\"\^]*p|r[\"\^]*i[\"\^]*g[\"\^]*h[\"\^]*t[\"\^]*s)|(?:s[\"\^]*l[\"\^]*o[\"\^]*o[\"\^]*k[\"\^]*u|m[\"\^]*a)[\"\^]*p|c[\"\^]*(?:(?:[\s,;]|\.|/|<|>).*|a[\"\^]*t)|b[\"\^]*t[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*t)|e[\"\^]*(?:x[\"\^]*p[\"\^]*(?:a[\"\^]*n[\"\^]*d[\"\^]*(?:[\s,;]|\.|/|<|>).*|l[\"\^]*o[\"\^]*r[\"\^]*e[\"\^]*r)|v[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*(?:c[\"\^]*r[\"\^]*e[\"\^]*a[\"\^]*t[\"\^]*e|v[\"\^]*w[\"\^]*r)|n[\"\^]*d[\"\^]*l[\"\^]*o[\"\^]*c[\"\^]*a[\"\^]*l|g[\"\^]*r[\"\^]*e[\"\^]*p|r[\"\^]*a[\"\^]*s[\"\^]*e|c[\"\^]*h[\"\^]*o)|g[\"\^]*(?:a[\"\^]*t[\"\^]*h[\"\^]*e[\"\^]*r[\"\^]*n[\"\^]*e[\"\^]*t[\"\^]*w[\"\^]*o[\"\^]*r[\"\^]*k[\"\^]*i[\"\^]*n[\"\^]*f[\"\^]*o|p[\"\^]*(?:(?:r[\"\^]*e[\"\^]*s[\"\^]*u[\"\^]*l|e[\"\^]*d[\"\^]*i)[\"\^]*t|u[\"\^]*p[\"\^]*d[\"\^]*a[\"\^]*t[\"\^]*e)|i[\"\^]*t[\"\^]*(?:[\s,;]|\.|/|<|>).*|e[\"\^]*t[\"\^]*m[\"\^]*a[\"\^]*c)|i[\"\^]*(?:r[\"\^]*b(?:[\"\^]*(?:1(?:[\"\^]*[89])?|2[\"\^]*[012]))?|f[\"\^]*m[\"\^]*e[\"\^]*m[\"\^]*b[\"\^]*e[\"\^]*r|p[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*g|n[\"\^]*e[\"\^]*t[\"\^]*c[\"\^]*p[\"\^]*l|c[\"\^]*a[\"\^]*c[\"\^]*l[\"\^]*s)|a[\"\^]*(?:d[\"\^]*(?:d[\"\^]*u[\"\^]*s[\"\^]*e[\"\^]*r[\"\^]*s|m[\"\^]*o[\"\^]*d[\"\^]*c[\"\^]*m[\"\^]*d)|r[\"\^]*p[\"\^]*(?:[\s,;]|\.|/|<|>).*|t[\"\^]*t[\"\^]*r[\"\^]*i[\"\^]*b|s[\"\^]*s[\"\^]*o[\"\^]*c|z[\"\^]*m[\"\^]*a[\"\^]*n)|l[\"\^]*(?:o[\"\^]*g[\"\^]*(?:e[\"\^]*v[\"\^]*e[\"\^]*n[\"\^]*t|t[\"\^]*i[\"\^]*m[\"\^]*e|m[\"\^]*a[\"\^]*n|o[\"\^]*f[\"\^]*f)|a[\"\^]*b[\"\^]*e[\"\^]*l[\"\^]*(?:[\s,;]|\.|/|<|>).*|u[\"\^]*s[\"\^]*r[\"\^]*m[\"\^]*g[\"\^]*r)|b[\"\^]*(?:(?:c[\"\^]*d[\"\^]*(?:b[\"\^]*o[\"\^]*o|e[\"\^]*d[\"\^]*i)|r[\"\^]*o[\"\^]*w[\"\^]*s[\"\^]*t[\"\^]*a)[\"\^]*t|i[\"\^]*t[\"\^]*s[\"\^]*a[\"\^]*d[\"\^]*m[\"\^]*i[\"\^]*n|o[\"\^]*o[\"\^]*t[\"\^]*c[\"\^]*f[\"\^]*g)|h[\"\^]*(?:o[\"\^]*s[\"\^]*t[\"\^]*n[\"\^]*a[\"\^]*m[\"\^]*e|d[\"\^]*w[\"\^]*w[\"\^]*i[\"\^]*z)|j[\"\^]*a[\"\^]*v[\"\^]*a[\"\^]*(?:[\s,;]|\.|/|<|>).*|7[\"\^]*z(?:[\"\^]*[ar])?)(?:\.[\"\^]*\w+)?\b" \ "id:932110,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Windows Command Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-windows',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # Apache 2.2 requires configuration file lines to be under 8kB. # Therefore, some remaining commands have been split off to a separate rule. # For explanation of this rule, see rule 932110. # # This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: # [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932115.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:;|\{|\||\|\||&|&&|\n|\r|`)\s*[\(,@\'\"\s]*(?:[\w'\"\./]+/|[\\\\'\"\^]*\w[\\\\'\"\^]*:.*\\\\|[\^\.\w '\"/\\\\]*\\\\)?[\"\^]* # [regexp assembled from util/regexp-assemble/regexp-932110.txt] # (?:\.[\"\^]*\w+)?\b" \ # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:;|\{|\||\|\||&|&&|\n|\r|`)\s*[\(,@\'\"\s]*(?:[\w'\"\./]+/|[\\\\'\"\^]*\w[\\\\'\"\^]*:.*\\\\|[\^\.\w '\"/\\\\]*\\\\)?[\"\^]*(?:s[\"\^]*(?:y[\"\^]*s[\"\^]*(?:t[\"\^]*e[\"\^]*m[\"\^]*(?:p[\"\^]*r[\"\^]*o[\"\^]*p[\"\^]*e[\"\^]*r[\"\^]*t[\"\^]*i[\"\^]*e[\"\^]*s[\"\^]*(?:d[\"\^]*a[\"\^]*t[\"\^]*a[\"\^]*e[\"\^]*x[\"\^]*e[\"\^]*c[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n[\"\^]*p[\"\^]*r[\"\^]*e[\"\^]*v[\"\^]*e[\"\^]*n[\"\^]*t[\"\^]*i[\"\^]*o[\"\^]*n|(?:p[\"\^]*e[\"\^]*r[\"\^]*f[\"\^]*o[\"\^]*r[\"\^]*m[\"\^]*a[\"\^]*n[\"\^]*c|h[\"\^]*a[\"\^]*r[\"\^]*d[\"\^]*w[\"\^]*a[\"\^]*r)[\"\^]*e|a[\"\^]*d[\"\^]*v[\"\^]*a[\"\^]*n[\"\^]*c[\"\^]*e[\"\^]*d)|i[\"\^]*n[\"\^]*f[\"\^]*o)|k[\"\^]*e[\"\^]*y|d[\"\^]*m)|h[\"\^]*(?:o[\"\^]*(?:w[\"\^]*(?:g[\"\^]*r[\"\^]*p|m[\"\^]*b[\"\^]*r)[\"\^]*s|r[\"\^]*t[\"\^]*c[\"\^]*u[\"\^]*t)|e[\"\^]*l[\"\^]*l[\"\^]*r[\"\^]*u[\"\^]*n[\"\^]*a[\"\^]*s|u[\"\^]*t[\"\^]*d[\"\^]*o[\"\^]*w[\"\^]*n|r[\"\^]*p[\"\^]*u[\"\^]*b[\"\^]*w|a[\"\^]*r[\"\^]*e|i[\"\^]*f[\"\^]*t)|e[\"\^]*(?:t[\"\^]*(?:(?:x[\"\^]*)?(?:[\s,;]|\.|/|<|>).*|l[\"\^]*o[\"\^]*c[\"\^]*a[\"\^]*l)|c[\"\^]*p[\"\^]*o[\"\^]*l|l[\"\^]*e[\"\^]*c[\"\^]*t)|c[\"\^]*(?:h[\"\^]*t[\"\^]*a[\"\^]*s[\"\^]*k[\"\^]*s|l[\"\^]*i[\"\^]*s[\"\^]*t)|u[\"\^]*b[\"\^]*(?:i[\"\^]*n[\"\^]*a[\"\^]*c[\"\^]*l|s[\"\^]*t)|t[\"\^]*a[\"\^]*r[\"\^]*t[\"\^]*(?:[\s,;]|\.|/|<|>).*|i[\"\^]*g[\"\^]*v[\"\^]*e[\"\^]*r[\"\^]*i[\"\^]*f|l[\"\^]*(?:e[\"\^]*e[\"\^]*p|m[\"\^]*g[\"\^]*r)|o[\"\^]*r[\"\^]*t|f[\"\^]*c|v[\"\^]*n)|p[\"\^]*(?:s[\"\^]*(?:s[\"\^]*(?:h[\"\^]*u[\"\^]*t[\"\^]*d[\"\^]*o[\"\^]*w[\"\^]*n|e[\"\^]*r[\"\^]*v[\"\^]*i[\"\^]*c[\"\^]*e|u[\"\^]*s[\"\^]*p[\"\^]*e[\"\^]*n[\"\^]*d)|l[\"\^]*(?:o[\"\^]*g[\"\^]*(?:g[\"\^]*e[\"\^]*d[\"\^]*o[\"\^]*n|l[\"\^]*i[\"\^]*s[\"\^]*t)|i[\"\^]*s[\"\^]*t)|p[\"\^]*(?:a[\"\^]*s[\"\^]*s[\"\^]*w[\"\^]*d|i[\"\^]*n[\"\^]*g)|g[\"\^]*e[\"\^]*t[\"\^]*s[\"\^]*i[\"\^]*d|e[\"\^]*x[\"\^]*e[\"\^]*c|f[\"\^]*i[\"\^]*l[\"\^]*e|i[\"\^]*n[\"\^]*f[\"\^]*o|k[\"\^]*i[\"\^]*l[\"\^]*l)|o[\"\^]*(?:w[\"\^]*e[\"\^]*r[\"\^]*(?:s[\"\^]*h[\"\^]*e[\"\^]*l[\"\^]*l(?:[\"\^]*_[\"\^]*i[\"\^]*s[\"\^]*e)?|c[\"\^]*f[\"\^]*g)|r[\"\^]*t[\"\^]*q[\"\^]*r[\"\^]*y|p[\"\^]*d)|r[\"\^]*(?:i[\"\^]*n[\"\^]*t[\"\^]*(?:(?:[\s,;]|\.|/|<|>).*|b[\"\^]*r[\"\^]*m)|n[\"\^]*(?:c[\"\^]*n[\"\^]*f[\"\^]*g|m[\"\^]*n[\"\^]*g[\"\^]*r)|o[\"\^]*m[\"\^]*p[\"\^]*t)|a[\"\^]*t[\"\^]*h[\"\^]*(?:p[\"\^]*i[\"\^]*n[\"\^]*g|(?:[\s,;]|\.|/|<|>).*)|e[\"\^]*r[\"\^]*(?:l(?:[\"\^]*(?:s[\"\^]*h|5))?|f[\"\^]*m[\"\^]*o[\"\^]*n)|y[\"\^]*t[\"\^]*h[\"\^]*o[\"\^]*n(?:[\"\^]*(?:3(?:[\"\^]*m)?|2))?|k[\"\^]*g[\"\^]*m[\"\^]*g[\"\^]*r|h[\"\^]*p(?:[\"\^]*[57])?|u[\"\^]*s[\"\^]*h[\"\^]*d|i[\"\^]*n[\"\^]*g)|r[\"\^]*(?:e[\"\^]*(?:(?:p[\"\^]*l[\"\^]*a[\"\^]*c[\"\^]*e|n(?:[\"\^]*a[\"\^]*m[\"\^]*e)?|s[\"\^]*e[\"\^]*t)[\"\^]*(?:[\s,;]|\.|/|<|>).*|g[\"\^]*(?:s[\"\^]*v[\"\^]*r[\"\^]*3[\"\^]*2|e[\"\^]*d[\"\^]*i[\"\^]*t|(?:[\s,;]|\.|/|<|>).*|i[\"\^]*n[\"\^]*i)|c[\"\^]*(?:d[\"\^]*i[\"\^]*s[\"\^]*c|o[\"\^]*v[\"\^]*e[\"\^]*r)|k[\"\^]*e[\"\^]*y[\"\^]*w[\"\^]*i[\"\^]*z)|u[\"\^]*(?:n[\"\^]*(?:d[\"\^]*l[\"\^]*l[\"\^]*3[\"\^]*2|a[\"\^]*s)|b[\"\^]*y[\"\^]*(?:1(?:[\"\^]*[89])?|2[\"\^]*[012]))|a[\"\^]*(?:s[\"\^]*(?:p[\"\^]*h[\"\^]*o[\"\^]*n[\"\^]*e|d[\"\^]*i[\"\^]*a[\"\^]*l)|r[\"\^]*(?:[\s,;]|\.|/|<|>).*)|m[\"\^]*(?:(?:d[\"\^]*i[\"\^]*r[\"\^]*)?(?:[\s,;]|\.|/|<|>).*|t[\"\^]*s[\"\^]*h[\"\^]*a[\"\^]*r[\"\^]*e)|o[\"\^]*(?:u[\"\^]*t[\"\^]*e[\"\^]*(?:[\s,;]|\.|/|<|>).*|b[\"\^]*o[\"\^]*c[\"\^]*o[\"\^]*p[\"\^]*y)|s[\"\^]*(?:t[\"\^]*r[\"\^]*u[\"\^]*i|y[\"\^]*n[\"\^]*c)|d[\"\^]*(?:[\s,;]|\.|/|<|>).*)|t[\"\^]*(?:a[\"\^]*(?:s[\"\^]*k[\"\^]*(?:k[\"\^]*i[\"\^]*l[\"\^]*l|l[\"\^]*i[\"\^]*s[\"\^]*t|s[\"\^]*c[\"\^]*h[\"\^]*d|m[\"\^]*g[\"\^]*r)|k[\"\^]*e[\"\^]*o[\"\^]*w[\"\^]*n)|(?:i[\"\^]*m[\"\^]*e[\"\^]*o[\"\^]*u|p[\"\^]*m[\"\^]*i[\"\^]*n[\"\^]*i|e[\"\^]*l[\"\^]*n[\"\^]*e|l[\"\^]*i[\"\^]*s)[\"\^]*t|s[\"\^]*(?:d[\"\^]*i[\"\^]*s[\"\^]*c[\"\^]*o|s[\"\^]*h[\"\^]*u[\"\^]*t[\"\^]*d)[\"\^]*n|y[\"\^]*p[\"\^]*e[\"\^]*(?:p[\"\^]*e[\"\^]*r[\"\^]*f|(?:[\s,;]|\.|/|<|>).*)|r[\"\^]*(?:a[\"\^]*c[\"\^]*e[\"\^]*r[\"\^]*t|e[\"\^]*e))|w[\"\^]*(?:i[\"\^]*n[\"\^]*(?:d[\"\^]*i[\"\^]*f[\"\^]*f|m[\"\^]*s[\"\^]*d[\"\^]*p|v[\"\^]*a[\"\^]*r|r[\"\^]*[ms])|u[\"\^]*(?:a[\"\^]*(?:u[\"\^]*c[\"\^]*l[\"\^]*t|p[\"\^]*p)|s[\"\^]*a)|s[\"\^]*c[\"\^]*(?:r[\"\^]*i[\"\^]*p[\"\^]*t|u[\"\^]*i)|e[\"\^]*v[\"\^]*t[\"\^]*u[\"\^]*t[\"\^]*i[\"\^]*l|m[\"\^]*i[\"\^]*(?:m[\"\^]*g[\"\^]*m[\"\^]*t|c)|a[\"\^]*i[\"\^]*t[\"\^]*f[\"\^]*o[\"\^]*r|h[\"\^]*o[\"\^]*a[\"\^]*m[\"\^]*i|g[\"\^]*e[\"\^]*t)|u[\"\^]*(?:s[\"\^]*(?:e[\"\^]*r[\"\^]*a[\"\^]*c[\"\^]*c[\"\^]*o[\"\^]*u[\"\^]*n[\"\^]*t[\"\^]*c[\"\^]*o[\"\^]*n[\"\^]*t[\"\^]*r[\"\^]*o[\"\^]*l[\"\^]*s[\"\^]*e[\"\^]*t[\"\^]*t[\"\^]*i[\"\^]*n[\"\^]*g[\"\^]*s|r[\"\^]*s[\"\^]*t[\"\^]*a[\"\^]*t)|n[\"\^]*(?:r[\"\^]*a[\"\^]*r|z[\"\^]*i[\"\^]*p))|q[\"\^]*(?:u[\"\^]*e[\"\^]*r[\"\^]*y[\"\^]*(?:[\s,;]|\.|/|<|>).*|p[\"\^]*r[\"\^]*o[\"\^]*c[\"\^]*e[\"\^]*s[\"\^]*s|w[\"\^]*i[\"\^]*n[\"\^]*s[\"\^]*t[\"\^]*a|g[\"\^]*r[\"\^]*e[\"\^]*p)|o[\"\^]*(?:d[\"\^]*b[\"\^]*c[\"\^]*(?:a[\"\^]*d[\"\^]*3[\"\^]*2|c[\"\^]*o[\"\^]*n[\"\^]*f)|p[\"\^]*e[\"\^]*n[\"\^]*f[\"\^]*i[\"\^]*l[\"\^]*e[\"\^]*s)|v[\"\^]*(?:o[\"\^]*l[\"\^]*(?:[\s,;]|\.|/|<|>).*|e[\"\^]*r[\"\^]*i[\"\^]*f[\"\^]*y)|x[\"\^]*c[\"\^]*(?:a[\"\^]*c[\"\^]*l[\"\^]*s|o[\"\^]*p[\"\^]*y)|z[\"\^]*i[\"\^]*p[\"\^]*(?:[\s,;]|\.|/|<|>).*)(?:\.[\"\^]*\w+)?\b" \ "id:932115,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Windows Command Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-windows',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Windows PowerShell, cmdlets and options ] # # Detect some common PowerShell commands, cmdlets and options. # These commands should be relatively uncommon in normal text, but # potentially useful for code injection. # # If you are not running Windows, it is safe to disable this rule. # # https://technet.microsoft.com/en-us/magazine/ff714569.aspx # https://msdn.microsoft.com/en-us/powershell/scripting/core-powershell/console/powershell.exe-command-line-help # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile windows-powershell-commands.data" \ "id:932120,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:cmdLine,t:lowercase,\ msg:'Remote Command Execution: Windows PowerShell Command Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'language-powershell',\ tag:'platform-windows',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Unix shell expressions ] # # Detects the following patterns which are common in Unix shell scripts # and oneliners: # # $(foo) Command substitution # ${foo} Parameter expansion # <(foo) Process substitution # >(foo) Process substitution # $((foo)) Arithmetic expansion # # Regexp generated from util/regexp-assemble/regexp-932130.data using Regexp::Assemble. # See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\$(?:\((?:\(.*\)|.*)\)|\{.*\})|[<>]\(.*\))" \ "id:932130,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:cmdLine,\ msg:'Remote Command Execution: Unix Shell Expression Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Windows FOR, IF commands ] # # This rule detects Windows command shell FOR and IF commands. # If you are not running Windows, it is safe to disable this rule. # # Examples: # # FOR %a IN (set) DO # FOR /D %a IN (dirs) DO # FOR /F "options" %a IN (text|"text") DO # FOR /L %a IN (start,step,end) DO # FOR /R C:\dir %A IN (set) DO # # IF [/I] [NOT] EXIST filename | DEFINED define | ERRORLEVEL n | CMDEXTVERSION n # IF [/I] [NOT] item1 [==|EQU|NEQ|LSS|LEQ|GTR|GEQ] item2 # IF [/I] [NOT] (item1) [==|EQU|NEQ|LSS|LEQ|GTR|GEQ] (item2) # # http://ss64.com/nt/if.html # http://ss64.com/nt/for.html # # Regexp generated from util/regexp-assemble/regexp-932140.data using Regexp::Assemble. # See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx \b(?:if(?:/i)?(?: not)?(?: exist\b| defined\b| errorlevel\b| cmdextversion\b|(?: |\().*(?:\bgeq\b|\bequ\b|\bneq\b|\bleq\b|\bgtr\b|\blss\b|==))|for(?:/[dflr].*)? %+[^ ]+ in\(.*\)\s?do)" \ "id:932140,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:cmdLine,\ msg:'Remote Command Execution: Windows FOR/IF Command Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-windows',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Unix direct remote command execution ] # # Detects Unix commands at the start of a parameter (direct RCE). # Example: foo=wget%20www.example.com # # This case is different from command injection (rule 932100), where a # command string is appended (injected) to a regular parameter, and then # passed to a shell unescaped. # # This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: # [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] # # Due to a higher risk of false positives, the following changes have been # made relative to rule 932100: # 1) the set of commands is smaller # 2) we require a trailing space (denoting command parameters) or command # separator character after the command # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932150.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:^|=)\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]* # [regexp assembled from util/regexp-assemble/regexp-932150.txt] # [\\\\'\"]*(?:\s|;|\||&|<|>)" \ # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:^|=)\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]*(?:l[\\\\'\"]*(?:s(?:[\\\\'\"]*(?:b[\\\\'\"]*_[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*l[\\\\'\"]*e[\\\\'\"]*a[\\\\'\"]*s[\\\\'\"]*e|c[\\\\'\"]*p[\\\\'\"]*u|m[\\\\'\"]*o[\\\\'\"]*d|p[\\\\'\"]*c[\\\\'\"]*i|u[\\\\'\"]*s[\\\\'\"]*b|-[\\\\'\"]*F|o[\\\\'\"]*f))?|z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|m[\\\\'\"]*(?:o[\\\\'\"]*r[\\\\'\"]*e|a)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s)|e[\\\\'\"]*s[\\\\'\"]*s[\\\\'\"]*(?:(?:f[\\\\'\"]*i[\\\\'\"]*l|p[\\\\'\"]*i[\\\\'\"]*p)[\\\\'\"]*e|e[\\\\'\"]*c[\\\\'\"]*h[\\\\'\"]*o)|a[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*(?:l[\\\\'\"]*o[\\\\'\"]*g(?:[\\\\'\"]*i[\\\\'\"]*n)?|c[\\\\'\"]*o[\\\\'\"]*m[\\\\'\"]*m)|w[\\\\'\"]*p(?:[\\\\'\"]*-[\\\\'\"]*d[\\\\'\"]*o[\\\\'\"]*w[\\\\'\"]*n[\\\\'\"]*l[\\\\'\"]*o[\\\\'\"]*a[\\\\'\"]*d)?|f[\\\\'\"]*t[\\\\'\"]*p(?:[\\\\'\"]*g[\\\\'\"]*e[\\\\'\"]*t)?|y[\\\\'\"]*n[\\\\'\"]*x)|s[\\\\'\"]*(?:e[\\\\'\"]*(?:t[\\\\'\"]*(?:e[\\\\'\"]*n[\\\\'\"]*v|s[\\\\'\"]*i[\\\\'\"]*d)|n[\\\\'\"]*d[\\\\'\"]*m[\\\\'\"]*a[\\\\'\"]*i[\\\\'\"]*l|d)|h(?:[\\\\'\"]*\.[\\\\'\"]*d[\\\\'\"]*i[\\\\'\"]*s[\\\\'\"]*t[\\\\'\"]*r[\\\\'\"]*i[\\\\'\"]*b)?|o[\\\\'\"]*(?:u[\\\\'\"]*r[\\\\'\"]*c[\\\\'\"]*e|c[\\\\'\"]*a[\\\\'\"]*t)|t[\\\\'\"]*r[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*g[\\\\'\"]*s|y[\\\\'\"]*s[\\\\'\"]*c[\\\\'\"]*t[\\\\'\"]*l|c[\\\\'\"]*(?:h[\\\\'\"]*e[\\\\'\"]*d|p)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|f[\\\\'\"]*t[\\\\'\"]*p|u[\\\\'\"]*d[\\\\'\"]*o|s[\\\\'\"]*h|v[\\\\'\"]*n)|p[\\\\'\"]*(?:t[\\\\'\"]*a[\\\\'\"]*r(?:[\\\\'\"]*(?:d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p))?|y[\\\\'\"]*t[\\\\'\"]*h[\\\\'\"]*o[\\\\'\"]*n(?:[\\\\'\"]*(?:3(?:[\\\\'\"]*m)?|2))?|k[\\\\'\"]*(?:e[\\\\'\"]*x[\\\\'\"]*e[\\\\'\"]*c|i[\\\\'\"]*l[\\\\'\"]*l)|r[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*t[\\\\'\"]*e[\\\\'\"]*n[\\\\'\"]*v|(?:g[\\\\'\"]*r[\\\\'\"]*e|f[\\\\'\"]*t)[\\\\'\"]*p|e[\\\\'\"]*r[\\\\'\"]*l(?:[\\\\'\"]*5)?|h[\\\\'\"]*p(?:[\\\\'\"]*[57])?|i[\\\\'\"]*n[\\\\'\"]*g|o[\\\\'\"]*p[\\\\'\"]*d)|n[\\\\'\"]*(?:c(?:[\\\\'\"]*(?:\.[\\\\'\"]*(?:t[\\\\'\"]*r[\\\\'\"]*a[\\\\'\"]*d[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*o[\\\\'\"]*n[\\\\'\"]*a[\\\\'\"]*l|o[\\\\'\"]*p[\\\\'\"]*e[\\\\'\"]*n[\\\\'\"]*b[\\\\'\"]*s[\\\\'\"]*d)|a[\\\\'\"]*t))?|e[\\\\'\"]*t[\\\\'\"]*(?:k[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*-[\\\\'\"]*f[\\\\'\"]*t[\\\\'\"]*p|(?:s[\\\\'\"]*t|c)[\\\\'\"]*a[\\\\'\"]*t)|o[\\\\'\"]*h[\\\\'\"]*u[\\\\'\"]*p|p[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*g|s[\\\\'\"]*t[\\\\'\"]*a[\\\\'\"]*t)|t[\\\\'\"]*(?:c[\\\\'\"]*(?:p[\\\\'\"]*(?:t[\\\\'\"]*r[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*u[\\\\'\"]*t[\\\\'\"]*e|i[\\\\'\"]*n[\\\\'\"]*g)|s[\\\\'\"]*h)|r[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*u[\\\\'\"]*t[\\\\'\"]*e(?:[\\\\'\"]*6)?|i[\\\\'\"]*m[\\\\'\"]*e(?:[\\\\'\"]*o[\\\\'\"]*u[\\\\'\"]*t)?|a[\\\\'\"]*(?:i[\\\\'\"]*l(?:[\\\\'\"]*f)?|r)|e[\\\\'\"]*l[\\\\'\"]*n[\\\\'\"]*e[\\\\'\"]*t)|r[\\\\'\"]*(?:e[\\\\'\"]*(?:p[\\\\'\"]*(?:l[\\\\'\"]*a[\\\\'\"]*c[\\\\'\"]*e|e[\\\\'\"]*a[\\\\'\"]*t)|a[\\\\'\"]*l[\\\\'\"]*p[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*h|n[\\\\'\"]*a[\\\\'\"]*m[\\\\'\"]*e)|u[\\\\'\"]*b[\\\\'\"]*y(?:[\\\\'\"]*(?:1(?:[\\\\'\"]*[89])?|2[\\\\'\"]*[012]))?|m[\\\\'\"]*(?:u[\\\\'\"]*s[\\\\'\"]*e|d[\\\\'\"]*i)[\\\\'\"]*r|n[\\\\'\"]*a[\\\\'\"]*n[\\\\'\"]*o|s[\\\\'\"]*y[\\\\'\"]*n[\\\\'\"]*c|c[\\\\'\"]*p)|b[\\\\'\"]*(?:z[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e|c[\\\\'\"]*a[\\\\'\"]*t)|s[\\\\'\"]*d[\\\\'\"]*(?:c[\\\\'\"]*a[\\\\'\"]*t|i[\\\\'\"]*f[\\\\'\"]*f|t[\\\\'\"]*a[\\\\'\"]*r)|u[\\\\'\"]*i[\\\\'\"]*l[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*n|a[\\\\'\"]*s[\\\\'\"]*h)|m[\\\\'\"]*(?:y[\\\\'\"]*s[\\\\'\"]*q[\\\\'\"]*l[\\\\'\"]*(?:d[\\\\'\"]*u[\\\\'\"]*m[\\\\'\"]*p(?:[\\\\'\"]*s[\\\\'\"]*l[\\\\'\"]*o[\\\\'\"]*w)?|h[\\\\'\"]*o[\\\\'\"]*t[\\\\'\"]*c[\\\\'\"]*o[\\\\'\"]*p[\\\\'\"]*y|a[\\\\'\"]*d[\\\\'\"]*m[\\\\'\"]*i[\\\\'\"]*n|s[\\\\'\"]*h[\\\\'\"]*o[\\\\'\"]*w)|l[\\\\'\"]*o[\\\\'\"]*c[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*e|a[\\\\'\"]*i[\\\\'\"]*l[\\\\'\"]*q)|u[\\\\'\"]*(?:n[\\\\'\"]*(?:c[\\\\'\"]*o[\\\\'\"]*m[\\\\'\"]*p[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|l[\\\\'\"]*z[\\\\'\"]*m[\\\\'\"]*a|a[\\\\'\"]*m[\\\\'\"]*e|r[\\\\'\"]*a[\\\\'\"]*r|s[\\\\'\"]*e[\\\\'\"]*t|z[\\\\'\"]*i[\\\\'\"]*p|x[\\\\'\"]*z)|s[\\\\'\"]*e[\\\\'\"]*r[\\\\'\"]*(?:(?:a[\\\\'\"]*d|m[\\\\'\"]*o)[\\\\'\"]*d|d[\\\\'\"]*e[\\\\'\"]*l))|x[\\\\'\"]*(?:z(?:[\\\\'\"]*(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|d[\\\\'\"]*(?:i[\\\\'\"]*f[\\\\'\"]*f|e[\\\\'\"]*c)|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e))?|a[\\\\'\"]*r[\\\\'\"]*g[\\\\'\"]*s)|z[\\\\'\"]*(?:(?:(?:[ef][\\\\'\"]*)?g[\\\\'\"]*r[\\\\'\"]*e|i)[\\\\'\"]*p|c[\\\\'\"]*(?:a[\\\\'\"]*t|m[\\\\'\"]*p)|d[\\\\'\"]*i[\\\\'\"]*f[\\\\'\"]*f|l[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*s|m[\\\\'\"]*o[\\\\'\"]*r[\\\\'\"]*e|r[\\\\'\"]*u[\\\\'\"]*n|s[\\\\'\"]*h)|f[\\\\'\"]*(?:t[\\\\'\"]*p[\\\\'\"]*(?:s[\\\\'\"]*t[\\\\'\"]*a[\\\\'\"]*t[\\\\'\"]*s|w[\\\\'\"]*h[\\\\'\"]*o)|i[\\\\'\"]*l[\\\\'\"]*e[\\\\'\"]*t[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*t|e[\\\\'\"]*t[\\\\'\"]*c[\\\\'\"]*h|g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p)|c[\\\\'\"]*(?:o[\\\\'\"]*(?:m[\\\\'\"]*m[\\\\'\"]*a[\\\\'\"]*n[\\\\'\"]*d|p[\\\\'\"]*r[\\\\'\"]*o[\\\\'\"]*c)|u[\\\\'\"]*r[\\\\'\"]*l|s[\\\\'\"]*h|c)|e[\\\\'\"]*(?:g[\\\\'\"]*r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*h[\\\\'\"]*o|v[\\\\'\"]*a[\\\\'\"]*l|x[\\\\'\"]*e[\\\\'\"]*c|n[\\\\'\"]*v)|d[\\\\'\"]*(?:m[\\\\'\"]*e[\\\\'\"]*s[\\\\'\"]*g|a[\\\\'\"]*s[\\\\'\"]*h|i[\\\\'\"]*f[\\\\'\"]*f|o[\\\\'\"]*a[\\\\'\"]*s)|g[\\\\'\"]*(?:z[\\\\'\"]*(?:c[\\\\'\"]*a[\\\\'\"]*t|i[\\\\'\"]*p)|r[\\\\'\"]*e[\\\\'\"]*p|c[\\\\'\"]*c)|j[\\\\'\"]*(?:o[\\\\'\"]*b[\\\\'\"]*s[\\\\'\"]*\s+[\\\\'\"]*-[\\\\'\"]*x|a[\\\\'\"]*v[\\\\'\"]*a)|w[\\\\'\"]*(?:h[\\\\'\"]*o[\\\\'\"]*a[\\\\'\"]*m[\\\\'\"]*i|g[\\\\'\"]*e[\\\\'\"]*t|3[\\\\'\"]*m)|i[\\\\'\"]*r[\\\\'\"]*b(?:[\\\\'\"]*(?:1(?:[\\\\'\"]*[89])?|2[\\\\'\"]*[012]))?|o[\\\\'\"]*n[\\\\'\"]*i[\\\\'\"]*n[\\\\'\"]*t[\\\\'\"]*r|h[\\\\'\"]*(?:e[\\\\'\"]*a[\\\\'\"]*d|u[\\\\'\"]*p)|v[\\\\'\"]*i[\\\\'\"]*(?:g[\\\\'\"]*r|p[\\\\'\"]*w)|G[\\\\'\"]*E[\\\\'\"]*T)[\\\\'\"]*(?:\s|;|\||&|<|>)" \ "id:932150,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Direct Unix Command Execution',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Unix shell snippets ] # # Detect some common sequences found in shell commands and scripts. # # Some commands which were restricted in earlier rules due to FP, # have been added here with their full path, in order to catch some # cases where the full path is sent. # # This rule is also triggered by an Apache Struts Remote Code Execution exploit: # [ Apache Struts vulnerability CVE-2017-9805 - Exploit tested: https://www.exploit-db.com/exploits/42627 ] # # This rule is also triggered by an Oracle WebLogic Remote Command Execution exploit: # [ Oracle WebLogic vulnerability CVE-2017-10271 - Exploit tested: https://www.exploit-db.com/exploits/43458 ] SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile unix-shell.data" \ "id:932160,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:cmdLine,t:normalizePath,t:lowercase,\ msg:'Remote Command Execution: Unix Shell Code Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ Shellshock vulnerability (CVE-2014-6271 and CVE-2014-7169) ] # # Detect exploitation of "Shellshock" GNU Bash RCE vulnerability. # # Based on ModSecurity rules created by Red Hat. # Permission for use was granted by Martin Prpic # # https://access.redhat.com/articles/1212303 # SecRule REQUEST_HEADERS|REQUEST_LINE "@rx ^\(\s*\)\s+{" \ "id:932170,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,\ msg:'Remote Command Execution: Shellshock (CVE-2014-6271)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule ARGS_NAMES|ARGS|FILES_NAMES "@rx ^\(\s*\)\s+{" \ "id:932171,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,t:urlDecodeUni,\ msg:'Remote Command Execution: Shellshock (CVE-2014-6271)',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ Restricted File Upload ]=- # # Detects attempts to upload a file with a forbidden filename. # # Many application contain Unrestricted File Upload vulnerabilities. # https://www.owasp.org/index.php/Unrestricted_File_Upload # # These might be abused to upload configuration files or other files # that affect the behavior of the web server, possibly causing remote # code execution. # SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X-File-Name \ "@pmFromFile restricted-upload.data" \ "id:932180,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'Restricted File Upload Attempt',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.lfi_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:932013,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:932014,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:932015,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:932016,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # # Missing Unix commands have been added to a new word list i.e. # util/regexp-assemble/regexp-932106.txt # These commands may have a higher risk of false positives. # Therefore, they have been split off to a separate rule in PL3. # For explanation of this rule, see rule 932100. # # To rebuild the word list regexp: # cd util/regexp-assemble # cat regexp-932106.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl # # Then insert the assembled regexp into this template: # # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]* # [regexp assembled from util/regexp-assemble/regexp-932106.txt] # \b" \ # # This rule is a stricter sibling of rule 932100. SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:;|\{|\||\|\||&|&&|\n|\r|\$\(|\$\(\(|`|\${|<\(|>\(|\(\s*\))\s*(?:{|\s*\(\s*|\w+=(?:[^\s]*|\$.*|\$.*|<.*|>.*|\'.*\'|\".*\")\s+|!\s*|\$)*\s*(?:'|\")*(?:[\?\*\[\]\(\)\-\|+\w'\"\./\\\\]+/)?[\\\\'\"]*(?:(?:(?:a[\\\\'\"]*p[\\\\'\"]*t[\\\\'\"]*i[\\\\'\"]*t[\\\\'\"]*u[\\\\'\"]*d|u[\\\\'\"]*p[\\\\'\"]*2[\\\\'\"]*d[\\\\'\"]*a[\\\\'\"]*t)[\\\\'\"]*e|d[\\\\'\"]*n[\\\\'\"]*f|v[\\\\'\"]*i)[\\\\'\"]*(?:\s|<|>).*|p[\\\\'\"]*(?:a[\\\\'\"]*c[\\\\'\"]*m[\\\\'\"]*a[\\\\'\"]*n[\\\\'\"]*(?:\s|<|>).*|w[\\\\'\"]*d|s)|w[\\\\'\"]*(?:(?:\s|<|>).*|h[\\\\'\"]*o))\b" \ "id:932106,\ phase:2,\ block,\ capture,\ t:none,\ msg:'Remote Command Execution: Unix Command Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # -=[ Bypass Rule 930120 (wildcard) ]=- # # When Paranoia Level is set to 1 and 2, a Remote Command Execution # could be exploited bypassing rule 930120 (OS File Access Attempt) # by using wildcard characters. # # In some other cases, it could be bypassed even if the Paranoia Level is set to 3. # Please, keep in mind that this rule could lead to many false positives. # SecRule ARGS "@rx (?:/|\\\\)(?:[\?\*]+[a-z/\\\\]+|[a-z/\\\\]+[\?\*]+)" \ "id:932190,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,t:urlDecodeUni,t:normalizePath,t:cmdLine,\ msg:'Remote Command Execution: Wildcard bypass technique attempt',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-shell',\ tag:'platform-unix',\ tag:'attack-rce',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION',\ tag:'WASCTC/WASC-31',\ tag:'OWASP_TOP_10/A1',\ tag:'PCI/6.5.2',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ severity:'CRITICAL',\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:932017,phase:1,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:932018,phase:2,pass,nolog,skipAfter:END-REQUEST-932-APPLICATION-ATTACK-RCE" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-932-APPLICATION-ATTACK-RCE" modsecurity-crs-3.2.0/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf000066400000000000000000001003561355660542300234660ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933011,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:933012,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ PHP Injection Attacks ]=- # # [ References ] # http://rips-scanner.sourceforge.net/ # https://www.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Executionh # # # [ PHP Open Tag Found ] # # Detects PHP open tags "', but # this resulted in false positives which were difficult to prevent. # Therefore, that pattern is now checked by rule 933190 in paranoia levels # 3 or higher. # # Not supported by re2 (?!re). # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:<\?(?!xml\s)|<\?php|\[(?:/|\\\\)?php\])" \ "id:933100,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:lowercase,\ msg:'PHP Injection Attack: PHP Open Tag Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Script Uploads ] # # Block file uploads with filenames ending in PHP related extensions # (.php, .phps, .phtml, .php5 etc). # # Many application contain Unrestricted File Upload vulnerabilities. # https://www.owasp.org/index.php/Unrestricted_File_Upload # # Attackers may use such a vulnerability to achieve remote code execution # by uploading a .php file. If the upload storage location is predictable # and not adequately protected, the attacker may then request the uploaded # .php file and have the code within it executed on the server. # # Also block files with just dot (.) characters after the extension: # https://community.rapid7.com/community/metasploit/blog/2013/08/15/time-to-patch-joomla # # Some AJAX uploaders use the nonstandard request headers X-Filename, # X_Filename, or X-File-Name to transmit the file name to the server; # scan these request headers as well as multipart/form-data file names. # SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.(?:php\d*|phtml)\.*$" \ "id:933110,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Script File Upload Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Configuration Directives ] # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-config-directives.data" \ "id:933120,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:normalisePath,t:lowercase,\ msg:'PHP Injection Attack: Configuration Directive Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ chain" SecRule MATCHED_VARS "@pm =" \ "capture,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Variables ] # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-variables.data" \ "id:933130,\ phase:2,\ block,\ capture,\ t:none,t:normalisePath,t:urlDecodeUni,t:lowercase,\ msg:'PHP Injection Attack: Variables Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP I/O Streams ] # # The "php://" syntax can be used to refer to various objects, such as local files (for LFI), # remote urls (for RFI), or standard input/request body. Its occurrence indicates a possible attempt # to either inject PHP code or exploit a file inclusion vulnerability in a PHP web app. # # Examples: # php://filter/resource=./../../../wp-config.php # php://filter/resource=http://www.example.com # php://stdin # php://input # # http://php.net/manual/en/wrappers.php.php # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)php://(?:std(?:in|out|err)|(?:in|out)put|fd|memory|temp|filter)" \ "id:933140,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: I/O Stream Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Wrappers ] # # PHP comes with many built-in wrappers for various URL-style protocols for use with the filesystem # functions such as fopen(), copy(), file_exists() and filesize(). Abusing of PHP wrappers like phar:// # could lead to RCE as describled by Sam Thomas at BlackHat USA 2018 (https://bit.ly/2yaKV5X), even # wrappers like zlib://, glob://, rar://, zip://, etc... could lead to LFI and expect:// to RCE. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:zlib|glob|phar|ssh2|rar|ogg|expect|zip)://" \ "id:933200,\ phase:2,\ block,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,t:cmdLine,\ msg:'PHP Injection Attack: Wrapper scheme detected',\ logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions ] # # Detecting PHP function names is useful to block PHP code injection attacks. # There are many PHP functions. We have to strike a balance between robust detection # of PHP code in content, and the risk of false positives. # # The list of PHP functions is divided into four groups of varying attack/false positive risk. # Four separate rules are used to detect these groups of functions: # # - Rule 933150: ~40 words highly common to PHP injection payloads and extremely rare in # natural language or other contexts. # Examples: 'base64_decode', 'file_get_contents'. # These words are detected as a match directly using @pmFromFile. # Function names are defined in php-function-names-933150.data # # - Rule 933160: ~220 words which are common in PHP code, but have a higher chance to cause # false positives in natural language or other contexts. # Examples: 'chr', 'eval'. # To mitigate false positives, a regexp looks for PHP function syntax, e.g. 'eval()'. # Regexp is generated from function names in util/regexp-assemble/regexp-933160.data # # - Rule 933151: ~1300 words of lesser importance. This includes most PHP functions and keywords. # Examples: 'addslashes', 'array_diff'. # For performance reasons, the @pmFromFile operator is used, and many functions from lesser # used PHP extensions are removed. # To mitigate false positives, we only match when the '(' character is also found. # This rule only runs in paranoia level 2 or higher. # Function names are defined in php-function-names-933151.data # # - Rule 933161: ~200 words with short or trivial names, possibly leading to false positives. # Examples: 'abs', 'cos'. # To mitigate false positives, a regexp matches on function syntax, e.g. 'abs()'. # This rule only runs in paranoia level 3 or higher. # Regexp is generated from function names in util/regexp-assemble/regexp-933161.data # # # [ PHP Functions: High-Risk PHP Function Names ] # # Rule 933150 contains a small list of function names which are highly indicative of a PHP # injection attack, for example 'base64_decode'. # We block these function names outright, without using a complex regexp or chain. # This could make the detection a bit more robust against possible bypasses. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-function-names-933150.data" \ "id:933150,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: High-Risk PHP Function Name Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: High-Risk PHP Function Calls ] # # Some PHP function names have a certain risk of false positives, due to short # names, full or partial overlap with common natural language terms, uses in # other contexts, et cetera. Some examples are 'eval', 'exec', 'system'. # # For these function names, we apply a regexp to look for PHP function syntax. # The regexp looks for a word boundary and adjoining parentheses. # For instance, we want to block 'eval()', but we want to allow 'medieval()'. # # We have to be careful of possible bypasses using comment syntax. Examples: # # system(...) # system (...) # system\t(...) # system /*comment*/ (...) # system /*multiline \n comment*/ (...) # system //comment \n (...) # system #comment \n (...) # # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2017-9791 - Exploit tested: https://www.exploit-db.com/exploits/42324 ] # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45260 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # # Regexp generated from util/regexp-assemble/regexp-933160.data using Regexp::Assemble. # See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. # # Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble # output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:s(?:e(?:t(?:_(?:e(?:xception|rror)_handler|magic_quotes_runtime|include_path)|defaultstub)|ssion_s(?:et_save_handler|tart))|qlite_(?:(?:(?:unbuffered|single|array)_)?query|create_(?:aggregate|function)|p?open|exec)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|implexml_load_(?:string|file)|ocket_c(?:onnect|reate)|h(?:ow_sourc|a1_fil)e|pl_autoload_register|ystem)|p(?:r(?:eg_(?:replace(?:_callback(?:_array)?)?|match(?:_all)?|split)|oc_(?:(?:terminat|clos|nic)e|get_status|open)|int_r)|o(?:six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|mk(?:fifo|nod)|ttyname|kill)|pen)|hp(?:_(?:strip_whitespac|unam)e|version|info)|g_(?:(?:execut|prepar)e|connect|query)|a(?:rse_(?:ini_file|str)|ssthru)|utenv)|r(?:unkit_(?:function_(?:re(?:defin|nam)e|copy|add)|method_(?:re(?:defin|nam)e|copy|add)|constant_(?:redefine|add))|e(?:(?:gister_(?:shutdown|tick)|name)_function|ad(?:(?:gz)?file|_exif_data|dir))|awurl(?:de|en)code)|i(?:mage(?:createfrom(?:(?:jpe|pn)g|x[bp]m|wbmp|gif)|(?:jpe|pn)g|g(?:d2?|if)|2?wbmp|xbm)|s_(?:(?:(?:execut|write?|read)ab|fi)le|dir)|ni_(?:get(?:_all)?|set)|terator_apply|ptcembed)|g(?:et(?:_(?:c(?:urrent_use|fg_va)r|meta_tags)|my(?:[gpu]id|inode)|(?:lastmo|cw)d|imagesize|env)|z(?:(?:(?:defla|wri)t|encod|fil)e|compress|open|read)|lob)|a(?:rray_(?:u(?:intersect(?:_u?assoc)?|diff(?:_u?assoc)?)|intersect_u(?:assoc|key)|diff_u(?:assoc|key)|filter|reduce|map)|ssert(?:_options)?)|h(?:tml(?:specialchars(?:_decode)?|_entity_decode|entities)|(?:ash(?:_(?:update|hmac))?|ighlight)_file|e(?:ader_register_callback|x2bin))|f(?:i(?:le(?:(?:[acm]tim|inod)e|(?:_exist|perm)s|group)?|nfo_open)|tp_(?:nb_(?:ge|pu)|connec|ge|pu)t|(?:unction_exis|pu)ts|write|open)|o(?:b_(?:get_(?:c(?:ontents|lean)|flush)|end_(?:clean|flush)|clean|flush|start)|dbc_(?:result(?:_all)?|exec(?:ute)?|connect)|pendir)|m(?:b_(?:ereg(?:_(?:replace(?:_callback)?|match)|i(?:_replace)?)?|parse_str)|(?:ove_uploaded|d5)_file|ethod_exists|ysql_query|kdir)|e(?:x(?:if_(?:t(?:humbnail|agname)|imagetype|read_data)|ec)|scapeshell(?:arg|cmd)|rror_reporting|val)|c(?:url_(?:file_create|exec|init)|onvert_uuencode|reate_function|hr)|u(?:n(?:serialize|pack)|rl(?:de|en)code|[ak]?sort)|(?:json_(?:de|en)cod|debug_backtrac|tmpfil)e|b(?:(?:son_(?:de|en)|ase64_en)code|zopen)|var_dump)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \ "id:933160,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: High-Risk PHP Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Object Injection ] # # PHP Object Injection is an application level vulnerability that could allow # an attacker to perform different kinds of malicious attacks, such as # Code Injection, SQL Injection, Path Traversal and Application Denial of Service, # depending on the context. # # The vulnerability occurs when user-supplied input is not properly sanitized # before being passed to the unserialize() PHP function. Since PHP allows object # serialization, attackers could pass ad-hoc serialized strings to a vulnerable # unserialize() call, resulting in an arbitrary PHP object(s) injection into the # application scope. # # https://www.owasp.org/index.php/PHP_Object_Injection # # In serialized form, PHP objects have the following format: # # O:8:"stdClass":1:{s:1:"a";i:2;} # O:3:"Foo":0:{} # # Also detected are PHP objects with a custom unserializer: # http://www.phpinternalsbook.com/classes_objects/serialization.html # These have the following format: # # C:11:"ArrayObject":37:{x:i:0;a:1:{s:1:"a";s:1:"b";};m:a:0:{}} # C:3:"Foo":23:{s:15:"My private data";} # # HTTP headers are inspected, since PHP object injection vulnerabilities have been # found in applications parsing them: # https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8562 (User-Agent header) # https://www.exploit-db.com/exploits/39033/ (X-Forwarded-For header) # http://karmainsecurity.com/KIS-2015-10 (Host header) # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS|ARGS_NAMES|ARGS|XML:/* "@rx [oOcC]:\d+:\".+?\":\d+:{.*}" \ "id:933170,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Serialized Object Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: Variable Function Calls ] # # PHP 'variable functions' provide an alternate syntax for calling PHP functions. # http://php.net/manual/en/functions.variable-functions.php # # An attacker may use variable function syntax to evade detection of function # names during exploitation of a remote code execution vulnerability. # An example to use the 'file_get_contents' function while evading rule 933150: # # $fn = 'file_' . 'get_' . 'contents'; # echo $fn('wp-co' . 'nfig.php'); # # Some examples from obfuscated malware: # # $OOO0000O0(...) # @$b374k(...) # $_[@-_]($_[@!+_] ) # # A breakdown of the regular expression: # # \$+ # The variable's '$' char, or multiple '$' for 'variable variables': # http://php.net/manual/en/language.variables.variable.php # (?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\s*{.+}) # One of the following: # - A variable name; regexp from http://php.net/language.variables.basics # - A nonempty expression for variable variables: ${'fn'} or $ {'fn'} # (?:\s|\[.+\]|{.+}|/\*.*\*/|//.*|#.*)* # Optional whitespace, array access, or comments # \(.*\) # Parentheses optionally containing function parameters # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx \$+(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\s*{.+})(?:\s|\[.+\]|{.+}|/\*.*\*/|//.*|#.*)*\(.*\)" \ "id:933180,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # [ PHP Functions: Variable Function Prevent Bypass ] # # Referring to https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/ # the rule 933180 could be bypassed by using the following payloads: # # - (system)('uname') # - (sy.(st).em)('uname') # - (string)"system"('uname') # - define('x', 'sys' . 'tem');(x)/* comment */('uname') # - $y = 'sys'.'tem';($y)('uname') # - define('z', [['sys' .'tem']]);(z)[0][0]('uname'); # - (system)(ls) # - (/**/system)(ls/**/); # - (['system'])[0]('uname'); # - (++[++system++][++0++])++{/*dsasd*/0}++(++ls++); # # This rule blocks all payloads above and avoids to block values like: # # - [ACME] this is a test (just a test) # - Test (with two) rounded (brackets) # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?:(?:\(|\[)[a-zA-Z0-9_.$\"'\[\](){}/*\s]+(?:\)|\])[0-9_.$\"'\[\](){}/*\s]*\([a-zA-Z0-9_.$\"'\[\](){}/*\s].*\)|\([\s]*string[\s]*\)[\s]*(?:\"|'))" \ "id:933210,\ phase:2,\ block,\ capture,\ t:none,t:urlDecode,t:replaceComments,t:compressWhitespace,\ msg:'PHP Injection Attack: Variable Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933013,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:933014,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # # [ PHP Functions: Medium-Risk PHP Function Names ] # # In paranoia level 2, we add additional checks for most PHP functions. # # The size of the PHP function list is considerable. # Even after excluding the more obscure PHP extensions, 1300+ functions remain. # For performance and maintenance reasons, this rule does not use a regexp, # but uses a phrase file (@pmFromFile), and additionally looks for an '(' character # in the matched variable. # # This approach carries some risk for false positives. Therefore, the function list # has been curated to remove words closely matching natural language and terms often # used in other contexts. # # This rule is a stricter sibling of rule 933150. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@pmFromFile php-function-names-933151.data" \ "id:933151,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: Medium-Risk PHP Function Name Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ tag:'paranoia-level/2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ chain" SecRule MATCHED_VARS "@pm (" \ "capture,\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933015,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:933016,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # # # [ PHP Variables: Common Variable Indexes ] # # In paranoia level 3, we add additional checks for parameters to many PHP variables. # # # One of the more common variables used within attacks on PHP is $_SERVER. Because # of how many different ways PHP has for executing variables (variable variables, # etc) often just looking for $_SERVER will be less effective than looking for the # various indexes within $_SERVER. This rule checks for these indexes. # This rule is located in PL 3 because often developers will use these names as # parameter names or values and this will lead to false positives. # Because this list is not expected to change and it is limited in size we use a # regex in this case to look for these values whereas in its sibling rule we use # @pmFromFile for flexibility and performance. # # To rebuild the regexp: # cd util/regexp-assemble # ./regexp-assemble.pl < regexp-933131.data # # This rule is a stricter sibling of rule 933130. SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:HTTP_(?:ACCEPT(?:_(?:ENCODING|LANGUAGE|CHARSET))?|(?:X_FORWARDED_FO|REFERE)R|(?:USER_AGEN|HOS)T|CONNECTION|KEEP_ALIVE)|PATH_(?:TRANSLATED|INFO)|ORIG_PATH_INFO|QUERY_STRING|REQUEST_URI|AUTH_TYPE)" \ "id:933131,\ phase:2,\ block,\ capture,\ t:none,t:normalisePath,t:urlDecodeUni,\ msg:'PHP Injection Attack: Variables Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # [ PHP Functions: Low-Value PHP Function Calls ] # # In paranoia level 3, we add additional checks for the remaining PHP functions. # # Most of these function names are likely to cause false positives in natural text # or common parameter values, such as 'abs', 'copy', 'date', 'key', 'max', 'min'. # Therefore, these function names are not scanned in lower paranoia levels. # # To mitigate the risk of false positives somewhat, a regexp is used to look for # PHP function syntax. (See rule 933160 for a description.) # # This rule is a stricter sibling of rule 933160. # # This rule is also triggered by the following exploit(s): # [ Apache Struts vulnerability CVE-2018-11776 - Exploit tested: https://www.exploit-db.com/exploits/45262 ] # [ SAP CRM Java vulnerability CVE-2018-2380 - Exploit tested: https://www.exploit-db.com/exploits/44292 ] # # Regexp generated from util/regexp-assemble/regexp-933161.data using Regexp::Assemble. # See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. # # Note that after assemble, PHP function syntax pre/postfix is added to the Regexp::Assemble # output. Example: "@rx (?i)\bASSEMBLE_OUTPUT_HERE(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:i(?:s(?:_(?:in(?:t(?:eger)?|finite)|n(?:u(?:meric|ll)|an)|(?:calla|dou)ble|s(?:calar|tring)|f(?:inite|loat)|re(?:source|al)|l(?:ink|ong)|a(?:rray)?|object|bool)|set)|n(?:(?:clud|vok)e|t(?:div|val))|(?:mplod|dat)e|conv)|s(?:t(?:r(?:(?:le|sp)n|coll)|at)|(?:e(?:rializ|ttyp)|huffl)e|i(?:milar_text|zeof|nh?)|p(?:liti?|rintf)|(?:candi|ubst)r|y(?:mlink|slog)|o(?:undex|rt)|leep|rand|qrt)|f(?:ile(?:(?:siz|typ)e|owner|pro)|l(?:o(?:atval|ck|or)|ush)|(?:rea|mo)d|t(?:ell|ok)|unction|close|gets|stat|eof)|c(?:h(?:o(?:wn|p)|eckdate|root|dir|mod)|o(?:(?:(?:nsta|u)n|mpac)t|sh?|py)|lose(?:dir|log)|(?:urren|ryp)t|eil)|e(?:x(?:(?:trac|i)t|p(?:lode)?)|a(?:ster_da(?:te|ys)|ch)|r(?:ror_log|egi?)|mpty|cho|nd)|l(?:o(?:g(?:1[0p])?|caltime)|i(?:nk(?:info)?|st)|(?:cfirs|sta)t|evenshtein|trim)|d(?:i(?:(?:skfreespac)?e|r(?:name)?)|e(?:fined?|coct)|(?:oubleva)?l|ate)|r(?:e(?:(?:quir|cod|nam)e|adlin[ek]|wind|set)|an(?:ge|d)|ound|sort|trim)|m(?:b(?:split|ereg)|i(?:crotime|n)|a(?:i[ln]|x)|etaphone|y?sql|hash)|u(?:n(?:(?:tain|se)t|iqid|link)|s(?:leep|ort)|cfirst|mask)|a(?:s(?:(?:se|o)rt|inh?)|r(?:sort|ray)|tan[2h]?|cosh?|bs)|t(?:e(?:xtdomain|mpnam)|a(?:int|nh?)|ouch|ime|rim)|h(?:e(?:ader(?:s_(?:lis|sen)t)?|brev)|ypot|ash)|p(?:a(?:thinfo|ck)|r(?:intf?|ev)|close|o[sw]|i)|g(?:et(?:t(?:ext|ype)|date)|mdate)|o(?:penlog|ctdec|rd)|b(?:asename|indec)|n(?:atsor|ex)t|k(?:sort|ey)|quotemeta|wordwrap|virtual|join)(?:\s|/\*.*\*/|//.*|#.*)*\(.*\)" \ "id:933161,\ phase:2,\ block,\ capture,\ t:none,\ msg:'PHP Injection Attack: Low-Value PHP Function Call Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # # [ PHP Script Uploads: Superfluous extension ] # # Block file uploads with PHP related extensions (.php, .phps, .phtml, # .php5 etc) anywhere in the name, followed by a dot. # # Example: index.php.tmp # # Uploading of such files can lead to remote code execution if # Apache is configured with AddType and MultiViews, as Apache will # automatically do a filename match when the extension is unknown. # This configuration is fortunately not common in modern installs. # # Blocking these file names might lead to more false positives. # # Some AJAX uploaders use the nonstandard request headers X-Filename, # X_Filename, or X-File-Name to transmit the file name to the server; # scan these request headers as well as multipart/form-data file names. # # This rule is a stricter sibling of rule 933110. # SecRule FILES|REQUEST_HEADERS:X-Filename|REQUEST_HEADERS:X_Filename|REQUEST_HEADERS:X.Filename|REQUEST_HEADERS:X-File-Name "@rx .*\.(?:php\d*|phtml)\..*$" \ "id:933111,\ phase:2,\ block,\ capture,\ t:none,t:lowercase,\ msg:'PHP Injection Attack: PHP Script File Upload Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" # [ PHP Closing Tag Found ] # # http://www.php.net/manual/en/language.basic-syntax.phptags.php # # This check was extracted from 933100 (paranoia level 1), since the # checked sequence '?>' commonly causes false positives. # See issue #654 for discussion. # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pm ?>" \ "id:933190,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,\ msg:'PHP Injection Attack: PHP Closing Tag Found',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-php',\ tag:'platform-multi',\ tag:'attack-injection-php',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/PHP_INJECTION',\ tag:'OWASP_TOP_10/A1',\ tag:'paranoia-level/3',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.php_injection_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933017,phase:1,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:933018,phase:2,pass,nolog,skipAfter:END-REQUEST-933-APPLICATION-ATTACK-PHP" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-933-APPLICATION-ATTACK-PHP" modsecurity-crs-3.2.0/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf000066400000000000000000000075231355660542300240240ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:934011,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:934012,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # [ Insecure unserialization / generic RCE signatures ] # # Libraries performing insecure unserialization: # - node-serialize: _$$ND_FUNC$$_ (CVE-2017-5941) # - funcster: __js_function # # See: # https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/ # https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/ # # Some generic snippets used: # - function() { # - new Function( # - eval( # - String.fromCharCode( # # Last two are used by nodejsshell.py, # https://github.com/ajinabraham/Node.Js-Security-Course/blob/master/nodejsshell.py # # As base64 is sometimes (but not always) used to encode serialized values, # use multiMatch and t:base64decode. # # Regexp generated from util/regexp-assemble/regexp-934100.data using Regexp::Assemble. # See https://coreruleset.org/20190826/optimizing-regular-expressions/ for usage. SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:(?:_(?:\$\$ND_FUNC\$\$_|_js_function)|(?:new\s+Function|\beval)\s*\(|String\s*\.\s*fromCharCode|function\s*\(\s*\)\s*{|this\.constructor)|module\.exports\s*=)" \ "id:934100,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:base64Decode,\ msg:'Node.js Injection Attack',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-javascript',\ tag:'platform-multi',\ tag:'attack-rce',\ tag:'attack-injection-nodejs',\ tag:'OWASP_CRS/WEB_ATTACK/NODEJS_INJECTION',\ tag:'OWASP_TOP_10/A1',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ multiMatch,\ setvar:'tx.rce_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:934013,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:934014,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:934015,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 3" "id:934016,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" # # -= Paranoia Level 3 =- (apply only when tx.executing_paranoia_level is sufficiently high: 3 or higher) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:934017,phase:1,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 4" "id:934018,phase:2,pass,nolog,skipAfter:END-REQUEST-934-APPLICATION-ATTACK-NODEJS" # # -= Paranoia Level 4 =- (apply only when tx.executing_paranoia_level is sufficiently high: 4 or higher) # # # -= Paranoia Levels Finished =- # SecMarker "END-REQUEST-934-APPLICATION-ATTACK-NODEJS" modsecurity-crs-3.2.0/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf000066400000000000000000001244751355660542300235230ustar00rootroot00000000000000# ------------------------------------------------------------------------ # OWASP ModSecurity Core Rule Set ver.3.2.0 # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. # # The OWASP ModSecurity Core Rule Set is distributed under # Apache Software License (ASL) version 2 # Please see the enclosed LICENSE file for full details. # ------------------------------------------------------------------------ # # -= Paranoia Level 0 (empty) =- (apply unconditionally) # SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:941011,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 1" "id:941012,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" # # -= Paranoia Level 1 (default) =- (apply only when tx.executing_paranoia_level is sufficiently high: 1 or higher) # # # -=[ Libinjection - XSS Detection ]=- # # Ref: https://github.com/client9/libinjection # Ref: https://speakerdeck.com/ngalbreath/libinjection-from-sqli-to-xss # # -=[ Targets ]=- # # 941100: PL1 : REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/| # REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent| # ARGS_NAMES|ARGS|XML:/* # # 941101: PL2 : REQUEST_HEADERS:Referer # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@detectXSS" \ "id:941100,\ phase:2,\ block,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Attack Detected via libinjection',\ logdata:'Matched Data: XSS data found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 1 ]=- # http://xssplayground.net23.net/xssfilter.html # script tag based XSS vectors, e.g., # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_FILENAME|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)]*>[\s\S]*?" \ "id:941110,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Filter - Category 1: Script Tag Vector',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 2 ]=- # XSS vectors making use of event handlers like onerror, onload etc, e.g., # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\"'`;\/0-9=\x0B\x09\x0C\x3B\x2C\x28\x3B]+on[a-zA-Z]+[\s\x0B\x09\x0C\x3B\x2C\x28\x3B]*?=" \ "id:941120,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Filter - Category 2: Event Handler Vector',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 3 ]=- # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx (?i)[\s\S]((?:x(?:link:href|html|mlns)|!ENTITY.*?(?:SYSTEM|PUBLIC)|data:text\/html|formaction|\@import|base64)\b|pattern\b.*?=)" \ "id:941130,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Filter - Category 3: Attribute Vector',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 4 ]=- # XSS vectors making use of javascript uri and tags, e.g.,

# SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:<(?:(?:apple|objec)t|isindex|embed|style|form|meta)\b[^>]*?>[\s\S]*?|(?:=|U\s*?R\s*?L\s*?\()\s*?[^>]*?\s*?S\s*?C\s*?R\s*?I\s*?P\s*?T\s*?:)" \ "id:941140,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Filter - Category 4: Javascript URI Vector',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # -=[ NoScript XSS Filters ]=- # Ref: http://noscript.net/ # # [NoScript InjectionChecker] HTML injection # # Regexp generated from util/regexp-assemble/regexp-941160.data using Regexp::Assemble. # To rebuild the regexp: # cd util/regexp-assemble # ./regexp-assemble.pl regexp-941160.data # Note that after assemble an ignore case flag (i) is added to the to the Regexp::Assemble output: # Add ignore case flag between '?' and ':': "(?i:...)" # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)(?:on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)|op)|i(?:s(?:c(?:hargingtimechange|onnect(?:ing|ed))|abled)|aling)|ata(?:setc(?:omplete|hanged)|(?:availabl|chang)e|error)|urationchange|ownloading|blclick)|Moz(?:M(?:agnifyGesture(?:Update|Start)?|ouse(?:PixelScroll|Hittest))|S(?:wipeGesture(?:Update|Start|End)?|crolledAreaChanged)|(?:(?:Press)?TapGestur|BeforeResiz)e|EdgeUI(?:C(?:omplet|ancel)|Start)ed|RotateGesture(?:Update|Start)?|A(?:udioAvailable|fterPaint))|c(?:o(?:m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|n(?:t(?:rolselect|extmenu)|nect(?:ing|ed))|py)|a(?:(?:llschang|ch)ed|nplay(?:through)?|rdstatechange)|h(?:(?:arging(?:time)?ch)?ange|ecking)|(?:fstate|ell)change|u(?:echange|t)|l(?:ick|ose))|s(?:t(?:a(?:t(?:uschanged|echange)|lled|rt)|k(?:sessione|comma)nd|op)|e(?:ek(?:complete|ing|ed)|(?:lec(?:tstar)?)?t|n(?:ding|t))|(?:peech|ound)(?:start|end)|u(?:ccess|spend|bmit)|croll|how)|m(?:o(?:z(?:(?:pointerlock|fullscreen)(?:change|error)|(?:orientation|time)change|network(?:down|up)load)|use(?:(?:lea|mo)ve|o(?:ver|ut)|enter|wheel|down|up)|ve(?:start|end)?)|essage|ark)|b(?:e(?:for(?:e(?:(?:scriptexecu|activa)te|u(?:nload|pdate)|p(?:aste|rint)|c(?:opy|ut)|editfocus)|deactivate)|gin(?:Event)?)|oun(?:dary|ce)|l(?:ocked|ur)|roadcast|usy)|a(?:n(?:imation(?:iteration|start|end)|tennastatechange)|fter(?:(?:scriptexecu|upda)te|print)|udio(?:process|start|end)|d(?:apteradded|dtrack)|ctivate|lerting|bort)|DOM(?:Node(?:Inserted(?:IntoDocument)?|Removed(?:FromDocument)?)|(?:CharacterData|Subtree)Modified|A(?:ttrModified|ctivate)|Focus(?:Out|In)|MouseScroll)|r(?:e(?:s(?:u(?:m(?:ing|e)|lt)|ize|et)|adystatechange|pea(?:tEven)?t|movetrack|trieving|ceived)|ow(?:s(?:inserted|delete)|e(?:nter|xit))|atechange)|p(?:op(?:up(?:hid(?:den|ing)|show(?:ing|n))|state)|a(?:ge(?:hide|show)|(?:st|us)e|int)|ro(?:pertychange|gress)|lay(?:ing)?)|t(?:ouch(?:(?:lea|mo)ve|en(?:ter|d)|cancel|start)|ime(?:update|out)|ransitionend|ext)|u(?:s(?:erproximity|sdreceived)|p(?:gradeneeded|dateready)|n(?:derflow|load))|f(?:o(?:rm(?:change|input)|cus(?:out|in)?)|i(?:lterchange|nish)|ailed)|l(?:o(?:ad(?:e(?:d(?:meta)?data|nd)|start)|secapture)|evelchange|y)|g(?:amepad(?:(?:dis)?connected|button(?:down|up)|axismove)|et)|e(?:n(?:d(?:Event|ed)?|abled|ter)|rror(?:update)?|mptied|xit)|i(?:cc(?:cardlockerror|infochange)|n(?:coming|valid|put))|o(?:(?:(?:ff|n)lin|bsolet)e|verflow(?:changed)?|pen)|SVG(?:(?:Unl|L)oad|Resize|Scroll|Abort|Error|Zoom)|h(?:e(?:adphoneschange|l[dp])|ashchange|olding)|v(?:o(?:lum|ic)e|ersion)change|w(?:a(?:it|rn)ing|heel)|key(?:press|down|up)|(?:AppComman|Loa)d|no(?:update|match)|Request|zoom)|s(?:tyle|rc)|background|formaction|lowsrc|ping)[\s\x08]*?=|<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?(?:(?:a\W*?(?:n\W*?i\W*?m\W*?a\W*?t\W*?e|p\W*?p\W*?l\W*?e\W*?t|u\W*?d\W*?i\W*?o)|b\W*?(?:i\W*?n\W*?d\W*?i\W*?n\W*?g\W*?s|a\W*?s\W*?e|o\W*?d\W*?y)|i?\W*?f\W*?r\W*?a\W*?m\W*?e|o\W*?b\W*?j\W*?e\W*?c\W*?t|i\W*?m\W*?a?\W*?g\W*?e?|e\W*?m\W*?b\W*?e\W*?d|p\W*?a\W*?r\W*?a\W*?m|v\W*?i\W*?d\W*?e\W*?o|l\W*?i\W*?n\W*?k)[^>\w]|s\W*?(?:c\W*?r\W*?i\W*?p\W*?t|t\W*?y\W*?l\W*?e|e\W*?t[^>\w]|v\W*?g)|m\W*?(?:a\W*?r\W*?q\W*?u\W*?e\W*?e|e\W*?t\W*?a[^>\w])|f\W*?o\W*?r\W*?m))" \ "id:941160,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'NoScript XSS InjectionChecker: HTML Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [NoScript InjectionChecker] Attributes injection # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|REQUEST_HEADERS:Referer|ARGS_NAMES|ARGS|XML:/* "@rx (?i)(?:\W|^)(?:javascript:(?:[\s\S]+[=\\\(\[\.<]|[\s\S]*?(?:\bname\b|\\[ux]\d))|data:(?:(?:[a-z]\w+\/\w[\w+-]+\w)?[;,]|[\s\S]*?;[\s\S]*?\b(?:base64|charset=)|[\s\S]*?,[\s\S]*?<[\s\S]*?\w[\s\S]*?>))|@\W*?i\W*?m\W*?p\W*?o\W*?r\W*?t\W*?(?:\/\*[\s\S]*?)?(?:[\"']|\W*?u\W*?r\W*?l[\s\S]*?\()|\W*?-\W*?m\W*?o\W*?z\W*?-\W*?b\W*?i\W*?n\W*?d\W*?i\W*?n\W*?g[\s\S]*?:[\s\S]*?\W*?u\W*?r\W*?l[\s\S]*?\(" \ "id:941170,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'NoScript XSS InjectionChecker: Attribute Injection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # [Blacklist Keywords from Node-Validator] # https://raw.github.com/chriso/node-validator/master/validator.js # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@pm document.cookie document.write .parentnode .innerhtml window.location -moz-binding .*?(?:@[i\\\\]|(?:[:=]|&#x?0*(?:58|3A|61|3D);?).*?(?:[(\\\\]|&#x?0*(?:40|28|92|5C);?)))" \ "id:941190,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'IE XSS Filters - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:<.*[:]?vmlframe.*?[\s/+]*?src[\s/+]*=)" \ "id:941200,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'IE XSS Filters - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:j|&#x?0*(?:74|4A|106|6A);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:a|&#x?0*(?:65|41|97|61);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:v|&#x?0*(?:86|56|118|76);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:a|&#x?0*(?:65|41|97|61);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:s|&#x?0*(?:83|53|115|73);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:c|&#x?0*(?:67|43|99|63);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:r|&#x?0*(?:82|52|114|72);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:i|&#x?0*(?:73|49|105|69);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:p|&#x?0*(?:80|50|112|70);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:t|&#x?0*(?:84|54|116|74);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?::|&(?:#x?0*(?:58|3A);?|colon;)).)" \ "id:941210,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'IE XSS Filters - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i:(?:v|&#x?0*(?:86|56|118|76);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:b|&#x?0*(?:66|42|98|62);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:s|&#x?0*(?:83|53|115|73);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:c|&#x?0*(?:67|43|99|63);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:r|&#x?0*(?:82|52|114|72);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:i|&#x?0*(?:73|49|105|69);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:p|&#x?0*(?:80|50|112|70);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?:t|&#x?0*(?:84|54|116|74);?)(?:\t|&(?:#x?0*(?:9|13|10|A|D);?|tab;|newline;))*(?::|&(?:#x?0*(?:58|3A);?|colon;)).)" \ "id:941220,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'IE XSS Filters - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i)]" \ "id:941290,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'IE XSS Filters - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?i))|(?:¾|¼|<).*(?:¾|¼)" \ "id:941310,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:lowercase,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ msg:'US-ASCII Malformed Encoding XSS Filter - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-tomcat',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # UTF-7 encoding XSS filter evasion for IE. # Reported by Vladimir Ivanov # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx (?:\+ADw\-|\+AD4\-).*(?:\+ADw\-|\+AD4\-|>)|(?:\+ADw\-|\+AD4\-|<).*(?:\+ADw\-|\+AD4\-)" \ "id:941350,\ phase:2,\ block,\ capture,\ t:none,t:urlDecodeUni,t:urlDecode,t:htmlEntityDecode,t:jsDecode,\ msg:'UTF-7 Encoding IE XSS - Attack Detected.',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-internet-explorer',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Defend against JSFuck and Hieroglyphy obfuscation of Javascript code # # https://en.wikipedia.org/wiki/JSFuck # https://github.com/alcuadrado/hieroglyphy # # These JS obfuscations mostly aim for client side XSS exploits, hence the # integration of this rule into the XSS rule group. But serverside JS could # also be attacked via these techniques. # # Detection pattern / Core elements of JSFuck and Hieroglyphy are the # following two items: # !![] # !+[] # # ModSecurity always transforms "+" into " " with query strings and the # URLENCODE body processor (but not for JSON). So we need to check for # the following patterns: # !![] # !+[] # ! [] SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "@rx ![!+ ]\[\]" \ "id:941360,\ phase:2,\ block,\ capture,\ t:none,\ msg:'JSFuck / Hieroglyphy obfuscation detected',\ logdata:'Matched Data: Suspicious payload found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'OWASP_TOP_10/A7',\ tag:'CAPEC-63',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" # # Prevent 941180 bypass by using JavaScript global variables # Examples: # - /?search=/?a=";+alert(self["document"]["cookie"]);// # - /?search=/?a=";+document+/*foo*/+.+/*bar*/+cookie;// # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS|XML:/* "@rx (?:self|document|this|top|window)\s*\)*(?:\[[^\]]+\]|\.\s*document|\.\s*cookie)" \ "id:941370,\ phase:2,\ block,\ capture,\ t:none,t:removeComments,t:urlDecodeUni,\ msg:'JavaScript global variable found',\ logdata:'Matched Data: Suspicious JS global variable found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'OWASP_TOP_10/A7',\ tag:'CAPEC-63',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:941013,phase:1,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" SecRule TX:EXECUTING_PARANOIA_LEVEL "@lt 2" "id:941014,phase:2,pass,nolog,skipAfter:END-REQUEST-941-APPLICATION-ATTACK-XSS" # # -= Paranoia Level 2 =- (apply only when tx.executing_paranoia_level is sufficiently high: 2 or higher) # # # This is a stricter sibling of rule 941100. # SecRule REQUEST_HEADERS:Referer "@detectXSS" \ "id:941101,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Attack Detected via libinjection',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ tag:'paranoia-level/2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # # -=[ XSS Filters - Category 5 ]=- # HTML attribues - src, style and href # SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|REQUEST_HEADERS:User-Agent|ARGS_NAMES|ARGS|XML:/* "@rx (?i)\b(?:s(?:tyle|rc)|href)\b[\s\S]*?=" \ "id:941150,\ phase:2,\ block,\ capture,\ t:none,t:utf8toUnicode,t:urlDecodeUni,t:htmlEntityDecode,t:jsDecode,t:cssDecode,t:removeNulls,\ msg:'XSS Filter - Category 5: Disallowed HTML Attributes',\ logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\ tag:'application-multi',\ tag:'language-multi',\ tag:'platform-multi',\ tag:'attack-xss',\ tag:'OWASP_CRS',\ tag:'OWASP_CRS/WEB_ATTACK/XSS',\ tag:'WASCTC/WASC-8',\ tag:'WASCTC/WASC-22',\ tag:'OWASP_TOP_10/A3',\ tag:'OWASP_AppSensor/IE1',\ tag:'CAPEC-242',\ tag:'paranoia-level/2',\ ctl:auditLogParts=+E,\ ver:'OWASP_CRS/3.2.0',\ severity:'CRITICAL',\ setvar:'tx.xss_score=+%{tx.critical_anomaly_score}',\ setvar:'tx.anomaly_score_pl2=+%{tx.critical_anomaly_score}'" # Detect tags that are the most common direct HTML injection points. # # # # #