├── .github ├── ISSUE_TEMPLATE │ ├── 01_false-positive.md │ ├── 02_false-negative.md │ ├── 03_bug-report.md │ ├── 04_feature.md │ └── config.yml └── workflows │ └── stale.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGES ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── INSTALL ├── KNOWN_BUGS ├── LICENSE ├── README.md ├── SECURITY.md ├── crs-setup.conf.example ├── docs └── README ├── rules ├── REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example ├── REQUEST-901-INITIALIZATION.conf ├── REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf ├── REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf ├── REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf ├── REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf ├── REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf ├── REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf ├── REQUEST-905-COMMON-EXCEPTIONS.conf ├── REQUEST-910-IP-REPUTATION.conf ├── REQUEST-911-METHOD-ENFORCEMENT.conf ├── REQUEST-912-DOS-PROTECTION.conf ├── REQUEST-913-SCANNER-DETECTION.conf ├── REQUEST-920-PROTOCOL-ENFORCEMENT.conf ├── REQUEST-921-PROTOCOL-ATTACK.conf ├── REQUEST-930-APPLICATION-ATTACK-LFI.conf ├── REQUEST-931-APPLICATION-ATTACK-RFI.conf ├── REQUEST-932-APPLICATION-ATTACK-RCE.conf ├── REQUEST-933-APPLICATION-ATTACK-PHP.conf ├── REQUEST-934-APPLICATION-ATTACK-NODEJS.conf ├── REQUEST-941-APPLICATION-ATTACK-XSS.conf ├── REQUEST-942-APPLICATION-ATTACK-SQLI.conf ├── REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf ├── REQUEST-944-APPLICATION-ATTACK-JAVA.conf ├── REQUEST-949-BLOCKING-EVALUATION.conf ├── RESPONSE-950-DATA-LEAKAGES.conf ├── RESPONSE-951-DATA-LEAKAGES-SQL.conf ├── RESPONSE-952-DATA-LEAKAGES-JAVA.conf ├── RESPONSE-953-DATA-LEAKAGES-PHP.conf ├── RESPONSE-954-DATA-LEAKAGES-IIS.conf ├── RESPONSE-959-BLOCKING-EVALUATION.conf ├── RESPONSE-980-CORRELATION.conf ├── RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example ├── crawlers-user-agents.data ├── iis-errors.data ├── java-classes.data ├── java-code-leakages.data ├── java-errors.data ├── lfi-os-files.data ├── php-config-directives.data ├── php-errors.data ├── php-function-names-933150.data ├── php-function-names-933151.data ├── php-variables.data ├── restricted-files.data ├── restricted-upload.data ├── scanners-headers.data ├── scanners-urls.data ├── scanners-user-agents.data ├── scripting-user-agents.data ├── sql-errors.data ├── unix-shell.data └── windows-powershell-commands.data ├── tests ├── integration │ ├── format_tests.py │ └── requirements.txt └── regression │ ├── CRS_Tests.py │ ├── CRS_Tests_Journal.py │ ├── README.md │ ├── __init__.py │ ├── config.ini │ ├── conftest.py │ ├── requirements.txt │ ├── tests │ ├── REQUEST-911-METHOD-ENFORCEMENT │ │ └── 911100.yaml │ ├── REQUEST-913-SCANNER-DETECTION │ │ ├── 913100.yaml │ │ ├── 913110.yaml │ │ └── 913120.yaml │ ├── REQUEST-920-PROTOCOL-ENFORCEMENT │ │ ├── 920100.yaml │ │ ├── 920120.yaml │ │ ├── 920160.yaml │ │ ├── 920170.yaml │ │ ├── 920180.yaml │ │ ├── 920190.yaml │ │ ├── 920200.yaml │ │ ├── 920201.yaml │ │ ├── 920202.yaml │ │ ├── 920210.yaml │ │ ├── 920220.yaml │ │ ├── 920230.yaml │ │ ├── 920240.yaml │ │ ├── 920250.yaml │ │ ├── 920260.yaml │ │ ├── 920270.yaml │ │ ├── 920271.yaml │ │ ├── 920272.yaml │ │ ├── 920273.yaml │ │ ├── 920274.yaml │ │ ├── 920280.yaml │ │ ├── 920290.yaml │ │ ├── 920300.yaml │ │ ├── 920310.yaml │ │ ├── 920311.yaml │ │ ├── 920320.yaml │ │ ├── 920330.yaml │ │ ├── 920340.yaml │ │ ├── 920350.yaml │ │ ├── 920360.yaml │ │ ├── 920370.yaml │ │ ├── 920380.yaml │ │ ├── 920390.yaml │ │ ├── 920400.yaml │ │ ├── 920420.yaml │ │ ├── 920430.yaml │ │ ├── 920440.yaml │ │ ├── 920450.yaml │ │ ├── 920460.yaml │ │ ├── 920470.yaml │ │ ├── 920480.yaml │ │ ├── 920490.yaml │ │ └── 920500.yaml │ ├── REQUEST-921-PROTOCOL-ATTACK │ │ ├── 921110.yaml │ │ ├── 921120.yaml │ │ ├── 921130.yaml │ │ ├── 921140.yaml │ │ ├── 921150.yaml │ │ ├── 921160.yaml │ │ ├── 921190.yaml │ │ └── 921200.yaml │ ├── REQUEST-930-APPLICATION-ATTACK-LFI │ │ ├── 930100.yaml │ │ ├── 930110.yaml │ │ └── 930120.yaml │ ├── REQUEST-931-APPLICATION-ATTACK-RFI │ │ ├── 931100.yaml │ │ ├── 931110.yaml │ │ ├── 931120.yaml │ │ └── 931130.yaml │ ├── REQUEST-932-APPLICATION-ATTACK-RCE │ │ ├── 932100.yaml │ │ └── 932140.yaml │ ├── REQUEST-933-APPLICATION-ATTACK-PHP │ │ ├── 933100.yaml │ │ ├── 933110.yaml │ │ ├── 933120.yaml │ │ ├── 933130.yaml │ │ ├── 933131.yaml │ │ ├── 933140.yaml │ │ ├── 933150.yaml │ │ ├── 933151.yaml │ │ ├── 933160.yaml │ │ ├── 933161.yaml │ │ ├── 933170.yaml │ │ ├── 933180.yaml │ │ └── 933210.yaml │ ├── REQUEST-934-APPLICATION-ATTACK-NODEJS │ │ └── 934100.yaml │ ├── REQUEST-941-APPLICATION-ATTACK-XSS │ │ ├── 941100.yaml │ │ ├── 941101.yaml │ │ ├── 941110.yaml │ │ ├── 941120.yaml │ │ ├── 941130.yaml │ │ ├── 941140.yaml │ │ ├── 941150.yaml │ │ ├── 941160.yaml │ │ ├── 941170.yaml │ │ ├── 941180.yaml │ │ ├── 941190.yaml │ │ ├── 941200.yaml │ │ ├── 941210.yaml │ │ ├── 941220.yaml │ │ ├── 941230.yaml │ │ ├── 941240.yaml │ │ ├── 941250.yaml │ │ ├── 941260.yaml │ │ ├── 941270.yaml │ │ ├── 941280.yaml │ │ ├── 941290.yaml │ │ ├── 941300.yaml │ │ ├── 941310.yaml │ │ ├── 941320.yaml │ │ ├── 941330.yaml │ │ ├── 941340.yaml │ │ ├── 941350.yaml │ │ ├── 941360.yaml │ │ ├── 941370.yaml │ │ └── 941380.yaml │ ├── REQUEST-942-APPLICATION-ATTACK-SQLI │ │ ├── 942100.yaml │ │ ├── 942101.yaml │ │ ├── 942110.yaml │ │ ├── 942120.yaml │ │ ├── 942130.yaml │ │ ├── 942140.yaml │ │ ├── 942150.yaml │ │ ├── 942160.yaml │ │ ├── 942180.yaml │ │ ├── 942190.yaml │ │ ├── 942200.yaml │ │ ├── 942210.yaml │ │ ├── 942220.yaml │ │ ├── 942230.yaml │ │ ├── 942240.yaml │ │ ├── 942250.yaml │ │ ├── 942260.yaml │ │ ├── 942270.yaml │ │ ├── 942280.yaml │ │ ├── 942290.yaml │ │ ├── 942300.yaml │ │ ├── 942310.yaml │ │ ├── 942320.yaml │ │ ├── 942330.yaml │ │ ├── 942340.yaml │ │ ├── 942350.yaml │ │ ├── 942360.yaml │ │ ├── 942361.yaml │ │ ├── 942370.yaml │ │ ├── 942380.yaml │ │ ├── 942390.yaml │ │ ├── 942400.yaml │ │ ├── 942410.yaml │ │ ├── 942420.yaml │ │ ├── 942421.yaml │ │ ├── 942430.yaml │ │ ├── 942431.yaml │ │ ├── 942432.yaml │ │ ├── 942440.yaml │ │ ├── 942450.yaml │ │ ├── 942470.yaml │ │ ├── 942480.yaml │ │ ├── 942490.yaml │ │ ├── 942500.yaml │ │ ├── 942510.yaml │ │ └── 942511.yaml │ ├── REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION │ │ ├── 943100.yaml │ │ ├── 943110.yaml │ │ └── 943120.yaml │ ├── REQUEST-944-APPLICATION-ATTACK-JAVA │ │ ├── 944000.yaml │ │ ├── 944100.yaml │ │ ├── 944110.yaml │ │ ├── 944120.yaml │ │ ├── 944130.yaml │ │ ├── 944200.yaml │ │ ├── 944210.yaml │ │ ├── 944240.yaml │ │ ├── 944250.yaml │ │ └── 944300.yaml │ ├── base_positive_rules.py │ ├── positivetest-light.yaml.skeleton │ └── positivetest.yaml.skeleton │ └── utils │ ├── data │ └── popularUAs.data │ ├── testSampling.py │ └── testUserAgents.py └── util ├── README ├── av-scanning ├── runAV │ ├── common.c │ ├── common.h │ ├── comp │ ├── runAV-clamd.c │ └── runAV.c └── runav.pl ├── browser-tools └── js-overrides.js ├── crs2-renumbering ├── IdNumbering.csv ├── README └── update.py ├── docker ├── Dockerfile ├── Dockerfile-2.9-apache ├── Dockerfile-3.0-apache ├── Dockerfile-3.0-nginx ├── README.md ├── REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf ├── RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf ├── docker-compose.yaml ├── docker-entrypoint.sh ├── httpd-logging-after-modsec.conf ├── httpd-logging-before-modsec.conf └── proxy.conf ├── geo-location └── README ├── honeypot-sensor ├── README.md ├── mlogc-honeypot-sensor.conf └── modsecurity_crs_10_honeypot.conf ├── id-range ├── join-multiline-rules └── join.py ├── regexp-assemble ├── regexp-932100.txt ├── regexp-932105.txt ├── regexp-932106.txt ├── regexp-932110.txt ├── regexp-932115.txt ├── regexp-932130.data ├── regexp-932140.data ├── regexp-932150.txt ├── regexp-933131.data ├── regexp-933160.data ├── regexp-933161.data ├── regexp-934100.txt ├── regexp-941130.data ├── regexp-941160.data ├── regexp-942120.data ├── regexp-942130.data ├── regexp-942140.data ├── regexp-942150.data ├── regexp-942170.data ├── regexp-942180.data ├── regexp-942190.data ├── regexp-942200.data ├── regexp-942210.data ├── regexp-942240.data ├── regexp-942260.data ├── regexp-942280.data ├── regexp-942300.data ├── regexp-942310.data ├── regexp-942320.data ├── regexp-942330.data ├── regexp-942340.data ├── regexp-942350.data ├── regexp-942360.data ├── regexp-942370.data ├── regexp-942380.data ├── regexp-942390.data ├── regexp-942400.data ├── regexp-942410.data ├── regexp-942470.data ├── regexp-942480.data ├── regexp-assemble-v2.pl ├── regexp-assemble.pl └── regexp-cmdline.py ├── regression-tests └── tests │ └── REQUEST-920-PROTOCOL-ENFORCEMENT │ └── 920181.yaml ├── send-payload-pls.sh ├── verify.rb └── virtual-patching ├── arachni2modsec.pl └── zap2modsec.pl /.github/ISSUE_TEMPLATE/01_false-positive.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'False positive' 3 | about: Report a false positive (incorrect blocking) 4 | title: '' 5 | labels: 'False Positive' 6 | assignees: '' 7 | --- 8 | 9 | PLEASE DON'T CREATE NEW ISSUES USING THIS REPO. 10 | 11 | WE ARE PERFORMING A MIGRATION RIGHT NOW. 12 | 13 | ### Description 14 | 15 | 16 | 17 | 18 | 19 | ### Audit Logs / Triggered Rule Numbers 20 | 21 | 22 | 23 | 24 | ### Your Environment 25 | 26 | 27 | 28 | 29 | * CRS version (e.g., v3.2.0): 30 | * Paranoia level setting: 31 | * ModSecurity version (e.g., 2.9.3): 32 | * Web Server and version (e.g., apache 2.4.41): 33 | * Operating System and version: 34 | 35 | ### Confirmation 36 | 37 | [ ] I have removed any personal data (email addresses, IP addresses, 38 | passwords, domain names) from any logs posted. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/02_false-negative.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'False negative' 3 | about: Report a false negative (incorrect bypass) 4 | title: '' 5 | labels: 'False Negative - Evasion' 6 | assignees: '' 7 | --- 8 | 9 | PLEASE DON'T CREATE NEW ISSUES USING THIS REPO. 10 | 11 | WE ARE PERFORMING A MIGRATION RIGHT NOW. 12 | 13 | ### Description 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ### Your Environment 24 | 25 | 26 | 27 | 28 | * CRS version (e.g., v3.2.0): 29 | * Paranoia level setting: 30 | * ModSecurity version (e.g., 2.9.3): 31 | * Web Server and version (e.g., apache 2.4.41): 32 | * Operating System and version: 33 | 34 | ### Confirmation 35 | 36 | [ ] I have removed any personal data (email addresses, IP addresses, 37 | passwords, domain names) from any logs posted. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/03_bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '🐞 Bug report' 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'Bug' 6 | assignees: '' 7 | --- 8 | 9 | PLEASE DON'T CREATE NEW ISSUES USING THIS REPO. 10 | 11 | WE ARE PERFORMING A MIGRATION RIGHT NOW. 12 | 13 | ### Describe the bug 14 | 15 | 16 | 17 | ### Steps to reproduce 18 | 19 | 20 | 21 | ### Expected behaviour 22 | 23 | 24 | 25 | ### Actual behaviour 26 | 27 | 28 | 29 | 30 | ### Additional context 31 | 32 | 33 | 34 | ### Your Environment 35 | 36 | 37 | 38 | 39 | * CRS version (e.g., v3.2.0): 40 | * Paranoia level setting: 41 | * ModSecurity version (e.g., 2.9.3): 42 | * Web Server and version (e.g., apache 2.4.41): 43 | * Operating System and version: 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/04_feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: '🚀 Feature request' 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'Feature Request' 6 | assignees: '' 7 | --- 8 | 9 | PLEASE DON'T CREATE NEW ISSUES USING THIS REPO. 10 | 11 | WE ARE PERFORMING A MIGRATION RIGHT NOW. 12 | 13 | ### Motivation 14 | 15 | 16 | 17 | 18 | ### Proposed solution 19 | 20 | 21 | 22 | 23 | ### Alternatives 24 | 25 | 26 | 27 | 28 | 29 | ### Additional context 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Help and support 4 | url: https://security.stackexchange.com/questions/tagged/owasp-crs 5 | about: For help and support please go here. 6 | - name: OWASP Core Rule Set mailing list 7 | url: https://groups.google.com/a/owasp.org/forum/#!forum/modsecurity-core-rule-set-project 8 | about: Ask general usage questions and participate in discussions on the CRS. 9 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | stale: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/stale@v1 14 | with: 15 | repo-token: ${{ secrets.GITHUB_TOKEN }} 16 | stale-issue-message: 'This issue has been open 120 days with no activity. Remove the stale label or comment, or this will be closed in 14 days' 17 | stale-issue-label: 'Stale issue' 18 | days-before-stale: 120 19 | days-before-close: 14 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | 4 | # User configuration 5 | crs-setup.conf 6 | rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf 7 | rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf 8 | 9 | # The MaxMind GeoIP database can be downloaded or upgraded by running: 10 | # util/upgrade.py geoip 11 | util/geo-location/GeoIP.dat 12 | 13 | # Unit test caches 14 | .cache 15 | 16 | # Byte-compiled / optimized / DLL files 17 | __pycache__/ 18 | *.py[cod] 19 | *$py.class 20 | 21 | .idea/ 22 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "docs/OWASP-CRS-Documentation"] 2 | path = docs/OWASP-CRS-Documentation 3 | url = https://github.com/SpiderLabs/OWASP-CRS-Documentation 4 | branch = master 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: linux 2 | language: python 3 | python: 4 | - 2.7 5 | 6 | # no more required in travis 7 | #sudo: required 8 | 9 | services: 10 | - docker 11 | 12 | jobs: 13 | include: 14 | script: 15 | - | 16 | if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then 17 | docker run -ti --name crs-test --entrypoint /docker-entrypoint.sh -e REPO=$TRAVIS_PULL_REQUEST_SLUG -e BRANCH=$TRAVIS_PULL_REQUEST_BRANCH themiddle/crs-test 18 | else 19 | docker run -ti --name crs-test --entrypoint /docker-entrypoint.sh -e REPO=$TRAVIS_REPO_SLUG -e BRANCH=$TRAVIS_BRANCH themiddle/crs-test 20 | fi 21 | 22 | # safelist 23 | branches: 24 | only: 25 | - v3.1/dev 26 | - v3.2/dev 27 | - v3.3/dev 28 | - fix-travis 29 | 30 | #notifications: 31 | # irc: "chat.freenode.net#modsecurity" 32 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | OWASP CRS has two types of releases, Major releases (3.0.0, 3.1.0, 3.2.0 etc.) and point releases (3.0.1, 3.0.2 etc.). 6 | For more information see our [wiki](https://github.com/SpiderLabs/owasp-modsecurity-crs/wiki/Release-Policy). 7 | The OWASP CRS officially supports the two point releases with security patching preceding the current major release . 8 | We are happy to receive and merge PR's that address security issues in older versions of the project, but the team itself may choose not to fix these. 9 | Along those lines, OWASP CRS team may not issue security notifications for unsupported software. 10 | 11 | | Version | Supported | 12 | | --------- | ------------------ | 13 | | 3.3.x-dev | :white_check_mark: | 14 | | 3.2.x | :white_check_mark: | 15 | | 3.1.x | :white_check_mark: | 16 | | 3.0.x | :x: | 17 | 18 | ## Reporting a Vulnerability 19 | 20 | We strive to make the OWASP ModSecurity CRS accessible to a wide audience of beginner and experienced users. 21 | We welcome bug reports, false positive alert reports, evasions, usability issues, and suggestions for new detections. 22 | Submit these types of non-vulnerability related issues via Github. 23 | Please include your installed version and the relevant portions of your audit log. 24 | False negative or common bypasses should [create an issue](https://github.com/SpiderLabs/owasp-modsecurity-crs/issues/new) so they can be addressed. 25 | 26 | Do this before submitting a vulnerability using our email: 27 | 1) Verify that you have the latest version of OWASP CRS. 28 | 2) Validate which Paranoia Level this bypass applies to. If it works in PL4, please send us an email. 29 | 3) If you detected anything that causes unexpected behavior of the engine via manipulation of existing CRS provided rules, please send it by email. 30 | 31 | Our email is [security@coreruleset.org](mailto:security@coreruleset.org). You can send us encrypted email using [this key](https://coreruleset.org/security.asc), (fingerprint: `3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72`). 32 | 33 | We are happy to work with the community to provide CVE identifiers for any discovered security issues if requested. 34 | 35 | If in doubt, feel free to reach out to us! 36 | -------------------------------------------------------------------------------- /docs/README: -------------------------------------------------------------------------------- 1 | Welcome to the OWASP Core Rule Set (CRS) documentation. 2 | 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. 3 | 4 | You can download the documentation using git: 5 | $ git submodule init 6 | $ git submodule update 7 | 8 | Alternatively, the latest version of the documentation is available at https://www.modsecurity.org/CRS/Documentation/ 9 | -------------------------------------------------------------------------------- /rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # OWASP ModSecurity Core Rule Set ver.3.2.0 3 | # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. 4 | # 5 | # The OWASP ModSecurity Core Rule Set is distributed under 6 | # Apache Software License (ASL) version 2 7 | # Please see the enclosed LICENSE file for full details. 8 | # ------------------------------------------------------------------------ 9 | 10 | # These exclusions remedy false positives in a default cPanel environment. 11 | # The exclusions are only active if crs_exclusions_cpanel=1 is set. 12 | # See rule 900130 in crs-setup.conf.example for instructions. 13 | 14 | 15 | SecRule &TX:crs_exclusions_cpanel|TX:crs_exclusions_cpanel "@eq 0" \ 16 | "id:9005000,\ 17 | phase:1,\ 18 | pass,\ 19 | t:none,\ 20 | nolog,\ 21 | ver:'OWASP_CRS/3.2.0',\ 22 | skipAfter:END-CPANEL" 23 | 24 | SecRule &TX:crs_exclusions_cpanel|TX:crs_exclusions_cpanel "@eq 0" \ 25 | "id:9005001,\ 26 | phase:2,\ 27 | pass,\ 28 | t:none,\ 29 | nolog,\ 30 | ver:'OWASP_CRS/3.2.0',\ 31 | skipAfter:END-CPANEL" 32 | 33 | 34 | # 35 | # [ cPanel whm-server-status ] 36 | # 37 | # Cpanel's WHM auto generates requests to /whm-server-status from 38 | # 127.0.0.1 (triggers rule 920280, non-blocking, log only) Once every 5 minutes. 39 | # These false positives have a low impact (logged, non-blocking) to a large number of users (all cPanel admins). 40 | # 41 | 42 | # 43 | # Rule to allow cPanel whm-server-status requests from localhost without log entry. 44 | # 45 | SecRule REQUEST_LINE "@rx ^GET /whm-server-status(?:/|/\?auto)? HTTP/[12]\.[01]$" \ 46 | "id:9005100,\ 47 | phase:1,\ 48 | pass,\ 49 | t:none,\ 50 | nolog,\ 51 | tag:'application-multi',\ 52 | tag:'language-multi',\ 53 | tag:'platform-apache',\ 54 | tag:'attack-generic',\ 55 | ver:'OWASP_CRS/3.2.0',\ 56 | chain" 57 | SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ 58 | "t:none,\ 59 | ctl:ruleRemoveById=920280,\ 60 | ctl:ruleRemoveById=920350" 61 | 62 | 63 | SecMarker "END-CPANEL" 64 | -------------------------------------------------------------------------------- /rules/REQUEST-905-COMMON-EXCEPTIONS.conf: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------ 2 | # OWASP ModSecurity Core Rule Set ver.3.2.0 3 | # Copyright (c) 2006-2019 Trustwave and contributors. All rights reserved. 4 | # 5 | # The OWASP ModSecurity Core Rule Set is distributed under 6 | # Apache Software License (ASL) version 2 7 | # Please see the enclosed LICENSE file for full details. 8 | # ------------------------------------------------------------------------ 9 | 10 | 11 | # This file is used as an exception mechanism to remove common false positives 12 | # that may be encountered. 13 | # 14 | # Exception for Apache SSL pinger 15 | # 16 | SecRule REQUEST_LINE "@streq GET /" \ 17 | "id:905100,\ 18 | phase:1,\ 19 | pass,\ 20 | t:none,\ 21 | nolog,\ 22 | tag:'application-multi',\ 23 | tag:'language-multi',\ 24 | tag:'platform-apache',\ 25 | tag:'attack-generic',\ 26 | ver:'OWASP_CRS/3.2.0',\ 27 | chain" 28 | SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ 29 | "t:none,\ 30 | ctl:ruleEngine=Off,\ 31 | ctl:auditEngine=Off" 32 | 33 | # 34 | # Exception for Apache internal dummy connection 35 | # 36 | SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,::1" \ 37 | "id:905110,\ 38 | phase:1,\ 39 | pass,\ 40 | t:none,\ 41 | nolog,\ 42 | tag:'application-multi',\ 43 | tag:'language-multi',\ 44 | tag:'platform-apache',\ 45 | tag:'attack-generic',\ 46 | ver:'OWASP_CRS/3.2.0',\ 47 | chain" 48 | SecRule REQUEST_HEADERS:User-Agent "@endsWith (internal dummy connection)" \ 49 | "t:none,\ 50 | chain" 51 | SecRule REQUEST_LINE "@rx ^(?:GET /|OPTIONS \*) HTTP/[12]\.[01]$" \ 52 | "t:none,\ 53 | ctl:ruleEngine=Off,\ 54 | ctl:auditEngine=Off" 55 | -------------------------------------------------------------------------------- /rules/crawlers-user-agents.data: -------------------------------------------------------------------------------- 1 | # Search engine crawlers and other bots 2 | # crawler 3 | # https://80legs.com/ 4 | 80legs 5 | # site ripper 6 | # http://www.softbytelabs.com/en/BlackWidow/ 7 | black widow 8 | blackwidow 9 | # crawler 10 | # 2006 11 | prowebwalker 12 | # generic crawler 13 | pymills-spider/ 14 | # SEO 15 | # https://ahrefs.com/robot 16 | AhrefsBot 17 | # people database 18 | # https://pipl.com/bot/ 19 | PiplBot 20 | # advertising targeting 21 | # https://www.grapeshot.com/crawler/ 22 | GrapeshotCrawler/2.0 23 | grapeFX 24 | # SEO 25 | # http://www.searchmetrics.com/searchmetricsbot/ 26 | SearchmetricsBot 27 | # SEO 28 | # https://www.semrush.com/bot/ 29 | SemrushBot 30 | # SEO 31 | # https://moz.com/help/guides/moz-procedures/what-is-rogerbot 32 | rogerbot 33 | # SEO 34 | # http://www.majestic12.co.uk/projects/dsearch/mj12bot.php 35 | MJ12bot 36 | # news service 37 | Owlin bot 38 | # misbehaving spider 39 | Lingewoud-550-Spyder 40 | # https://www.wappalyzer.com/ 41 | Wappalyzer 42 | -------------------------------------------------------------------------------- /rules/iis-errors.data: -------------------------------------------------------------------------------- 1 |

HTTP 403.6 - Forbidden: IP address rejected
2 | 500 Internal Server Error 3 | Microsoft VBScript runtime (0x8 4 | error '800 5 | Application uses a value of the wrong type for the current operation 6 | Microsoft VBScript compilation (0x8 7 | Microsoft VBScript compilation error 8 | Microsoft .NET Framework Version: 9 | A trappable error occurred in an external object. The script cannot continue running 10 | Microsoft VBScript runtime Error 11 | >Syntax error in string in query expression 12 | ADODB.Command 13 | Object required: ' 14 | -------------------------------------------------------------------------------- /rules/java-classes.data: -------------------------------------------------------------------------------- 1 | com.opensymphony.xwork2 2 | com.sun.org.apache 3 | java.io.BufferedInputStream 4 | java.io.BufferedReader 5 | java.io.ByteArrayInputStream 6 | java.io.ByteArrayOutputStream 7 | java.io.CharArrayReader 8 | java.io.DataInputStream 9 | java.io.File 10 | java.io.FileOutputStream 11 | java.io.FilePermission 12 | java.io.FileWriter 13 | java.io.FilterInputStream 14 | java.io.FilterOutputStream 15 | java.io.FilterReader 16 | java.io.InputStream 17 | java.io.InputStreamReader 18 | java.io.LineNumberReader 19 | java.io.ObjectOutputStream 20 | java.io.OutputStream 21 | java.io.PipedOutputStream 22 | java.io.PipedReader 23 | java.io.PrintStream 24 | java.io.PushbackInputStream 25 | java.io.Reader 26 | java.io.StringReader 27 | java.lang.Class 28 | java.lang.Integer 29 | java.lang.Number 30 | java.lang.Object 31 | java.lang.Process 32 | java.lang.ProcessBuilder 33 | java.lang.reflect 34 | java.lang.Runtime 35 | java.lang.String 36 | java.lang.StringBuilder 37 | java.lang.System 38 | javax.script.ScriptEngineManager 39 | org.apache.commons 40 | org.apache.struts 41 | org.apache.struts2 42 | org.omg.CORBA 43 | java.beans.XMLDecode 44 | -------------------------------------------------------------------------------- /rules/java-code-leakages.data: -------------------------------------------------------------------------------- 1 | hello.html 3 | /actSensepostnottherenonotive 4 | /acunetix-wvs-test-for-some-inexistent-file 5 | /antidisestablishmentarianism 6 | /appscan_fingerprint/mac_address 7 | /arachni- 8 | /cybercop 9 | /nessus_is_probing_you_ 10 | /nessustest 11 | /netsparker- 12 | /rfiinc.txt 13 | /thereisnowaythat-you-canbethere 14 | /w3af/remotefileinclude.html 15 | appscan_fingerprint 16 | w00tw00t.at.ISC.SANS.DFind 17 | w00tw00t.at.blackhats.romanian.anti-sec 18 | -------------------------------------------------------------------------------- /rules/scripting-user-agents.data: -------------------------------------------------------------------------------- 1 | # Generic HTTP clients (popular libraries) 2 | 3 | # http library 4 | # http://search.cpan.org/~opera/HTTP-DAV/DAV.pm 5 | dav.pm/v 6 | # http library 7 | # http://search.cpan.org/dist/libwww-perl/lib/LWP.pm 8 | libwww-perl 9 | # generic 10 | mozilla/4.0 (compatible) 11 | mozilla/4.0 (compatible; msie 6.0; win32) 12 | mozilla/5.0 sf/ 13 | mozilla/5.0 sf// 14 | # http library 15 | # https://pypi.python.org/pypi/httplib2 16 | python-httplib2 17 | # http library 18 | # http://docs.python-requests.org/en/master/ 19 | python-requests 20 | # http library 21 | # https://docs.python.org/2/library/urllib.html 22 | Python-urllib 23 | # http library 24 | # https://github.com/typhoeus/typhoeus 25 | typhoeus 26 | # http library 27 | # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382925%28v=vs.85%29.aspx 28 | winhttp.winhttprequest 29 | -------------------------------------------------------------------------------- /rules/sql-errors.data: -------------------------------------------------------------------------------- 1 | MySqlClient. 2 | Server message 3 | SQL error 4 | Oracle error 5 | JET Database Engine 6 | Procedure or function 7 | SQLite.Exception 8 | [IBM][CLI Driver][DB2/6000] 9 | the used select statements have different number of columns 10 | org.postgresql.util.PSQLException 11 | Access Database Engine 12 | Incorrect syntax near 13 | Syntax error in string in query expression 14 | SQLiteException 15 | ' doesn't exist 16 | CLI Driver 17 | on MySQL result index 18 | sybase 19 | com.informix.jdbc 20 | [MySQL][ODBC 21 | Error 22 | has occurred in the vicinity of: 23 | Sintaxis incorrecta cerca de 24 | MySQL server version for the right syntax to use 25 | com.mysql.jdbc.exceptions 26 | You have an error in your SQL syntax near 27 | You have an error in your SQL syntax; 28 | An illegal character has been found in the statement 29 | pg_query() [: 30 | supplied argument is not a valid MySQL 31 | mssql_query() 32 | mysql_fetch_array() 33 | Exception 34 | java.sql.SQLException 35 | Column count doesn't match value count at row 36 | Sybase message 37 | SQL Server 38 | PostgreSQL query failed: 39 | Dynamic SQL Error 40 | System.Data.SQLite.SQLiteException 41 | SQLite/JDBCDriver 42 | Unclosed quotation mark before the character string 43 | System.Data.SqlClient. 44 | Unclosed quotation mark after the character string 45 | System.Data.OleDb.OleDbException 46 | [DM_QUERY_E_SYNTAX] 47 | [SqlException 48 | Unexpected end of command in statement 49 | valid PostgreSQL result 50 | pg_exec() [: 51 | SQL Server 52 | [SQLITE_ERROR] 53 | Microsoft OLE DB Provider for ODBC Drivers 54 | PostgreSQL 55 | org.hsqldb.jdbc 56 | ADODB.Field (0x800A0BCD) 57 | SQL syntax 58 | Exception 59 | System.Data.SqlClient.SqlException 60 | Data type mismatch in criteria expression. 61 | Driver 62 | DB2 SQL error 63 | Sybase message: 64 | ORA- 65 | [Microsoft][ODBC SQL Server Driver] 66 | '80040e14' 67 | Microsoft OLE DB Provider for SQL Server 68 | in query expression 69 | Npgsql. 70 | valid MySQL result 71 | supplied argument is not a valid PostgreSQL result 72 | db2_ 73 | Ingres SQLSTATE 74 | Column count doesn't match 75 | Warning 76 | [Microsoft][ODBC Microsoft Access Driver] 77 | [Macromedia][SQLServer JDBC Driver] 78 | Warning: ibase_ 79 | Roadhouse.Cms. 80 | DB2 SQL error: 81 | -------------------------------------------------------------------------------- /rules/unix-shell.data: -------------------------------------------------------------------------------- 1 | ${CDPATH} 2 | ${DIRSTACK} 3 | ${HOME} 4 | ${HOSTNAME} 5 | ${IFS} 6 | ${OLDPWD} 7 | ${OSTYPE} 8 | ${PATH} 9 | ${PWD} 10 | $CDPATH 11 | $DIRSTACK 12 | $HOME 13 | $HOSTNAME 14 | $IFS 15 | $OLDPWD 16 | $OSTYPE 17 | $PATH 18 | $PWD 19 | bin/bash 20 | bin/cat 21 | bin/csh 22 | bin/dash 23 | bin/du 24 | bin/echo 25 | bin/grep 26 | bin/less 27 | bin/ls 28 | bin/mknod 29 | bin/more 30 | bin/nc 31 | bin/ps 32 | bin/rbash 33 | bin/sh 34 | bin/sleep 35 | bin/su 36 | bin/tcsh 37 | bin/uname 38 | dev/fd/ 39 | dev/null 40 | dev/stderr 41 | dev/stdin 42 | dev/stdout 43 | dev/tcp/ 44 | dev/udp/ 45 | dev/zero 46 | etc/group 47 | etc/master.passwd 48 | etc/passwd 49 | etc/pwd.db 50 | etc/shadow 51 | etc/shells 52 | etc/spwd.db 53 | proc/self/ 54 | usr/bin/awk 55 | usr/bin/base64 56 | usr/bin/cat 57 | usr/bin/cc 58 | usr/bin/clang 59 | usr/bin/clang++ 60 | usr/bin/curl 61 | usr/bin/diff 62 | usr/bin/env 63 | usr/bin/fetch 64 | usr/bin/file 65 | usr/bin/find 66 | usr/bin/ftp 67 | usr/bin/gawk 68 | usr/bin/gcc 69 | usr/bin/head 70 | usr/bin/hexdump 71 | usr/bin/id 72 | usr/bin/less 73 | usr/bin/ln 74 | usr/bin/mkfifo 75 | usr/bin/more 76 | usr/bin/nc 77 | usr/bin/ncat 78 | usr/bin/nice 79 | usr/bin/nmap 80 | usr/bin/perl 81 | usr/bin/php 82 | usr/bin/php5 83 | usr/bin/php7 84 | usr/bin/php-cgi 85 | usr/bin/printf 86 | usr/bin/psed 87 | usr/bin/python 88 | usr/bin/python2 89 | usr/bin/python3 90 | usr/bin/ruby 91 | usr/bin/sed 92 | usr/bin/socat 93 | usr/bin/tail 94 | usr/bin/tee 95 | usr/bin/telnet 96 | usr/bin/top 97 | usr/bin/uname 98 | usr/bin/wget 99 | usr/bin/who 100 | usr/bin/whoami 101 | usr/bin/xargs 102 | usr/bin/xxd 103 | usr/bin/yes 104 | usr/local/bin/bash 105 | usr/local/bin/curl 106 | usr/local/bin/ncat 107 | usr/local/bin/nmap 108 | usr/local/bin/perl 109 | usr/local/bin/php 110 | usr/local/bin/python 111 | usr/local/bin/python2 112 | usr/local/bin/python3 113 | usr/local/bin/rbash 114 | usr/local/bin/ruby 115 | usr/local/bin/wget 116 | -------------------------------------------------------------------------------- /tests/integration/format_tests.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pytest 3 | import os 4 | import sys 5 | 6 | def get_file_list(start): 7 | """ 8 | Gets the file list of all files that end in .conf 9 | """ 10 | valid_files = [] 11 | for root, dirs, files in os.walk(start): 12 | for name in files: 13 | if name[-5:] == ".conf": 14 | valid_files.append(os.path.join(root,name)) 15 | return valid_files 16 | 17 | 18 | def test_trailing_whitespace(): 19 | """ 20 | Test to ensure that there is no line with trailing whitespace 21 | """ 22 | test_failed = False 23 | files = get_file_list(".") 24 | for fname in files: 25 | with open(fname,'r') as fp: 26 | for i,line in enumerate(fp): 27 | if len(line) > 1 and line[-2] == ' ': 28 | print("Line", i+1, "in", fname, "has trailing whitespace.") 29 | test_failed = True 30 | assert test_failed == False 31 | -------------------------------------------------------------------------------- /tests/integration/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest>=2.9.1 2 | -------------------------------------------------------------------------------- /tests/regression/CRS_Tests.py: -------------------------------------------------------------------------------- 1 | from ftw import ruleset, logchecker, testrunner 2 | import datetime 3 | import pytest 4 | import sys 5 | import re 6 | import os 7 | 8 | 9 | def test_crs(ruleset, test, logchecker_obj): 10 | runner = testrunner.TestRunner() 11 | for stage in test.stages: 12 | runner.run_stage(stage, logchecker_obj) 13 | 14 | 15 | class FooLogChecker(logchecker.LogChecker): 16 | def __init__(self, config): 17 | super(FooLogChecker, self).__init__() 18 | self.log_location = config['log_location_linux'] 19 | self.log_date_regex = config['log_date_regex'] 20 | self.log_date_format = config['log_date_format'] 21 | 22 | def reverse_readline(self, filename): 23 | with open(filename) as f: 24 | f.seek(0, os.SEEK_END) 25 | position = f.tell() 26 | line = '' 27 | while position >= 0: 28 | f.seek(position) 29 | next_char = f.read(1) 30 | if next_char == "\n": 31 | yield line[::-1] 32 | line = '' 33 | else: 34 | line += next_char 35 | position -= 1 36 | yield line[::-1] 37 | 38 | def get_logs(self): 39 | pattern = re.compile(r'%s' % self.log_date_regex) 40 | our_logs = [] 41 | for lline in self.reverse_readline(self.log_location): 42 | # Extract dates from each line 43 | match = re.match(pattern, lline) 44 | if match: 45 | log_date = match.group(1) 46 | log_date = datetime.datetime.strptime( 47 | log_date, self.log_date_format) 48 | # NGINX doesn't give us microsecond level by detail, round down. 49 | if "%f" not in self.log_date_format: 50 | ftw_start = self.start.replace(microsecond=0) 51 | else: 52 | ftw_start = self.start 53 | ftw_end = self.end 54 | if log_date <= ftw_end and log_date >= ftw_start: 55 | our_logs.append(lline) 56 | # If our log is from before FTW started stop 57 | if log_date < ftw_start: 58 | break 59 | return our_logs 60 | 61 | 62 | @pytest.fixture(scope='session') 63 | def logchecker_obj(config): 64 | return FooLogChecker(config) 65 | -------------------------------------------------------------------------------- /tests/regression/CRS_Tests_Journal.py: -------------------------------------------------------------------------------- 1 | from ftw import ruleset, logchecker, testrunner 2 | import datetime 3 | import pytest 4 | import sys 5 | import re 6 | import os 7 | 8 | 9 | def test_crs(ruleset, test, logchecker_obj, with_journal, tablename): 10 | runner = testrunner.TestRunner() 11 | for stage in test.stages: 12 | runner.run_stage_with_journal(test.ruleset_meta['name'], test, with_journal, tablename, logchecker_obj) 13 | 14 | 15 | class FooLogChecker(logchecker.LogChecker): 16 | def __init__(self, config): 17 | super(FooLogChecker, self).__init__() 18 | self.log_location = config['log_location_linux'] 19 | self.log_date_regex = config['log_date_regex'] 20 | self.log_date_format = config['log_date_format'] 21 | 22 | def reverse_readline(self, filename): 23 | with open(filename) as f: 24 | f.seek(0, os.SEEK_END) 25 | position = f.tell() 26 | line = '' 27 | while position >= 0: 28 | f.seek(position) 29 | next_char = f.read(1) 30 | if next_char == "\n": 31 | yield line[::-1] 32 | line = '' 33 | else: 34 | line += next_char 35 | position -= 1 36 | yield line[::-1] 37 | 38 | def get_logs(self): 39 | pattern = re.compile(r'%s' % self.log_date_regex) 40 | our_logs = [] 41 | for lline in self.reverse_readline(self.log_location): 42 | # Extract dates from each line 43 | match = re.match(pattern, lline) 44 | if match: 45 | log_date = match.group(1) 46 | log_date = datetime.datetime.strptime( 47 | log_date, self.log_date_format) 48 | # NGINX doesn't give us microsecond level by detail, round down. 49 | if "%f" not in self.log_date_format: 50 | ftw_start = self.start.replace(microsecond=0) 51 | else: 52 | ftw_start = self.start 53 | ftw_end = self.end 54 | if log_date <= ftw_end and log_date >= ftw_start: 55 | our_logs.append(lline) 56 | # If our log is from before FTW started stop 57 | if log_date < ftw_start: 58 | break 59 | return our_logs 60 | 61 | 62 | @pytest.fixture(scope='session') 63 | def logchecker_obj(config): 64 | return FooLogChecker(config) 65 | -------------------------------------------------------------------------------- /tests/regression/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpiderLabs/owasp-modsecurity-crs/56ff01a8408bd387fe14f7856391c48e245b7937/tests/regression/__init__.py -------------------------------------------------------------------------------- /tests/regression/config.ini: -------------------------------------------------------------------------------- 1 | [2.9-apache] 2 | log_date_format = %a %b %d %H:%M:%S.%f %Y 3 | log_date_regex = \[([A-Z][a-z]{2} [A-z][a-z]{2} \d{1,2} \d{1,2}\:\d{1,2}\:\d{1,2}\.\d+? \d{4})\] 4 | log_location_linux = /var/log/apache2/error.log 5 | 6 | [3.0-apache] 7 | log_date_format = %a %b %d %H:%M:%S.%f %Y 8 | log_date_regex = \[([A-Z][a-z]{2} [A-z][a-z]{2} \d{1,2} \d{1,2}\:\d{1,2}\:\d{1,2}\.\d+? \d{4})\] 9 | log_location_linux = /var/log/apache2/error.log 10 | 11 | [3.0-nginx] 12 | log_date_format = %Y/%m/%d %H:%M:%S 13 | log_date_regex = (\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}) 14 | log_location_linux = /var/log/nginx/error.log 15 | -------------------------------------------------------------------------------- /tests/regression/conftest.py: -------------------------------------------------------------------------------- 1 | try: 2 | import ConfigParser as configparser 3 | except ImportError: 4 | import configparser 5 | import os 6 | import pytest 7 | 8 | 9 | def pytest_addoption(parser): 10 | parser.addoption('--config', action='store', default='2.9-apache') 11 | 12 | 13 | @pytest.fixture(scope='session') 14 | def config(request): 15 | cp = configparser.RawConfigParser() 16 | cp.read(os.path.join(os.path.dirname(__file__), 'config.ini')) 17 | return dict(cp.items(request.config.getoption('--config'))) 18 | -------------------------------------------------------------------------------- /tests/regression/requirements.txt: -------------------------------------------------------------------------------- 1 | ftw==1.1.7 2 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-913-SCANNER-DETECTION/913110.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 913110.yaml 7 | tests: 8 | - 9 | test_title: 913110-1 10 | desc: Request Indicates a Security Scanner Scanned the Site (913110) from old modsec 11 | regressions 12 | stages: 13 | - 14 | stage: 15 | input: 16 | dest_addr: 127.0.0.1 17 | headers: 18 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 19 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 20 | Accept-Encoding: gzip,deflate 21 | Accept-Language: en-us,en;q=0.5 22 | Acunetix-Product: WVS/5.0 (Acunetix Web Vulnerability Scanner - EVALUATION) 23 | Host: localhost 24 | Keep-Alive: '300' 25 | Proxy-Connection: keep-alive 26 | User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET 27 | CLR 2.0.50727) 28 | method: GET 29 | port: 80 30 | uri: / 31 | version: HTTP/1.0 32 | output: 33 | log_contains: id "913110" 34 | - 35 | test_title: 913110-2 36 | desc: "Scanner identification based on custom header" 37 | stages: 38 | - 39 | stage: 40 | input: 41 | dest_addr: "127.0.0.1" 42 | method: "GET" 43 | port: 80 44 | headers: 45 | Host: "localhost" 46 | X-Scanner: "whatever" 47 | uri: "/" 48 | output: 49 | log_contains: id "913110" 50 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-913-SCANNER-DETECTION/913120.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 913120.yaml 7 | tests: 8 | - 9 | test_title: 913120-1 10 | desc: Request Indicates a Security Scanner Scanned the Site (913120) from old modsec 11 | regressions 12 | stages: 13 | - 14 | stage: 15 | input: 16 | dest_addr: 127.0.0.1 17 | headers: 18 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 19 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 20 | Accept-Encoding: gzip,deflate 21 | Accept-Language: en-us,en;q=0.5 22 | Host: localhost 23 | Keep-Alive: '300' 24 | Proxy-Connection: keep-alive 25 | User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET 26 | CLR 2.0.50727) 27 | method: GET 28 | port: 80 29 | uri: /nessustest 30 | version: HTTP/1.0 31 | output: 32 | log_contains: id "913120" 33 | - 34 | test_title: 913120-2 35 | desc: IBM fingerprint from (http://www-01.ibm.com/support/docview.wss?uid=swg21293132) 36 | stages: 37 | - 38 | stage: 39 | input: 40 | dest_addr: 127.0.0.1 41 | headers: 42 | User-Agent: "ModSecurity CRS 3 Tests" 43 | Host: localhost 44 | uri: /AppScan_fingerprint/MAC_ADDRESS_01234567890.html?9ABCDG1 45 | version: HTTP/1.0 46 | output: 47 | log_contains: id "913120" 48 | - 49 | test_title: 913120-3 50 | desc: "Scanner identification based on uri" 51 | stages: 52 | - 53 | stage: 54 | input: 55 | dest_addr: "127.0.0.1" 56 | method: "GET" 57 | port: 80 58 | headers: 59 | Host: "localhost" 60 | version: HTTP/1.0 61 | uri: "/nessus_is_probing_you_" 62 | output: 63 | log_contains: id "913120" 64 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920190.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920190.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 920190-1 10 | stages: 11 | - 12 | stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | method: "GET" 16 | port: 80 17 | headers: 18 | User-Agent: "ModSecurity CRS 3 Tests" 19 | Host: "localhost" 20 | Range: "0-1" 21 | protocol: "http" 22 | uri: "/" 23 | output: 24 | no_log_contains: id "920190" 25 | - 26 | test_title: 920190-2 27 | desc: 'Range: Invalid Last Byte Value (920190) from old modsec regressions' 28 | stages: 29 | - 30 | stage: 31 | input: 32 | dest_addr: 127.0.0.1 33 | headers: 34 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 35 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 36 | Accept-Language: en-us,en;q=0.5 37 | Connection: close 38 | Host: localhost 39 | Keep-Alive: '300' 40 | Proxy-Connection: keep-alive 41 | Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15 42 | User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv 43 | method: GET 44 | port: 80 45 | uri: / 46 | version: HTTP/1.1 47 | output: 48 | log_contains: id "920190" 49 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920201.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920201.yaml" 6 | description: "Tests for 920201" 7 | tests: 8 | - 9 | test_title: 920201-1 10 | desc: This should FAIL with rule 920201 (PL2) 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | Range: "bytes=10-11, 20-21, 30-31, 40-41, 50-51, 60-61, 70-71, 80-81, 90-91, 100-101, 110-11, 120-21, 130-31, 140-41, 150-51, 160-61, 170-71, 180-81, 190-91, 200-101, 210-11, 220-21, 230-31, 240-41, 250-51, 260-61, 270-71, 280-81, 290-91, 300-101, 310-311, 320-321, 330-331, 340-341, 350-351, 360-361, 370-371, 380-381, 390-391, 400-401, 410-411, 420-421, 430-431, 440-441, 450-451, 460-461, 470-471, 480-481, 490-491, 500-501, 510-511, 520-521, 530-531, 540-541, 550-551, 560-561, 570-571, 580-581, 590-591, 600-601, 610-611, 620-621, 630-631" 19 | User-Agent: "ModSecurity CRS 3 Tests" 20 | method: GET 21 | port: 80 22 | uri: /index.pdf 23 | output: 24 | log_contains: id "920201" 25 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920202.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920202.yaml" 6 | description: "Tests for 920202" 7 | tests: 8 | - 9 | test_title: 920202-1 10 | desc: This should FAIL with rule 920202 (PL4) 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | Range: "bytes=10-11, 20-21, 30-31, 40-41, 50-51, 60-61" 19 | User-Agent: "ModSecurity CRS 3 Tests" 20 | method: GET 21 | port: 80 22 | uri: /index.pdf 23 | output: 24 | log_contains: id "920202" 25 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920230.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920230.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | # From old modsec regression tests 10 | test_title: 920230-1 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: "127.0.0.1" 16 | port: 80 17 | uri: "/?parm=%25%37%33%25%36%46%25%36%44%25%36%35%25%37%34%25%36%35%25%37%38%25%37%34%25%35%46%25%33%31%25%33%32%25%33%33%25%33%34" 18 | headers: 19 | User-Agent: "ModSecurity CRS 3 Tests" 20 | Host: "localhost" 21 | Accept: "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" 22 | Accept-Language: "en-us,en;q=0.5" 23 | Accept-Charset: "ISO-8859-1,utf-8;q=0.7,*;q=0.7" 24 | Keep-Alive: "300" 25 | Proxy-Connection: "keep-alive" 26 | output: 27 | log_contains: "id \"920230\"" 28 | - 29 | # From old modsec regression tests 30 | test_title: 920230-2 31 | stages: 32 | - 33 | stage: 34 | input: 35 | dest_addr: "127.0.0.1" 36 | port: 80 37 | uri: "/?parm=%7%6F%6D%65%74%65%78%74%5F%31%32%33%" 38 | headers: 39 | User-Agent: "ModSecurity CRS 3 Tests" 40 | Host: "localhost" 41 | Accept: "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" 42 | Accept-Language: "en-us,en;q=0.5" 43 | Accept-Charset: "ISO-8859-1,utf-8;q=0.7,*;q=0.7" 44 | Keep-Alive: "300" 45 | Proxy-Connection: "keep-alive" 46 | output: 47 | no_log_contains: "id \"920230\"" 48 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920260.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920260.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 920260-1 10 | stages: 11 | - 12 | stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | port: 80 16 | uri: "/?test=%uff0F" 17 | headers: 18 | User-Agent: "ModSecurity CRS 3 Tests" 19 | Host: "localhost" 20 | output: 21 | log_contains: "id \"920260\"" 22 | - 23 | test_title: 920260-2 24 | stages: 25 | - 26 | stage: 27 | input: 28 | dest_addr: "127.0.0.1" 29 | port: 80 30 | uri: "/?test=%u0F" 31 | headers: 32 | User-Agent: "ModSecurity CRS 3 Tests" 33 | Host: "localhost" 34 | output: 35 | no_log_contains: "id \"920260\"" 36 | - 37 | # Test taken from existing modsec regression 38 | test_title: 920260-3 39 | stages: 40 | - 41 | stage: 42 | input: 43 | dest_addr: "127.0.0.1" 44 | port: 80 45 | uri: "/?param=foo%uFF01" 46 | version: "HTTP/1.0" 47 | headers: 48 | User-Agent: "ModSecurity CRS 3 Tests" 49 | Host: "localhost" 50 | Accept: "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" 51 | Accept-Language: "en-us,en;q=0.5" 52 | Accept-Charset: "ISO-8859-1,utf-8;q=0.7,*;q=0.7" 53 | Keep-Alive: "300" 54 | Proxy-Connection: "keep-alive" 55 | output: 56 | log_contains: "id \"920260\"" -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920272.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920272.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 920272-1 10 | stages: 11 | - 12 | stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | port: 80 16 | uri: "/?test=test1%25" 17 | headers: 18 | User-Agent: "ModSecurity CRS 3 Tests" 19 | Host: "localhost" 20 | output: 21 | log_contains: "id \"920272\"" 22 | - 23 | test_title: 920272-2 24 | stages: 25 | - 26 | stage: 27 | input: 28 | dest_addr: "127.0.0.1" 29 | port: 80 30 | uri: "/?test=test1%80" 31 | headers: 32 | User-Agent: "ModSecurity CRS 3 Tests" 33 | Host: "localhost" 34 | output: 35 | log_contains: "id \"920272\"" 36 | - 37 | test_title: 920272-3 38 | stages: 39 | - 40 | stage: 41 | input: 42 | dest_addr: "127.0.0.1" 43 | port: 80 44 | uri: "/index.html?test=t%FFest1" 45 | headers: 46 | User-Agent: "ModSecurity CRS 3 Tests" 47 | Host: "localhost" 48 | output: 49 | log_contains: "id \"920272\"" 50 | - 51 | test_title: 920272-4 52 | stages: 53 | - 54 | stage: 55 | input: 56 | dest_addr: "127.0.0.1" 57 | port: 80 58 | uri: "/?test=test1%35" 59 | headers: 60 | User-Agent: "ModSecurity CRS 3 Tests" 61 | Host: "localhost" 62 | output: 63 | no_log_contains: "id \"920272\"" 64 | - 65 | # This will not trigger with Apache because Apache will block with AH00127 66 | #(22)Invalid argument: [client 127.0.0.1:47427] AH00127: Cannot map GET /i%FFndex.html?test=test1 HTTP/1.1 to file. It will return a 404 instead so we accept either. 67 | test_title: 920272-5 68 | stages: 69 | - 70 | stage: 71 | input: 72 | dest_addr: "127.0.0.1" 73 | port: 80 74 | uri: "/i%FFndex.html?test=test1" 75 | headers: 76 | User-Agent: "ModSecurity CRS 3 Tests" 77 | Host: "localhost" 78 | output: 79 | status: [403, 404] 80 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920273.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "csanders-git" 4 | enabled: true 5 | name: "920273.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 920273-1 10 | stages: 11 | - 12 | stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | port: 80 16 | uri: "/?test=test1%20" 17 | headers: 18 | User-Agent: "ModSecurity CRS 3 Tests" 19 | Host: "localhost" 20 | output: 21 | log_contains: "id \"920273\"" 22 | - 23 | # the '&' is one of the only symbol allowed 24 | test_title: 920273-2 25 | stages: 26 | - 27 | stage: 28 | input: 29 | dest_addr: "127.0.0.1" 30 | port: 80 31 | uri: "/?test=test1&test=t" 32 | headers: 33 | User-Agent: "ModSecurity CRS 3 Tests" 34 | Host: "localhost" 35 | output: 36 | no_log_contains: "id \"920273\"" 37 | - 38 | test_title: 920273-3 39 | stages: 40 | - 41 | stage: 42 | input: 43 | dest_addr: "127.0.0.1" 44 | port: 80 45 | uri: "/index.html?test=test1" 46 | headers: 47 | User-Agent: "ModSecurity CRS 3 Tests" 48 | Host: "localhost" 49 | data: "Shazam 30 | version: HTTP/1.1 31 | output: 32 | log_contains: id "921120" 33 | - 34 | test_title: 921120-2 35 | desc: "HTTP Response splitting attack" 36 | stages: 37 | - 38 | stage: 39 | input: 40 | dest_addr: 127.0.0.1 41 | headers: 42 | Host: localhost 43 | Proxy-Connection: keep-alive 44 | Referer: http 45 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 46 | method: GET 47 | port: 80 48 | uri: "/file.jsp?somevar=foobar%0d%0aContent-Length:%2002343432423ftw" 49 | version: HTTP/1.1 50 | output: 51 | log_contains: id "921120" 52 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921130.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 921130.yaml 7 | tests: 8 | - 9 | test_title: 921130-1 10 | desc: HTTP response splitting (921130) from old modsec regressions 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, 18 | application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, 19 | */* 20 | Accept-Encoding: gzip, deflate 21 | Accept-Language: zh-sg 22 | Host: localhost 23 | Keep-Alive: '300' 24 | Proxy-Connection: keep-alive 25 | Referer: http 26 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 27 | method: GET 28 | port: 80 29 | uri: /?lang=foobar%3Cmeta%20http-equiv%3D%22Refresh%22%20content%3D%220%3B%20url%3Dhttp%3A%2F%2Fwww.hacker.com%2F%22%3E 30 | version: HTTP/1.1 31 | output: 32 | log_contains: id "921130" 33 | - 34 | test_title: 921130-2 35 | desc: "HTTP Response splitting attack: cookie data" 36 | stages: 37 | - 38 | stage: 39 | input: 40 | dest_addr: 127.0.0.1 41 | headers: 42 | Host: "localhost" 43 | Cookie: "oreo=munchmuch%0d%0a%0d%0a" 44 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 45 | method: GET 46 | port: 80 47 | uri: "/" 48 | output: 49 | log_contains: id "921130" 50 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921140.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | enabled: true 5 | name: "921140.yaml" 6 | description: "Tests for protocol based attacks" 7 | tests: 8 | - 9 | test_title: 921140-1 10 | desc: "HTTP Header Injection Attack via headers" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: "127.0.0.1" 16 | method: "GET" 17 | port: 80 18 | headers: 19 | Host: "localhost" 20 | SomeHeader: "Headerdata\rInjectedHeader: response_splitting_code" 21 | uri: "/" 22 | output: 23 | status: 400 24 | no_log_contains: "id:921140" 25 | - 26 | test_title: 921140-2 27 | desc: "HTTP Header Injection Attack via headers" 28 | stages: 29 | - 30 | stage: 31 | input: 32 | dest_addr: "127.0.0.1" 33 | method: "GET" 34 | port: 80 35 | headers: 36 | Host: "localhost" 37 | SomeHeader: "Headerdata%0dInjectedHeader: response_splitting_code" 38 | uri: "/" 39 | output: 40 | no_log_contains: "id:921140" 41 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921150.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | enabled: true 5 | name: "921150.yaml" 6 | description: "Tests for protocol based attacks" 7 | tests: 8 | - 9 | test_title: 921150-1 10 | desc: "HTTP Header Injection Attack via payload" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: "127.0.0.1" 16 | method: "GET" 17 | port: 80 18 | headers: 19 | Host: "localhost" 20 | User-agent: "user agent" 21 | uri: "/script.jsp?variableX=bar&variable2=Y&%0d%0restofdata" 22 | output: 23 | log_contains: "id \"921150\"" 24 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921190.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Andrea Menin (theMiddle)" 4 | description: "HTTP Splitting" 5 | enabled: true 6 | name: 921190.yaml 7 | tests: 8 | - 9 | test_title: 921190-1 10 | desc: "New line char in request filename (1)" 11 | stages: 12 | - stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | headers: 16 | Host: "localhost" 17 | User-Agent: "ModSecurity CRS 3 Tests" 18 | port: 80 19 | uri: "/foo%0Abar" 20 | output: 21 | log_contains: id "921190" 22 | - 23 | test_title: 921190-2 24 | desc: "New line char in request filename (2)" 25 | stages: 26 | - stage: 27 | input: 28 | dest_addr: "127.0.0.1" 29 | headers: 30 | Host: "localhost" 31 | User-Agent: "ModSecurity CRS 3 Tests" 32 | port: 80 33 | uri: "/foo%0abar" 34 | output: 35 | log_contains: id "921190" 36 | - 37 | test_title: 921190-3 38 | desc: "FastCGI variable injection: Nginx + PHP-FPM (CVE-2019-11043)" 39 | stages: 40 | - stage: 41 | input: 42 | dest_addr: "127.0.0.1" 43 | headers: 44 | Host: "localhost" 45 | User-Agent: "ModSecurity CRS 3 Tests" 46 | port: 80 47 | uri: "/index.php/PHP%0Ainfo.php?QQQ" 48 | output: 49 | log_contains: id "921190" 50 | - 51 | test_title: 921190-4 52 | desc: "PHP Settings injection: Nginx + PHP-FPM (CVE-2019-11043)" 53 | stages: 54 | - stage: 55 | input: 56 | dest_addr: "127.0.0.1" 57 | headers: 58 | Host: "localhost" 59 | User-Agent: "ModSecurity CRS 3 Tests" 60 | port: 80 61 | uri: "/index.php/PHP_VALUE%0Asession.auto_start=1;;;?QQQ" 62 | output: 63 | log_contains: id "921190" 64 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-930-APPLICATION-ATTACK-LFI/930100.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | enabled: true 5 | name: "930100.yaml" 6 | description: "Application attack LFI" 7 | tests: 8 | - 9 | test_title: 930100-1 10 | desc: "Path Traversal Attack (/../) encoded" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: "127.0.0.1" 16 | method: "GET" 17 | port: 80 18 | headers: 19 | Host: "localhost" 20 | FoobarHeader: "0x5c0x2e.%00/" 21 | uri: "/" 22 | output: 23 | log_contains: id "930100" 24 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-931-APPLICATION-ATTACK-RFI/931100.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 931100.yaml 7 | tests: 8 | - 9 | test_title: 931100-1 10 | desc: Remote File Inclusion Attack (931100) from old modsec regressions 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, 18 | application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, 19 | */* 20 | Accept-Encoding: gzip, deflate 21 | Accept-Language: zh-sg 22 | Host: localhost 23 | Keep-Alive: '300' 24 | Proxy-Connection: keep-alive 25 | Referer: http 26 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 27 | method: GET 28 | port: 80 29 | uri: /wp-content/themes/thedawn/lib/scripts/timthumb.php?src=http://66.240.183.75/crash.php 30 | version: HTTP/1.1 31 | output: 32 | log_contains: id "931100" 33 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-933-APPLICATION-ATTACK-PHP/933100.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 933100.yaml 7 | tests: 8 | - 9 | test_title: 933100-1 10 | desc: PHP Injection Attack (933100) from old modsec regressions 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 18 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 19 | Accept-Encoding: gzip,deflate 20 | Accept-Language: en-us,en;q=0.5 21 | Host: localhost 22 | Keep-Alive: '300' 23 | Proxy-Connection: keep-alive 24 | User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv 25 | method: GET 26 | port: 80 27 | uri: /?foo=" 39 | output: 40 | log_contains: id "941330" 41 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941340.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | description: None 5 | enabled: true 6 | name: 941340.yaml 7 | tests: 8 | - 9 | test_title: 941340-1 10 | desc: "IE XSS Filters - Attack" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | method: POST 19 | port: 80 20 | data: "var=' infoo.bar=&var2=whatever" 21 | version: HTTP/1.0 22 | output: 23 | log_contains: id "941340" 24 | - 25 | test_title: 941340-2 26 | desc: "XSS test based on portswigger XSS cheatsheet" 27 | stages: 28 | - 29 | stage: 30 | input: 31 | dest_addr: 127.0.0.1 32 | headers: 33 | Host: localhost 34 | method: POST 35 | port: 80 36 | data: "payload=XSS" 37 | version: HTTP/1.0 38 | output: 39 | log_contains: id "941340" 40 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941350.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: fgsch 4 | enabled: true 5 | name: 941350.yaml 6 | description: Test rule 941350 7 | tests: 8 | - 9 | test_title: 941350-1 10 | desc: GH issue #1514 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | method: GET 17 | port: 80 18 | uri: /xx?id=%25252bADw-script%25252bAD4- 19 | headers: 20 | Accept: "*/*" 21 | Host: localhost 22 | User-Agent: ModSecurity CRS 3 Tests 23 | output: 24 | log_contains: id "941350" 25 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941380.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Franziska Buehler" 4 | description: None 5 | enabled: true 6 | name: 941380.yaml 7 | tests: 8 | - 9 | test_title: 941380-1 10 | desc: "AngularJS client side template injection detection" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | Accept: "*/*" 19 | User-Agent: "ModSecurity CRS 3 Tests" 20 | method: GET 21 | port: 80 22 | uri: '/login?user=%20x%20%7B%7Bconstructor.constructor(%27alert(1)%27)()%7D%7D%20.%20ff' 23 | # /login?user={{constructor.constructor('alert(1)')()}} 24 | version: HTTP/1.1 25 | output: 26 | log_contains: id "941380" 27 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942110.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | description: None 5 | enabled: true 6 | name: 942110.yaml 7 | tests: 8 | - 9 | test_title: 942110-1 10 | desc: "Common SQL Injection Testing" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | method: POST 19 | port: 80 20 | # NB: false positives: /?var=\'\' 21 | data: "var=%27%27" 22 | version: HTTP/1.0 23 | output: 24 | log_contains: id "942110" 25 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942180.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Christian S.J. Peron" 4 | description: None 5 | enabled: true 6 | name: 942180.yaml 7 | tests: 8 | - 9 | test_title: 942180-1 10 | desc: "basic SQL authentication bypass" 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Host: localhost 18 | method: GET 19 | port: 80 20 | # something simple like 3' ' 1 21 | uri: "/?var=3%27%20%27%201" 22 | version: HTTP/1.0 23 | output: 24 | log_contains: id "942180" 25 | - 26 | test_title: 942180-2 27 | desc: "XSS test based on portswigger XSS cheatsheet" 28 | stages: 29 | - 30 | stage: 31 | input: 32 | dest_addr: 127.0.0.1 33 | headers: 34 | Host: localhost 35 | method: POST 36 | port: 80 37 | uri: "/" 38 | version: HTTP/1.0 39 | data : "javascript:\"/*'/*`/*-->0}" 21 | version: HTTP/1.0 22 | output: 23 | log_contains: id "942500" 24 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942510.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Franziska Buehler" 4 | description: None 5 | enabled: true 6 | name: 942510.yaml 7 | tests: 8 | - test_title: 942510-1 9 | desc: "SQLi bypass detected: backticks" 10 | stages: 11 | - stage: 12 | input: 13 | dest_addr: 127.0.0.1 14 | headers: 15 | User-Agent: "ModSecurity CRS 3 Tests" 16 | Host: localhost 17 | method: GET 18 | port: 80 19 | uri: "/?`bla`" 20 | version: HTTP/1.0 21 | output: 22 | log_contains: id "942510" 23 | - test_title: 942510-2 24 | desc: "SQLi bypass detected: backticks" 25 | stages: 26 | - stage: 27 | input: 28 | dest_addr: 127.0.0.1 29 | headers: 30 | User-Agent: "ModSecurity CRS 3 Tests" 31 | Host: localhost 32 | method: GET 33 | port: 80 34 | uri: "/?'bla'" 35 | version: HTTP/1.0 36 | output: 37 | no_log_contains: id "942510" 38 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942511.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "Walter Hop" 4 | description: None 5 | enabled: true 6 | name: 942511.yaml 7 | tests: 8 | - test_title: 942511-1 9 | desc: "SQLi bypass detected: quotes" 10 | stages: 11 | - stage: 12 | input: 13 | dest_addr: 127.0.0.1 14 | headers: 15 | User-Agent: "ModSecurity CRS 3 Tests" 16 | Host: localhost 17 | method: GET 18 | port: 80 19 | uri: "/?`bla`" 20 | version: HTTP/1.0 21 | output: 22 | no_log_contains: id "942511" 23 | - test_title: 942511-2 24 | desc: "SQLi bypass detected: quotes" 25 | stages: 26 | - stage: 27 | input: 28 | dest_addr: 127.0.0.1 29 | headers: 30 | User-Agent: "ModSecurity CRS 3 Tests" 31 | Host: localhost 32 | method: GET 33 | port: 80 34 | uri: "/?'bla'" 35 | version: HTTP/1.0 36 | output: 37 | log_contains: id "942511" 38 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION/943100.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 943100.yaml 7 | tests: 8 | - 9 | test_title: 943100-1 10 | desc: Session Fixation Attack (943100) from old modsec regressions 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, 18 | application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, 19 | */* 20 | Accept-Encoding: gzip, deflate 21 | Accept-Language: zh-sg 22 | Host: localhost 23 | Keep-Alive: '300' 24 | Proxy-Connection: keep-alive 25 | Referer: http 26 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 27 | method: GET 28 | port: 80 29 | uri: /foo.php?bar=blah 30 | version: HTTP/1.1 31 | output: 32 | log_contains: id "943100" 33 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION/943120.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: csanders-git 4 | description: None 5 | enabled: true 6 | name: 943120.yaml 7 | tests: 8 | - 9 | test_title: 943120-1 10 | desc: Session Fixation Attack (943120) from old modsec regressions 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: 127.0.0.1 16 | headers: 17 | Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, 18 | application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, 19 | */* 20 | Accept-Encoding: gzip, deflate 21 | Accept-Language: zh-sg 22 | Host: localhost 23 | Keep-Alive: '300' 24 | Proxy-Connection: keep-alive 25 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 26 | method: GET 27 | port: 80 28 | uri: /login.php?jsessionid=74B0CB414BD77D17B5680A6386EF1666 29 | version: HTTP/1.1 30 | output: 31 | log_contains: id "943120" 32 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-944-APPLICATION-ATTACK-JAVA/944000.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "spartantri" 4 | enabled: true 5 | name: "944000.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 944000-1 10 | desc: Using text/plain Content-Type which do not have any bodyprocessor associated 11 | stages: 12 | - 13 | stage: 14 | input: 15 | dest_addr: "127.0.0.1" 16 | port: 80 17 | headers: 18 | Host: "localhost" 19 | User-Agent: "ModSecurity CRS 3 Tests" 20 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 21 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 22 | Accept-Encoding: gzip,deflate 23 | Accept-Language: en-us,en;q=0.5 24 | Content-Type: "text/plain" 25 | method: POST 26 | version: HTTP/1.0 27 | data: "test=value" 28 | output: 29 | no_log_contains: "id \"944000\"" 30 | -------------------------------------------------------------------------------- /tests/regression/tests/REQUEST-944-APPLICATION-ATTACK-JAVA/944200.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "spartantri" 4 | enabled: true 5 | name: "944200.yaml" 6 | description: "Description" 7 | tests: 8 | 9 | - 10 | test_title: 944200-0FP 11 | desc: Argument test includes java serialization magic bytes, raw request 12 | stages: 13 | - 14 | stage: 15 | input: 16 | stop_magic: true 17 | dest_addr: "127.0.0.1" 18 | port: 80 19 | raw_request: "POST / HTTP/1.0\r\nHost: localhost\r\nUser-Agent: ModSecurity CRS 3 Tests\r\nAccept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nAccept-Encoding: gzip,deflate\r\nAccept-Language: en-us,en;q=0.5\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 9\r\n\r\ntest=\xac\xed\x00\x05\r\n\r\n" 20 | output: 21 | no_log_contains: "id \"944200\"" 22 | 23 | - 24 | test_title: 944200-1 25 | desc: Argument test includes java serialization magic bytes, base64 encoded request 26 | stages: 27 | - 28 | stage: 29 | input: 30 | dest_addr: "127.0.0.1" 31 | port: 80 32 | encoded_request: "UE9TVCAvIEhUVFAvMS4wDQpIb3N0OiBsb2NhbGhvc3QNClVzZXItQWdlbnQ6IE1vZFNlY3VyaXR5IENSUyAzIFRlc3RzDQpBY2NlcHQ6IHRleHQveG1sLGFwcGxpY2F0aW9uL3htbCxhcHBsaWNhdGlvbi94aHRtbCt4bWwsdGV4dC9odG1sO3E9MC45LHRleHQvcGxhaW47cT0wLjgsaW1hZ2UvcG5nLCovKjtxPTAuNQ0KQWNjZXB0LUNoYXJzZXQ6IElTTy04ODU5LTEsdXRmLTg7cT0wLjcsKjtxPTAuNw0KQWNjZXB0LUVuY29kaW5nOiBnemlwLGRlZmxhdGUNCkFjY2VwdC1MYW5ndWFnZTogZW4tdXMsZW47cT0wLjUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkDQpDb250ZW50LUxlbmd0aDogOQ0KDQp0ZXN0PaztAAUNCg0K" 33 | output: 34 | log_contains: "id \"944200\"" 35 | 36 | -------------------------------------------------------------------------------- /tests/regression/utils/testSampling.py: -------------------------------------------------------------------------------- 1 | from ftw import ruleset, http, errors 2 | 3 | """ 4 | This script assumes that default blocking action is 403 5 | and sampling is one. It will send a know bad request 6 | that is expected to be blocked. If sampling is on it 7 | will only block a certain percentage. We send 1000 8 | requests to verify this. In order to do this we must 9 | also turn off IP Reputation blocking. 10 | SecAction "id:900005,phase:1,nolog,pass,ctl:ruleEngine=on,ctl:ruleRemoveById=910000" 11 | """ 12 | def send_requests(input_data,subiters,result,index): 13 | http_ua = http.HttpUA() 14 | for i in range(0,subiters): 15 | new_index = str(index)+str(i) 16 | http_ua.send_request(input_data) 17 | result[new_index] = http_ua.response_object.status 18 | def run_requests(iterations): 19 | """Post request with no content-type AND no content-length""" 20 | x = ruleset.Input(method="GET", protocol="http",port=80,uri='/?X=">',dest_addr="localhost",headers={"Host":"localhost","User-Agent":"ModSecurity CRS 3 test"}) 21 | import threading 22 | returns = {} 23 | threads = [] 24 | for i in range(5): 25 | t = threading.Thread(target=send_requests,args=(x,100, returns,i,)) 26 | threads.append(t) 27 | t.start() 28 | for t in threads: 29 | t.join() 30 | status_not_403 = 0 31 | status_403 = 0 32 | for status in returns.values(): 33 | if status == 403: 34 | status_403 += 1 35 | else: 36 | status_not_403 += 1 37 | x = (status_403/(len(returns)*1.0))*100 38 | y = (status_not_403/(len(returns)*1.0))*100 39 | print "403s =", x 40 | print "not 403s =", y 41 | return (x,y) 42 | 43 | def test_sampling(): 44 | print "running" 45 | block,passed = run_requests(100) 46 | assert block < 55 and block > 45 -------------------------------------------------------------------------------- /tests/regression/utils/testUserAgents.py: -------------------------------------------------------------------------------- 1 | from ftw import ruleset, http, errors 2 | 3 | """ 4 | This script reads in a list of popular Useragents and checks to see if it triggers 5 | It expects 403's to be returned for a rule firing 6 | """ 7 | 8 | def read_useragents(filename): 9 | f = open(filename,'r') 10 | useragents = [agent.strip() for agent in f.readlines()] 11 | return useragents 12 | 13 | def run_requests(useragent_list): 14 | status_not_403 = 0 15 | status_403 = 0 16 | for useragent in useragent_list: 17 | # get me a counter while i'm waiting 18 | if (status_not_403 + status_403)%15 == 0: 19 | print("Send",status_not_403 + status_403, "Out of",len(useragent_list)) 20 | input_data = ruleset.Input(method="GET", protocol="http",port=80,uri='/',dest_addr="localhost",headers={"Host":"localhost","User-Agent":useragent}) 21 | http_ua = http.HttpUA() 22 | http_ua.send_request(input_data) 23 | status = http_ua.response_object.status 24 | if status == 403: 25 | status_403 += 1 26 | else: 27 | status_not_403 += 1 28 | x = (status_403/(len(useragent_list)*1.0))*100 29 | y = (status_not_403/(len(useragent_list)*1.0))*100 30 | print "403s =", x 31 | print "not 403s =", y 32 | 33 | 34 | def main(): 35 | uas = read_useragents('./data/popularUAs.data') 36 | run_requests(uas) 37 | main() 38 | -------------------------------------------------------------------------------- /util/README: -------------------------------------------------------------------------------- 1 | The util directory contains many supporting tools/scripts that may be used with 2 | the OWASP ModSecurity CRS files. 3 | 4 | Docker Support 5 | ============== 6 | A Dockerfile can be found in the docker/ directory, along with additional 7 | notes in docker/README.md 8 | -------------------------------------------------------------------------------- /util/av-scanning/runAV/comp: -------------------------------------------------------------------------------- 1 | gcc -c -o common.o -DEXTERN= common.c 2 | gcc -o runAV -DEXTERN=extern common.o runAV.c 3 | -------------------------------------------------------------------------------- /util/av-scanning/runAV/runAV-clamd.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | main(int argc, char *argv[]) 4 | { 5 | char cmd[MAX_OUTPUT_SIZE]; 6 | char output[MAX_OUTPUT_SIZE]; 7 | int error; 8 | char *colon; 9 | char *keyword; 10 | 11 | if (argc > 1) { 12 | sprintf (cmd, "/usr/bin/clamdscan --no-summary %s", argv[1]); 13 | output[0] = '\0'; 14 | error = run_cmd(cmd,output,MAX_OUTPUT_SIZE); 15 | if (error != 0) { 16 | printf ("1 exec error %d: OK", error); 17 | } else if (!*output) { 18 | printf ("1 exec empty: OK"); 19 | } 20 | else { 21 | colon = strstr(output, ":"); 22 | if (colon) { colon += 2; } 23 | if (!colon) { 24 | printf ("0 unable to parse clamdscan output [%s] for cmd [%s]", output, cmd); 25 | } 26 | else if (keyword = strstr(colon, " FOUND")) { 27 | *keyword = '\0'; 28 | printf ("0 clamdscan: %s", colon); 29 | } 30 | else if (keyword = strstr(colon, " ERROR")) { 31 | *keyword = '\0'; 32 | printf ("0 clamdscan: %s", colon); 33 | } 34 | else if (keyword = strstr(colon, "OK")) { 35 | printf ("1 clamdscan: OK"); 36 | } 37 | else if (keyword = strstr(colon, "Empty file")) { 38 | printf ("1 empty file"); 39 | } 40 | else if (keyword = strstr(colon, "Can't access file ")) { 41 | printf ("0 invalid file %s", keyword+18); 42 | } 43 | else { 44 | printf ("0 unable to parse clamdscan output [%s] for cmd [%s]", output, cmd); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /util/av-scanning/runAV/runAV.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | main(int argc, char *argv[]) 4 | { 5 | char cmd[MAX_OUTPUT_SIZE]; 6 | char output[MAX_OUTPUT_SIZE]; 7 | int error; 8 | char *colon; 9 | char *keyword; 10 | 11 | if (argc > 1) { 12 | sprintf (cmd, "/usr/bin/clamscan --no-summary %s", argv[1]); 13 | output[0] = '\0'; 14 | error = run_cmd(cmd,output,MAX_OUTPUT_SIZE); 15 | if (error != 0) { 16 | printf ("1 exec error %d: OK", error); 17 | } else if (!*output) { 18 | printf ("1 exec empty: OK"); 19 | } 20 | else { 21 | colon = strstr(output, ":"); 22 | if (colon) { colon += 2; } 23 | if (!colon) { 24 | printf ("0 unable to parse clamscan output [%s] for cmd [%s]", output, cmd); 25 | } 26 | else if (keyword = strstr(colon, " FOUND")) { 27 | *keyword = '\0'; 28 | printf ("0 clamscan: %s", colon); 29 | } 30 | else if (keyword = strstr(colon, " ERROR")) { 31 | *keyword = '\0'; 32 | printf ("0 clamscan: %s", colon); 33 | } 34 | else if (keyword = strstr(colon, "OK")) { 35 | printf ("1 clamscan: OK"); 36 | } 37 | else if (keyword = strstr(colon, "Empty file")) { 38 | printf ("1 empty file"); 39 | } 40 | else if (keyword = strstr(colon, "Can't access file ")) { 41 | printf ("0 invalid file %s", keyword+18); 42 | } 43 | else { 44 | printf ("0 unable to parse clamscan output [%s] for cmd [%s]", output, cmd); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /util/av-scanning/runav.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | # runav.pl 4 | # Copyright (c) 2004-2011 Trustwave 5 | # 6 | # This script is an interface between ModSecurity and its 7 | # ability to intercept files being uploaded through the 8 | # web server, and ClamAV 9 | 10 | 11 | $CLAMSCAN = "clamscan"; 12 | 13 | if ($#ARGV != 0) { 14 | print "Usage: modsec-clamscan.pl \n"; 15 | exit; 16 | } 17 | 18 | my ($FILE) = shift @ARGV; 19 | 20 | $cmd = "$CLAMSCAN --stdout --disable-summary $FILE"; 21 | $input = `$cmd`; 22 | $input =~ m/^(.+)/; 23 | $error_message = $1; 24 | 25 | $output = "0 Unable to parse clamscan output [$1]"; 26 | 27 | if ($error_message =~ m/: Empty file\.?$/) { 28 | $output = "1 empty file"; 29 | } 30 | elsif ($error_message =~ m/: (.+) ERROR$/) { 31 | $output = "0 clamscan: $1"; 32 | } 33 | elsif ($error_message =~ m/: (.+) FOUND$/) { 34 | $output = "0 clamscan: $1"; 35 | } 36 | elsif ($error_message =~ m/: OK$/) { 37 | $output = "1 clamscan: OK"; 38 | } 39 | 40 | print "$output\n"; 41 | -------------------------------------------------------------------------------- /util/browser-tools/js-overrides.js: -------------------------------------------------------------------------------- 1 | (function() { // don't leak XSSTripwire into global ns 2 | 3 | /* 4 | Assumptions: 5 | - we need to run first, before any other attacker script 6 | - we can't prevent tripwire from being detected (e.g. by side effects) 7 | Todo: 8 | - a lot more in lockdown 9 | - protect XHR 10 | */ 11 | var XSSTripwire = new Object(); 12 | 13 | XSSTripwire.report = function() { 14 | // Notify server 15 | var notify = XSSTripwire.newXHR(); 16 | 17 | // Create a results string to send back 18 | var results; 19 | try { 20 | results = "HTML=" + encodeURIComponent(document.body.outerHTML); 21 | } catch (e) {} // we don't always have document.body 22 | 23 | notify.open("POST", XSSTripwire.ReportURL, true); 24 | notify.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 25 | notify.send(results); 26 | } 27 | 28 | XSSTripwire.lockdown = function(obj, name) { 29 | if (Object.defineProperty) { 30 | Object.defineProperty(obj, name, { 31 | configurable: false 32 | }) 33 | } 34 | } 35 | 36 | XSSTripwire.newXHR = function() { 37 | var xmlreq = false; 38 | if (window.XMLHttpRequest) { 39 | xmlreq = new XMLHttpRequest(); 40 | } else if (window.ActiveXObject) { 41 | // Try ActiveX 42 | try { 43 | xmlreq = new ActiveXObject("Msxml2.XMLHTTP"); 44 | } catch (e1) { 45 | // first method failed 46 | try { 47 | xmlreq = new ActiveXObject("Microsoft.XMLHTTP"); 48 | } catch (e2) { 49 | // both methods failed 50 | } 51 | } 52 | } 53 | return xmlreq; 54 | }; 55 | 56 | XSSTripwire.proxy = function(obj, name, report_function_name, exec_original) { 57 | var proxy = obj[name]; 58 | obj[name] = function() { 59 | // URL of the page to notify, in the event of a detected XSS event: 60 | XSSTripwire.ReportURL = "xss-tripwire-report?function=" + encodeURIComponent(report_function_name); 61 | 62 | XSSTripwire.report(); 63 | 64 | if (exec_original) { 65 | return proxy.apply(this, arguments); 66 | } 67 | }; 68 | XSSTripwire.lockdown(obj, name); 69 | }; 70 | 71 | XSSTripwire.proxy(window, 'alert', 'window.alert', true); 72 | XSSTripwire.proxy(window, 'confirm', 'window.confirm', true); 73 | XSSTripwire.proxy(window, 'prompt', 'window.prompt', true); 74 | XSSTripwire.proxy(window, 'unescape', 'unescape', true); 75 | XSSTripwire.proxy(document, 'write', 'document.write', true); 76 | XSSTripwire.proxy(String, 'fromCharCode', 'String.fromCharCode', true); 77 | 78 | })(); -------------------------------------------------------------------------------- /util/crs2-renumbering/README: -------------------------------------------------------------------------------- 1 | CRS 2.x to 3.x migration utility 2 | ================================ 3 | 4 | In CRS 3.0, we have renumbered the rules to be more logical and helpful. 5 | The new rule file names now correspond with the rule IDs in the file. 6 | First rule of a given file is usually 9XX100, then the rules continue 7 | in steps of ten. Related rules/siblings follow with a single digit 8 | change (9XX101, etc.). 9 | 10 | This utility replaces CRS 2 ruleIds with their CRS 3 counterparts. 11 | You can use it when migrating your CRS 2 exclusion/.conf files to CRS 3.0 12 | or higher. 13 | 14 | Example usage: 15 | 16 | ./update.py -f your_old_modsec_conf.conf 17 | 18 | Rules which have been removed in CRS 3 are listed with the new ID 000000 in the 19 | CSV file. This means that the former rule is no longer part of CRS 3. If after 20 | replacement you find a string 000000 in your config files, you can likely 21 | remove that exclusion or special case. 22 | 23 | If you want to create your own tooling for this migration, you can use 24 | the file idNumbering.csv in this directory. It lists the old rule IDs of 25 | CRS 2.2, together with the corresponding rule IDs in CRS 3.0. 26 | 27 | A rule renumbering is painful for all existing installations. But we really 28 | think that the rule IDs lacked sense and reason, and we are confident future 29 | maintenance will be much easier once this is done. We do not plan to change 30 | rule IDs after this. We appreciate your understanding in this matter. 31 | -------------------------------------------------------------------------------- /util/crs2-renumbering/update.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """This is designed to convert 2.x CRS ID numbering to 3.x CRS numbering""" 5 | from __future__ import print_function 6 | import csv 7 | import argparse 8 | import os 9 | import sys 10 | 11 | def main(): 12 | """Main function that contains all the logic to relabel CRS IDs""" 13 | 14 | id_translation_file = os.path.join(sys.path[0], "IdNumbering.csv") 15 | 16 | if not os.path.isfile(id_translation_file): 17 | sys.stderr.write("We were unable to locate the ID translation CSV (idNumbering.csv) \ 18 | please place this is the same directory as this script\n") 19 | sys.exit(1) 20 | 21 | parser = argparse.ArgumentParser(description="A program that takes in an exceptions file \ 22 | and renumbers all the ID to match OWASP CRS 3 numbers. Output will be directed to STDOUT.") 23 | parser.add_argument("-f", "--file", required=True, action="store", dest="fname", \ 24 | help="the file to be renumbered") 25 | args = parser.parse_args() 26 | 27 | if not os.path.isfile((args.fname).encode('utf8')): 28 | sys.stderr.write("We were unable to find the file you were trying to update the ID numbers \ 29 | in, please check your path\n") 30 | sys.exit(1) 31 | 32 | fcontent = "" 33 | 34 | try: 35 | update_file = open((args.fname).encode('utf-8'), "r") 36 | try: 37 | fcontent = update_file.read() 38 | finally: 39 | update_file.close() 40 | except IOError: 41 | sys.stderr.write("There was an error opening the file you were trying to update") 42 | 43 | if fcontent != "": 44 | # CSV File 45 | id_csv_file = open(id_translation_file, 'rt') 46 | try: 47 | reader = csv.reader(id_csv_file) 48 | for row in reader: 49 | fcontent = fcontent.replace(row[0], row[1]) 50 | finally: 51 | id_csv_file.close() 52 | print(fcontent) 53 | 54 | if __name__ == "__main__": 55 | main() 56 | -------------------------------------------------------------------------------- /util/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity:2.9-apache-ubuntu 2 | MAINTAINER Chaim Sanders chaim.sanders@gmail.com 3 | 4 | ARG COMMIT=v3.3/dev 5 | ARG REPO=SpiderLabs/owasp-modsecurity-crs 6 | ENV PARANOIA=1 7 | ENV ANOMALYIN=5 8 | ENV ANOMALYOUT=4 9 | 10 | RUN apt-get update && \ 11 | apt-get -y install python git ca-certificates iproute2 12 | 13 | RUN cd /opt && \ 14 | git clone https://github.com/${REPO}.git owasp-modsecurity-crs-3.2 && \ 15 | cd owasp-modsecurity-crs-3.2 && \ 16 | git checkout -qf ${COMMIT} 17 | 18 | RUN cd /opt && \ 19 | cp -R /opt/owasp-modsecurity-crs-3.2/ /etc/apache2/modsecurity.d/owasp-crs/ && \ 20 | mv /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf.example /etc/apache2/modsecurity.d/owasp-crs/crs-setup.conf && \ 21 | cd /etc/apache2/modsecurity.d && \ 22 | printf "include modsecurity.d/owasp-crs/crs-setup.conf\ninclude modsecurity.d/owasp-crs/rules/*.conf" > include.conf && \ 23 | sed -i -e 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/apache2/modsecurity.d/modsecurity.conf && \ 24 | a2enmod proxy proxy_http 25 | 26 | COPY proxy.conf /etc/apache2/modsecurity.d/proxy.conf 27 | COPY docker-entrypoint.sh / 28 | 29 | EXPOSE 80 30 | 31 | ENTRYPOINT ["/docker-entrypoint.sh"] 32 | CMD ["apachectl", "-D", "FOREGROUND"] 33 | -------------------------------------------------------------------------------- /util/docker/Dockerfile-2.9-apache: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity:2.9-apache 2 | LABEL maintainer="Chaim Sanders " 3 | 4 | ARG COMMIT=v3.3/dev 5 | ARG BRANCH=v3.3/dev 6 | ARG REPO=SpiderLabs/owasp-modsecurity-crs 7 | ENV WEBSERVER=Apache 8 | ENV PARANOIA=1 9 | ENV ANOMALYIN=5 10 | ENV ANOMALYOUT=4 11 | 12 | RUN apt-get update && \ 13 | apt-get -y install python git ca-certificates iproute2 && \ 14 | mkdir /opt/owasp-modsecurity-crs-3.2 && \ 15 | cd /opt/owasp-modsecurity-crs-3.2 && \ 16 | git init && \ 17 | git remote add origin https://github.com/${REPO} && \ 18 | git fetch --depth 1 origin ${BRANCH} && \ 19 | git checkout ${COMMIT} && \ 20 | mv crs-setup.conf.example crs-setup.conf && \ 21 | ln -sv /opt/owasp-modsecurity-crs-3.2 /etc/modsecurity.d/owasp-crs && \ 22 | printf "include /etc/modsecurity.d/owasp-crs/crs-setup.conf\ninclude /etc/modsecurity.d/owasp-crs/rules/*.conf" >> /etc/modsecurity.d/include.conf && \ 23 | sed -i -e 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/modsecurity.d/modsecurity.conf 24 | 25 | COPY httpd-logging-before-modsec.conf /usr/local/apache2/conf/extra/httpd-logging-before-modsec.conf 26 | COPY httpd-logging-after-modsec.conf /usr/local/apache2/conf/extra/httpd-logging-after-modsec.conf 27 | COPY docker-entrypoint.sh / 28 | 29 | EXPOSE 80 30 | EXPOSE 443 31 | 32 | ENTRYPOINT ["/docker-entrypoint.sh"] 33 | CMD ["apachectl", "-D", "FOREGROUND"] 34 | -------------------------------------------------------------------------------- /util/docker/Dockerfile-3.0-apache: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity:3.0-apache 2 | LABEL maintainer="Chaim Sanders " 3 | 4 | ARG COMMIT=v3.3/dev 5 | ARG BRANCH=v3.3/dev 6 | ARG REPO=SpiderLabs/owasp-modsecurity-crs 7 | ENV WEBSERVER=Apache 8 | ENV PARANOIA=1 9 | ENV ANOMALYIN=5 10 | ENV ANOMALYOUT=4 11 | 12 | RUN apt-get update && \ 13 | apt-get -y install python git ca-certificates iproute2 && \ 14 | mkdir /opt/owasp-modsecurity-crs-3.2 && \ 15 | cd /opt/owasp-modsecurity-crs-3.2 && \ 16 | git init && \ 17 | git remote add origin https://github.com/${REPO} && \ 18 | git fetch --depth 1 origin ${BRANCH} && \ 19 | git checkout ${COMMIT} && \ 20 | mv crs-setup.conf.example crs-setup.conf && \ 21 | ln -sv /opt/owasp-modsecurity-crs-3.2 /etc/modsecurity.d/owasp-crs && \ 22 | printf "include /etc/modsecurity.d/owasp-crs/crs-setup.conf\ninclude /etc/modsecurity.d/owasp-crs/rules/*.conf" >> /etc/modsecurity.d/include.conf && \ 23 | sed -i -e 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/modsecurity.d/modsecurity.conf && \ 24 | mkdir /var/log/apache2/ && \ 25 | sed -i 's|ErrorLog\s.*$|ErrorLog /var/log/apache2/error.log|g' /usr/local/apache2/conf/httpd.conf 26 | 27 | COPY proxy.conf /etc/modsecurity.d/proxy.conf 28 | COPY docker-entrypoint.sh / 29 | 30 | EXPOSE 80 31 | 32 | ENTRYPOINT ["/docker-entrypoint.sh"] 33 | CMD ["apachectl", "-D", "FOREGROUND"] 34 | -------------------------------------------------------------------------------- /util/docker/Dockerfile-3.0-nginx: -------------------------------------------------------------------------------- 1 | FROM owasp/modsecurity:3.0-nginx 2 | LABEL maintainer="Chaim Sanders " 3 | 4 | ARG COMMIT=v3.3/dev 5 | ARG BRANCH=v3.3/dev 6 | ARG REPO=SpiderLabs/owasp-modsecurity-crs 7 | ENV WEBSERVER=Nginx 8 | ENV PARANOIA=1 9 | ENV ANOMALYIN=5 10 | ENV ANOMALYOUT=4 11 | 12 | RUN apt-get update && \ 13 | apt-get -y install python git ca-certificates iproute2 && \ 14 | mkdir /opt/owasp-modsecurity-crs-3.2 && \ 15 | cd /opt/owasp-modsecurity-crs-3.2 && \ 16 | git init && \ 17 | git remote add origin https://github.com/${REPO} && \ 18 | git fetch --depth 1 origin ${BRANCH} && \ 19 | git checkout ${COMMIT} && \ 20 | mv crs-setup.conf.example crs-setup.conf && \ 21 | ln -sv /opt/owasp-modsecurity-crs-3.2 /etc/modsecurity.d/owasp-crs && \ 22 | printf "include /etc/modsecurity.d/owasp-crs/crs-setup.conf\ninclude /etc/modsecurity.d/owasp-crs/rules/*.conf" >> /etc/modsecurity.d/include.conf && \ 23 | sed -i -e 's/SecRuleEngine DetectionOnly/SecRuleEngine On/g' /etc/modsecurity.d/modsecurity.conf 24 | 25 | COPY docker-entrypoint.sh / 26 | 27 | EXPOSE 80 28 | 29 | ENTRYPOINT ["/docker-entrypoint.sh"] 30 | CMD ["nginx", "-g", "daemon off;"] 31 | -------------------------------------------------------------------------------- /util/docker/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf: -------------------------------------------------------------------------------- 1 | # https://github.com/SpiderLabs/owasp-modsecurity-crs/blob/v3.2/dev/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example 2 | # 3 | # "...,ctl:ruleRemoveById=942100" 4 | # "...,ctl:ruleRemoveByTag=attack-sqli" 5 | # "...,ctl:ruleRemoveTargetById=942100;ARGS:password" 6 | # "...,ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:password" 7 | 8 | -------------------------------------------------------------------------------- /util/docker/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf: -------------------------------------------------------------------------------- 1 | # https://github.com/SpiderLabs/owasp-modsecurity-crs/blob/v3.2/dev/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example 2 | # 3 | # Examples: 4 | # SecRuleRemoveById 942100 5 | # SecRuleRemoveByTag "attack-sqli" 6 | # SecRuleUpdateTargetById 942100 "!ARGS:password" 7 | # SecRuleUpdateTargetByTag "attack-sqli" "!ARGS:password" 8 | -------------------------------------------------------------------------------- /util/docker/httpd-logging-after-modsec.conf: -------------------------------------------------------------------------------- 1 | # === ModSec Timestamps at the End of Each Phase (ids: 90010 - 90019) 2 | 3 | SecAction "id:90010,phase:1,pass,nolog,setvar:TX.ModSecTimestamp1end=%{DURATION}" 4 | SecAction "id:90011,phase:2,pass,nolog,setvar:TX.ModSecTimestamp2end=%{DURATION}" 5 | SecAction "id:90012,phase:3,pass,nolog,setvar:TX.ModSecTimestamp3end=%{DURATION}" 6 | SecAction "id:90013,phase:4,pass,nolog,setvar:TX.ModSecTimestamp4end=%{DURATION}" 7 | SecAction "id:90014,phase:5,pass,nolog,setvar:TX.ModSecTimestamp5end=%{DURATION}" 8 | 9 | 10 | # === ModSec performance calculations and variable export (ids: 90100 - 90199) 11 | 12 | SecAction "id:90100,phase:5,pass,nolog,\ 13 | setvar:TX.perf_modsecinbound=%{PERF_PHASE1},\ 14 | setvar:TX.perf_modsecinbound=+%{PERF_PHASE2},\ 15 | setvar:TX.perf_application=%{TX.ModSecTimestamp3start},\ 16 | setvar:TX.perf_application=-%{TX.ModSecTimestamp2end},\ 17 | setvar:TX.perf_modsecoutbound=%{PERF_PHASE3},\ 18 | setvar:TX.perf_modsecoutbound=+%{PERF_PHASE4},\ 19 | setenv:ModSecTimeIn=%{TX.perf_modsecinbound},\ 20 | setenv:ApplicationTime=%{TX.perf_application},\ 21 | setenv:ModSecTimeOut=%{TX.perf_modsecoutbound},\ 22 | setenv:ModSecAnomalyScoreInPLs=%{tx.anomaly_score_pl1}-%{tx.anomaly_score_pl2}-%{tx.anomaly_score_pl3}-%{tx.anomaly_score_pl4},\ 23 | setenv:ModSecAnomalyScoreOutPLs=%{tx.outbound_anomaly_score_pl1}-%{tx.outbound_anomaly_score_pl2}-%{tx.outbound_anomaly_score_pl3}-%{tx.outbound_anomaly_score_pl4},\ 24 | setenv:ModSecAnomalyScoreIn=%{TX.anomaly_score},\ 25 | setenv:ModSecAnomalyScoreOut=%{TX.outbound_anomaly_score}" 26 | -------------------------------------------------------------------------------- /util/docker/httpd-logging-before-modsec.conf: -------------------------------------------------------------------------------- 1 | ErrorLog ${ERRORLOG} 2 | 3 | # For more information regarding the values in the extended log format 4 | # and aliases and scripts to extract information please read: 5 | # https://www.netnea.com/cms/apache-tutorial-5_extending-access-log/ 6 | # https://www.netnea.com/cms/apache-tutorial-7_including-modsecurity-core-rules/ 7 | 8 | LoadModule logio_module /usr/local/apache2/modules/mod_logio.so 9 | 10 | LogFormat "%h %{GEOIP_COUNTRY_CODE}e %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] \"%r\" %>s %b \ 11 | \"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" %{remote}p %v %A %p %R \ 12 | %{BALANCER_WORKER_ROUTE}e %X \"%{cookie}n\" %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x \ 13 | %I %O %{ratio}n%% %D %{ModSecTimeIn}e %{ApplicationTime}e %{ModSecTimeOut}e \ 14 | %{ModSecAnomalyScoreInPLs}e %{ModSecAnomalyScoreOutPLs}e \ 15 | %{ModSecAnomalyScoreIn}e %{ModSecAnomalyScoreOut}e" extended 16 | 17 | CustomLog ${ACCESSLOG} extended 18 | 19 | 20 | # === ModSec timestamps at the start of each phase (ids: 90000 - 90009) 21 | 22 | SecAction "id:90000,phase:1,nolog,pass,setvar:TX.ModSecTimestamp1start=%{DURATION}" 23 | SecAction "id:90001,phase:2,nolog,pass,setvar:TX.ModSecTimestamp2start=%{DURATION}" 24 | SecAction "id:90002,phase:3,nolog,pass,setvar:TX.ModSecTimestamp3start=%{DURATION}" 25 | SecAction "id:90003,phase:4,nolog,pass,setvar:TX.ModSecTimestamp4start=%{DURATION}" 26 | SecAction "id:90004,phase:5,nolog,pass,setvar:TX.ModSecTimestamp5start=%{DURATION}" 27 | -------------------------------------------------------------------------------- /util/docker/proxy.conf: -------------------------------------------------------------------------------- 1 | 2 | ProxyPass "/" "http://${UPSTREAM}/" 3 | 4 | -------------------------------------------------------------------------------- /util/geo-location/README: -------------------------------------------------------------------------------- 1 | License 2 | The GeoLite databases are distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. The attribution requirement may be met by including the following in all advertising and documentation mentioning features of or use of this database: 3 | 4 | This product includes GeoLite data created by MaxMind, available from 5 | http://www.maxmind.com. 6 | -------------------------------------------------------------------------------- /util/honeypot-sensor/README.md: -------------------------------------------------------------------------------- 1 | The purpose of these files is to turn your current ModSecurity host into 2 | a pseudo-honeypot sensor by doing the following: 3 | 4 | 1. Instructs Apache to listen for traffic on multiple unused ports 5 | - 8000 6 | - 8080 7 | - 8888 8 | 2. Creates Apache virtual host containers to bind to these ports. 9 | 3. If any traffic is received on these ports, then ModSecurity will 10 | inspect the traffic by inheriting any rules specified in the main 11 | Apache configuration. 12 | 4. ModSecurity's Audit Engine will use the mlogc program to forward 13 | the audit log entry onto the ModSecurity Project's central logging 14 | server. 15 | -------------------------------------------------------------------------------- /util/honeypot-sensor/modsecurity_crs_10_honeypot.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Add in honeypot ports. 3 | # - These are common proxy ports used by attackers 4 | # - All traffic accepted on these ports are suspicious. 5 | # 6 | Listen 8000 7 | Listen 8080 8 | Listen 8888 9 | 10 | # 11 | # Create basic virtual host containers that will forward all traffic received 12 | # to the official ModSecurity Project honeypot logging host. 13 | # 14 | # - You should adjust the Document root location to an empty directory on your server 15 | # - Also adjust the path to your local ModSecurity mlogc program and for the 16 | # mlogc-honeypot-sensor.conf file. 17 | # - Make sure you main SecAuditLogType is set to concurrent mode. 18 | # 19 | 20 | ServerName www.example1.com 21 | DocumentRoot "/usr/local/apache/honeypot-htdocs" 22 | 23 | Options none 24 | AllowOverride None 25 | Order allow,deny 26 | Allow from all 27 | 28 | SecAuditEngine On 29 | SecAuditLog "|/usr/local/apache/bin/mlogc /usr/local/apache/conf/mlogc-honeypot-sensor.conf" 30 | 31 | 32 | -------------------------------------------------------------------------------- /util/id-range: -------------------------------------------------------------------------------- 1 | 900000-2999999 2 | 2000000-299999 3 | -------------------------------------------------------------------------------- /util/join-multiline-rules/join.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This script reads all the rule files passed on the command line, 4 | # and outputs them, with each (multi-line) directive joined as a 5 | # single line. 6 | # 7 | # This can be used to work around a bug in Apache < 2.4.11 in 8 | # parsing long configuration directives. 9 | # 10 | # Usage: 11 | # 12 | # util/join-multiline-rules/join.py rules/*.conf > rules/rules.conf.joined 13 | # 14 | # This produces a single 'rules.conf.joined' file that can be included 15 | # in buggy Apache versions. It is recommended to keep this file in the 16 | # rules/ directory (because it refers to .data files in that directory) 17 | # but give it a name not ending in .conf (so the file will not be 18 | # included in *.conf and you can re-run the command multiple times 19 | # without including its own output). 20 | # 21 | # Example: 22 | # 23 | # SecRule &TX:paranoia_level "@eq 0" \ 24 | # "id:901120,\ 25 | # phase:1,\ 26 | # pass,\ 27 | # nolog,\ 28 | # setvar:tx.paranoia_level=1" 29 | # 30 | # will be outputted as: 31 | # 32 | # SecRule &TX:paranoia_level "@eq 0" "id:901120,phase:1,pass,nolog,setvar:tx.paranoia_level=1" 33 | # 34 | 35 | import fileinput, sys 36 | 37 | for line in fileinput.input(): 38 | line = line.strip() 39 | if line == '': 40 | sys.stdout.write("\n") 41 | continue 42 | 43 | if line[-1] == '\\': 44 | sys.stdout.write(line[0:-1]) 45 | else: 46 | sys.stdout.write(line) 47 | sys.stdout.write("\n") 48 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-932106.txt: -------------------------------------------------------------------------------- 1 | # Word list for rule 932106 (RCE Unix command injection part 3/3) 2 | # 3 | # To convert to a regexp that can be pasted into the rule: 4 | # cat regexp-932106.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl 5 | # 6 | # 7 | # Entries starting with ' are used verbatim. 8 | # Everything after # is a comment. 9 | # 10 | # To prevent some FP for a command, you can require command parameters 11 | # after a command. Only do this if the command regularly causes FP and if 12 | # allowing the bare command (without parameters) is not too dangerous. 13 | # (Note: due to \b following the regexp, a word boundary is also required 14 | # further on, so some letter/number is needed for a match). Example: 15 | # 16 | # diff+ 17 | 18 | vi+ 19 | ps 20 | pwd 21 | who 22 | w+ 23 | aptitude+ 24 | pacman+ 25 | dnf+ 26 | up2date+ 27 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-932130.data: -------------------------------------------------------------------------------- 1 | \$\(.*\) 2 | \$\{.*\} 3 | <\(.*\) 4 | >\(.*\) 5 | \$\(\(.*\)\) 6 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-932140.data: -------------------------------------------------------------------------------- 1 | \bfor(?:/[dflr].*)? %+[^ ]+ in\(.*\)\s?do 2 | \bif(?:/i)?(?: not)?(?: exist\b| defined\b| errorlevel\b| cmdextversion\b|(?: |\().*(?:\bgeq\b|\bequ\b|\bneq\b|\bleq\b|\bgtr\b|\blss\b|==)) 3 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-933131.data: -------------------------------------------------------------------------------- 1 | AUTH_TYPE 2 | HTTP_ACCEPT 3 | HTTP_ACCEPT_CHARSET 4 | HTTP_ACCEPT_ENCODING 5 | HTTP_ACCEPT_LANGUAGE 6 | HTTP_CONNECTION 7 | HTTP_HOST 8 | HTTP_KEEP_ALIVE 9 | HTTP_REFERER 10 | HTTP_USER_AGENT 11 | HTTP_X_FORWARDED_FOR 12 | ORIG_PATH_INFO 13 | PATH_INFO 14 | PATH_TRANSLATED 15 | QUERY_STRING 16 | REQUEST_URI 17 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-933161.data: -------------------------------------------------------------------------------- 1 | abs 2 | acos 3 | acosh 4 | array 5 | arsort 6 | asin 7 | asinh 8 | asort 9 | assert 10 | atan 11 | atan2 12 | atanh 13 | basename 14 | bindec 15 | ceil 16 | chdir 17 | checkdate 18 | chmod 19 | chop 20 | chown 21 | chroot 22 | closedir 23 | closelog 24 | compact 25 | constant 26 | copy 27 | cos 28 | cosh 29 | count 30 | crypt 31 | current 32 | date 33 | decoct 34 | define 35 | defined 36 | die 37 | dir 38 | dirname 39 | diskfreespace 40 | dl 41 | doubleval 42 | each 43 | easter_date 44 | easter_days 45 | echo 46 | empty 47 | end 48 | ereg 49 | eregi 50 | error_log 51 | exit 52 | exp 53 | explode 54 | extract 55 | fclose 56 | feof 57 | fgets 58 | fileowner 59 | filepro 60 | filesize 61 | filetype 62 | floatval 63 | flock 64 | floor 65 | flush 66 | fmod 67 | fread 68 | fstat 69 | ftell 70 | ftok 71 | function 72 | getdate 73 | gettext 74 | gettype 75 | gmdate 76 | hash 77 | header 78 | headers_list 79 | headers_sent 80 | hebrev 81 | hypot 82 | iconv 83 | idate 84 | implode 85 | include 86 | intdiv 87 | intval 88 | invoke 89 | is_a 90 | is_array 91 | is_bool 92 | is_callable 93 | is_double 94 | is_finite 95 | is_float 96 | is_infinite 97 | is_int 98 | is_integer 99 | is_link 100 | is_long 101 | is_nan 102 | is_null 103 | is_numeric 104 | is_object 105 | is_real 106 | is_resource 107 | is_scalar 108 | is_string 109 | isset 110 | join 111 | key 112 | ksort 113 | lcfirst 114 | levenshtein 115 | link 116 | linkinfo 117 | list 118 | localtime 119 | log 120 | log10 121 | log1p 122 | lstat 123 | ltrim 124 | mail 125 | main 126 | max 127 | mbereg 128 | mbsplit 129 | metaphone 130 | mhash 131 | microtime 132 | min 133 | msql 134 | mysql 135 | natsort 136 | next 137 | octdec 138 | openlog 139 | ord 140 | pack 141 | pathinfo 142 | pclose 143 | pi 144 | pos 145 | pow 146 | prev 147 | print 148 | printf 149 | quotemeta 150 | rand 151 | range 152 | readline 153 | readlink 154 | recode 155 | rename 156 | require 157 | reset 158 | rewind 159 | round 160 | rsort 161 | rtrim 162 | scandir 163 | serialize 164 | settype 165 | shuffle 166 | similar_text 167 | sin 168 | sinh 169 | sizeof 170 | sleep 171 | sort 172 | soundex 173 | split 174 | spliti 175 | sprintf 176 | sqrt 177 | srand 178 | stat 179 | strcoll 180 | strlen 181 | strspn 182 | substr 183 | symlink 184 | syslog 185 | taint 186 | tan 187 | tanh 188 | tempnam 189 | textdomain 190 | time 191 | touch 192 | trim 193 | ucfirst 194 | umask 195 | uniqid 196 | unlink 197 | unset 198 | untaint 199 | usleep 200 | usort 201 | virtual 202 | wordwrap 203 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-934100.txt: -------------------------------------------------------------------------------- 1 | _\$\$ND_FUNC\$\$_ 2 | __js_function 3 | \beval\s*\( 4 | String\s*\.\s*fromCharCode 5 | function\s*\(\s*\)\s*{ 6 | new\s+Function\s*\( 7 | this\.constructor 8 | module\.exports\s*= -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-941130.data: -------------------------------------------------------------------------------- 1 | (?i)[\s\S]xlink:href\b 2 | (?i)[\s\S]xhtml\b 3 | (?i)[\s\S]xmlns\b 4 | (?i)[\s\S]!ENTITY\s+(?:\S+|%\s+\S+)\s+SYSTEM\b 5 | (?i)[\s\S]!ENTITY\s+(?:\S+|%\s+\S+)\s+PUBLIC\b 6 | (?i)[\s\S]data:text/html\b 7 | (?i)[\s\S]formaction\b 8 | (?i)[\s\S]@import\b 9 | (?i)[\s\S];base64\b 10 | (?i)[\s\S]pattern\b.*?=\b 11 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942120.data: -------------------------------------------------------------------------------- 1 | \!\= 2 | \&\& 3 | \|\| 4 | >> 5 | << 6 | >= 7 | <= 8 | <> 9 | <=> 10 | \bxor\b 11 | \bregexp\b 12 | regexp\s+binary 13 | \bisnull\b 14 | \brlike\b 15 | rlike\s+binary 16 | not\s+between\s+0\s+and 17 | is\s+null 18 | like\s+null 19 | ^in[+\s]*\([\s\d\"]+[^()]*\) 20 | \Win[+\s]*\([\s\d\"]+[^()]*\) 21 | <>\s+binary 22 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942130.data: -------------------------------------------------------------------------------- 1 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?=[\s'\"`()]*?(?:\b\1\b) 2 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=>[\s'\"`()]*?(?:\b\1\b) 3 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?like[\s'\"`()]*?(?:\b\1\b) 4 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?rlike[\s'\"`()]*?(?:\b\1\b) 5 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?sounds\s+like[\s'\"`()]*?(?:\b\1\b) 6 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?regexp[\s'\"`()]*?(?:\b\1\b) 7 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?!=[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 8 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 9 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>=[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 10 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<>[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 11 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 12 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 13 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?\^[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 14 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?is\s+not[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 15 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+like[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 16 | [\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+regexp[\s'\"`()]*?(?!\b\1\b)[\d\w]+ 17 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942140.data: -------------------------------------------------------------------------------- 1 | database\W*\( 2 | db_name\W*\( 3 | information_schema\b 4 | master\.\.sysdatabases\b 5 | msdb\b 6 | msysaccessobjects\b 7 | msysaccessstorage\b 8 | msysaccessxml\b 9 | msysaces\b 10 | msysmodules2\b 11 | msysmodules\b 12 | msysobjects\b 13 | msysqueries\b 14 | msysrelationships\b 15 | mysql\.db\b 16 | northwind\b 17 | pg_catalog\b 18 | pg_toast\b 19 | schema_name\b 20 | schema\W*\( 21 | sqlite_master\b 22 | sqlite_temp_master\b 23 | sysaux\b 24 | sys\.database_name\b 25 | tempdb\b 26 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942170.data: -------------------------------------------------------------------------------- 1 | select\s+benchmark\s*?\(\s*?[(]?\s*?\w+ 2 | ;\s+benchmark\s*?\(\s*?[(]?\s*?\w+ 3 | select\s+if\s*?\(\s*?[(]?\s*?\w+ 4 | ;\s+if\s*?\(\s*?[(]?\s*?\w+ 5 | select\s+sleep\s*?\(\s*?[(]?\s*?\w+ 6 | ;\s+sleep\s*?\(\s*?[(]?\s*?\w+ 7 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942180.data: -------------------------------------------------------------------------------- 1 | \d[\"'`]\s+[\"'`]\s+\d 2 | ^admin\s*?[\"'`] 3 | (?:/\*)+[\"'`]+\s? 4 | (?:/\*)+[\"'`]+\s?-- 5 | (?:/\*)+[\"'`]+\s?# 6 | (?:/\*)+[\"'`]+\s?/\* 7 | (?:/\*)+[\"'`]+\s?{ 8 | [\"'`]\s*?or[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 9 | [\"'`]\s*?xor[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 10 | [\"'`]\s*?div[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 11 | [\"'`]\s*?like[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 12 | [\"'`]\s*?between[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 13 | [\"'`]\s*?and[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`] 14 | [\"'`]\s*?[^\w\s]?=\s*?[\"'`] 15 | [\"'`]\W*?[+=]+\W*?[\"'`] 16 | [\"'`]\s*?[!=|][\d\s!=+-]+.*?[\"'`(].*?$ 17 | [\"'`]\s*?[!=|][\d\s!=]+.*?\d+$ 18 | [\"'`]\s*?like\W+[\w\"'`(] 19 | \sis\s*?0\W 20 | where\s[\s\w\.,-]+\s= 21 | [\"'`][<>~]+[\"'`] 22 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942190.data: -------------------------------------------------------------------------------- 1 | [\"'`]\s*?!\s*?[\"'`\w] 2 | [\"'`];?\s*?having\b\s*?[^\s] 3 | [\"'`];?\s*?select\b\s*?[^\s] 4 | [\"'`];?\s*?union\b\s*?[^\s] 5 | \s*?exec.*?\Wxp_cmdshell 6 | \s*?execute.*?\Wxp_cmdshell 7 | \wiif\s*?\( 8 | connection_id\s*?\([^\)]*? 9 | current_user\s*?\([^\)]*? 10 | database\s*?\([^\)]*? 11 | exec\s+master\. 12 | execute\s+master\. 13 | from\W+information_schema\W 14 | into[\s+]+dumpfile\s*?[\"'`] 15 | into[\s+]+outfile\s*?[\"'`] 16 | schema\s*?\([^\)]*? 17 | select.*?\w?user\( 18 | union select @ 19 | union[\w(\s]*?select 20 | user\s*?\([^\)]*? 21 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942200.data: -------------------------------------------------------------------------------- 1 | ,.*?[)\da-f\"'`][\"'`][\"'`].*?[\"'`] 2 | ,.*?[)\da-f\"'`][\"'`](?:\r?\n)?\z 3 | ,.*?[)\da-f\"'`][\"'`][^\"'`]+ 4 | \Wselect.+\W*?from 5 | select\s*?\(\s*?space\s*?\( 6 | create\s*?\(\s*?space\s*?\( 7 | rename\s*?\(\s*?space\s*?\( 8 | truncate\s*?\(\s*?space\s*?\( 9 | load\s*?\(\s*?space\s*?\( 10 | alter\s*?\(\s*?space\s*?\( 11 | delete\s*?\(\s*?space\s*?\( 12 | update\s*?\(\s*?space\s*?\( 13 | insert\s*?\(\s*?space\s*?\( 14 | desc\s*?\(\s*?space\s*?\( 15 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942210.data: -------------------------------------------------------------------------------- 1 | @.+=\s*?\(\s*?select 2 | \d+\s*?or\s*?\d+\s*?[\-+] 3 | \d+\s*?xor\s*?\d+\s*?[\-+] 4 | \d+\s*?div\s*?\d+\s*?[\-+] 5 | \d+\s*?like\s*?\d+\s*?[\-+] 6 | \d+\s*?between\s*?\d+\s*?[\-+] 7 | \d+\s*?and\s*?\d+\s*?[\-+] 8 | \/\w+;?\s+having\W 9 | \/\w+;?\s+and\W 10 | \/\w+;?\s+or\W 11 | \/\w+;?\s+xor\W 12 | \/\w+;?\s+div\W 13 | \/\w+;?\s+like\W 14 | \/\w+;?\s+between\W 15 | \/\w+;?\s+select\W 16 | \d\s+group\s+by.+\( 17 | ;\s*?drop 18 | #\s*?drop 19 | --\s*?drop 20 | ;\s*?alter 21 | #\s*?alter 22 | --\s*?alter 23 | ;\s*?update\s*?\w{2,} 24 | #\s*?update\s*?\w{2,} 25 | --\s*?update\s*?\w{2,} 26 | ;\s*?insert\s*?\w{2,} 27 | #\s*?insert\s*?\w{2,} 28 | --\s*?insert\s*?\w{2,} 29 | [^\w]SET\s*?@\w+ 30 | and[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 31 | nand[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 32 | or[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 33 | xor[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 34 | xxor[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 35 | div[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 36 | like[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 37 | between[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 38 | not[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 39 | \|\|[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 40 | \&\&[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()] 41 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942240.data: -------------------------------------------------------------------------------- 1 | alter\s*?\w+.*?character\s+set\s+\w+ 2 | alter\s*?\w+.*?char\s+set\s+\w+ 3 | [\"'`];*?\s*?waitfor\s+time\s+[\"'`] 4 | [\"'`];*?\s*?waitfor\s+delay\s+[\"'`] 5 | [\"'`];.*?:\s*?goto 6 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942260.data: -------------------------------------------------------------------------------- 1 | union\s*?\s*?[([]*?\s*?select\s+ 2 | union\s*?all\s*?[([]*?\s*?select\s+ 3 | union\s*?distinct\s*?[([]*?\s*?select\s+ 4 | union\s*?[(!@]*?\s*?[([]*?\s*?select\s+ 5 | \w+\s+like\s+[\"'`] 6 | like\s*?[\"'`]\% 7 | [\"'`]\s*?like\W*?[\"'`\d] 8 | [\"'`]\s*?and\s+[\s\w]+=\s*?\w+\s*?having\s+ 9 | [\"'`]\s*?nand\s+[\s\w]+=\s*?\w+\s*?having\s+ 10 | [\"'`]\s*?or\s+[\s\w]+=\s*?\w+\s*?having\s+ 11 | [\"'`]\s*?xor\s+[\s\w]+=\s*?\w+\s*?having\s+ 12 | [\"'`]\s*?xxor\s+[\s\w]+=\s*?\w+\s*?having\s+ 13 | [\"'`]\s*?div\s+[\s\w]+=\s*?\w+\s*?having\s+ 14 | [\"'`]\s*?like\s+[\s\w]+=\s*?\w+\s*?having\s+ 15 | [\"'`]\s*?between\s+[\s\w]+=\s*?\w+\s*?having\s+ 16 | [\"'`]\s*?not\s+[\s\w]+=\s*?\w+\s*?having\s+ 17 | [\"'`]\s*?\|\|\s+[\s\w]+=\s*?\w+\s*?having\s+ 18 | [\"'`]\s*?\&\&\s+[\s\w]+=\s*?\w+\s*?having\s+ 19 | [\"'`]\s*?\*\s*?\w+\W+[\"'`] 20 | [\"'`]\s*?[^?\w\s=.,;)(]++\s*?[(@\"'`]*?\s*?\w+\W+\w 21 | select\s+?[\[\]()\s\w\.,\"'`-]+from\s+ 22 | find_in_set\s*?\( 23 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942280.data: -------------------------------------------------------------------------------- 1 | select\s*?pg_sleep 2 | waitfor\s*?delay\s?[\"'`]+\s?\d 3 | ;\s*?shutdown\s*?; 4 | ;\s*?shutdown\s*?-- 5 | ;\s*?shutdown\s*?# 6 | ;\s*?shutdown\s*?\/\* 7 | ;\s*?shutdown\s*?{ 8 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942300.data: -------------------------------------------------------------------------------- 1 | \)\s*?when\s*?\d+\s*?then 2 | [\"'`]\s*?# 3 | [\"'`]\s*?-- 4 | [\"'`]\s*?{ 5 | \/\*!\s?\d+ 6 | char\s*?\(\s*?\d 7 | chr\s*?\(\s*?\d 8 | and\s+\s*?\w+\( 9 | nand\s+\s*?\w+\( 10 | or\s+\s*?\w+\( 11 | xor\s+\s*?\w+\( 12 | xxor\s+\s*?\w+\( 13 | div\s+\s*?\w+\( 14 | like\s+\s*?\w+\( 15 | between\s+\s*?\w+\( 16 | not\s+\s*?\w+\( 17 | \|\|\s+\s*?\w+\( 18 | \&\&\s+\s*?\w+\( 19 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942310.data: -------------------------------------------------------------------------------- 1 | [\"'`]\s+and\s*?=\W 2 | \(\s*?select\s*?\w+\s*?\( 3 | \*\/from 4 | \+\s*?\d+\s*?\+\s*?@ 5 | \w[\"'`]\s*?(?:[-+=|@]+\s+?)+[\d(] 6 | \w[\"'`]\s*?[-+=|@]+[\d(] 7 | coalesce\s*?\( 8 | @@\w+\s*?[^\w\s] 9 | \W!+[\"'`]\w 10 | [\"'`];\s*?if 11 | [\"'`];\s*?while 12 | [\"'`];\s*?begin 13 | [\"'`][\s\d]+=\s*?\d 14 | order\s+by\s+if\w*?\s*?\( 15 | [\s(]+case\d*?\W.+[tw]hen[\s(] 16 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942320.data: -------------------------------------------------------------------------------- 1 | create\s+function\s*?\w+\s*?\(\s*?\)\s*?- 2 | create\s+procedure\s*?\w+\s*?\(\s*?\)\s*?- 3 | declare[^\w]+[@#]\s*?\w+ 4 | exec\s*?\(\s*?@ 5 | procedure\s+analyse\s*?\( 6 | ;\s*?declare\s+[\w-]+ 7 | ;\s*?open\s+[\w-]+ 8 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942330.data: -------------------------------------------------------------------------------- 1 | [\"'`]\s*?or\s*?[\"'`]?\d 2 | [\"'`]\s*?xor\s*?[\"'`]?\d 3 | [\"'`]\s*?div\s*?[\"'`]?\d 4 | [\"'`]\s*?like\s*?[\"'`]?\d 5 | [\"'`]\s*?between\s*?[\"'`]?\d 6 | [\"'`]\s*?and\s*?[\"'`]?\d 7 | \\\\x(?:23|27|3d) 8 | ^.?[\"'`]$ 9 | ^[\"'`\\\\]*?[\d\"'`]+\s*?and\s*?[\w\"'`][+&!@(),.-] 10 | ^[\"'`\\\\]*?[\d\"'`]+\s*?nand\s*?[\w\"'`][+&!@(),.-] 11 | ^[\"'`\\\\]*?[\d\"'`]+\s*?or\s*?[\w\"'`][+&!@(),.-] 12 | ^[\"'`\\\\]*?[\d\"'`]+\s*?xor\s*?[\w\"'`][+&!@(),.-] 13 | ^[\"'`\\\\]*?[\d\"'`]+\s*?xxor\s*?[\w\"'`][+&!@(),.-] 14 | ^[\"'`\\\\]*?[\d\"'`]+\s*?div\s*?[\w\"'`][+&!@(),.-] 15 | ^[\"'`\\\\]*?[\d\"'`]+\s*?like\s*?[\w\"'`][+&!@(),.-] 16 | ^[\"'`\\\\]*?[\d\"'`]+\s*?between\s*?[\w\"'`][+&!@(),.-] 17 | ^[\"'`\\\\]*?[\d\"'`]+\s*?not\s*?[\w\"'`][+&!@(),.-] 18 | ^[\"'`\\\\]*?[\d\"'`]+\s*?\|\|\s*?[\w\"'`][+&!@(),.-] 19 | ^[\"'`\\\\]*?[\d\"'`]+\s*?\&\&\s*?[\w\"'`][+&!@(),.-] 20 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?and\s*?[\w\"'`][+&!@(),.-] 21 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?nand\s*?[\w\"'`][+&!@(),.-] 22 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?or\s*?[\w\"'`][+&!@(),.-] 23 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?xor\s*?[\w\"'`][+&!@(),.-] 24 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?xxor\s*?[\w\"'`][+&!@(),.-] 25 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?div\s*?[\w\"'`][+&!@(),.-] 26 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?like\s*?[\w\"'`][+&!@(),.-] 27 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?between\s*?[\w\"'`][+&!@(),.-] 28 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?not\s*?[\w\"'`][+&!@(),.-] 29 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?\|\|\s*?[\w\"'`][+&!@(),.-] 30 | ^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?\&\&\s*?[\w\"'`][+&!@(),.-] 31 | [^\w\s]\w+\s*?[|-]\s*?[\"'`]\s*?\w 32 | @\w+\s+and\s*?[\"'`\d]+ 33 | @\w+\s+or\s*?[\"'`\d]+ 34 | @\w+\s+xor\s*?[\"'`\d]+ 35 | @\w+\s+div\s*?[\"'`\d]+ 36 | @\w+\s+like\s*?[\"'`\d]+ 37 | @\w+\s+between\s*?[\"'`\d]+ 38 | @[\w-]+\sand\s*?[^\w\s] 39 | @[\w-]+\sor\s*?[^\w\s] 40 | @[\w-]+\sxor\s*?[^\w\s] 41 | @[\w-]+\sdiv\s*?[^\w\s] 42 | @[\w-]+\slike\s*?[^\w\s] 43 | @[\w-]+\sbetween\s*?[^\w\s] 44 | [^\w\s:]\s*?\d\W+[^\w\s]\s*?[\"'`]. 45 | \Winformation_schema 46 | table_name\W 47 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942340.data: -------------------------------------------------------------------------------- 1 | in\s*?[(]+\s*?select 2 | (?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+regexp\s*?\( 3 | (?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+sounds\s+like\s*?[\"'`] 4 | (?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+[=\d]+x 5 | [\"'`]\s*?\d\s*?-- 6 | [\"'`]\s*?\d\s*?# 7 | [\"'`][\%&<>^=]+\d\s*?= 8 | [\"'`][\%&<>^=]+\d\s*?or 9 | [\"'`][\%&<>^=]+\d\s*?xor 10 | [\"'`][\%&<>^=]+\d\s*?div 11 | [\"'`][\%&<>^=]+\d\s*?like 12 | [\"'`][\%&<>^=]+\d\s*?between 13 | [\"'`][\%&<>^=]+\d\s*?and 14 | [\"'`]\W+[\w+-]+\s*?=\s*?\d\W+[\"'`] 15 | [\"'`]\s*?is\s*?\d.+[\"'`]?\w 16 | [\"'`][|]?[\w-]{3,}[^\w\s.,]+[\"'`] 17 | [\"'`]\s*?is\s*?[\d.]+\s*?\W.*?[\"'`] 18 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942350.data: -------------------------------------------------------------------------------- 1 | create\s+function\s+.+\s+returns 2 | ;\s*?alter\b\s*?[\[(]?\w{2,} 3 | ;\s*?create\b\s*?[\[(]?\w{2,} 4 | ;\s*?delete\b\s*?[\[(]?\w{2,} 5 | ;\s*?desc\b\s*?[\[(]?\w{2,} 6 | ;\s*?insert\b\s*?[\[(]?\w{2,} 7 | ;\s*?load\b\s*?[\[(]?\w{2,} 8 | ;\s*?rename\b\s*?[\[(]?\w{2,} 9 | ;\s*?select\b\s*?[\[(]?\w{2,} 10 | ;\s*?truncate\b\s*?[\[(]?\w{2,} 11 | ;\s*?update\b\s*?[\[(]?\w{2,} 12 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942370.data: -------------------------------------------------------------------------------- 1 | [\"'`]\s*?\*.+or\W*?[\"'`]\d 2 | [\"'`]\s*?\*.+xor\W*?[\"'`]\d 3 | [\"'`]\s*?\*.+div\W*?[\"'`]\d 4 | [\"'`]\s*?\*.+like\W*?[\"'`]\d 5 | [\"'`]\s*?\*.+between\W*?[\"'`]\d 6 | [\"'`]\s*?\*.+and\W*?[\"'`]\d 7 | [\"'`]\s*?\*.+id\W*?[\"'`]\d 8 | \^[\"'`] 9 | [\"'`]\s*?[^\w\s?]+\s*?[^\w\s]+\s*?[\"'`] 10 | [\"'`]\s*?[^\w\s]+\s*?[\W\d].*?# 11 | [\"'`]\s*?[^\w\s]+\s*?[\W\d].*?-- 12 | [\"'`].*?\*\s*?\d 13 | [\"'`]\s*?or\s[^\d]+[\w-]+.*?\d 14 | [\"'`]\s*?xor\s[^\d]+[\w-]+.*?\d 15 | [\"'`]\s*?div\s[^\d]+[\w-]+.*?\d 16 | [\"'`]\s*?like\s[^\d]+[\w-]+.*?\d 17 | [\"'`]\s*?between\s[^\d]+[\w-]+.*?\d 18 | [\"'`]\s*?and\s[^\d]+[\w-]+.*?\d 19 | [()\*<>%+-][\w-]+[^\w\s]+[\"'`][^,] 20 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942380.data: -------------------------------------------------------------------------------- 1 | \b(?i:having)\b\s+\d{1,10}\s*?[=<>] 2 | \b(?i:having)\b\s+'[^=]{1,10}'\s*?[=<>] 3 | (?i:\bexecute\() 4 | (?i:\bexecute\s{1,5}[\w\.$]{1,5}\s{0,3}) 5 | \bhaving\b ?\d{1,10} ?[=<>]+ 6 | \bhaving\b ?[\'\"][^=]{1,10}[\'\" ?[=<>]+ 7 | (?i:\bcreate\s+?table.{0,20}?\() 8 | (?i:\blike\W*?char\W*?\() 9 | (?i:select.*?case) 10 | (?i:from.*?limit) 11 | (?i:order\sby) 12 | exists\s\sselect 13 | exists\sselect\Sif\s\( 14 | exists\sselect\Sifnull\s\( 15 | exists\sselect\Stop 16 | exists\sselect\Sconcat 17 | exists\ssystem\s\( 18 | exists\s\b(?i:having)\b\s+\d{1,10} 19 | exists\s'[^=]{1,10}' 20 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942390.data: -------------------------------------------------------------------------------- 1 | (?i:\bor\b ?\d{1,10} ?[=<>]+) 2 | (?i:\bor\b ?[\'\"][^=]{1,10}[\'\"] ?[=<>]+) 3 | (?i:'\s+or\s+.{1,20}[+\-!<>=]) 4 | (?i:'\s+xor\s+.{1,20}[+\-!<>=]) 5 | \b(?i:or)\b\s+\d{1,10} 6 | \b(?i:or)\b\s+'[^=]{1,10}' 7 | \b(?i:xor)\b\s+\d{1,10} 8 | \b(?i:xor)\b\s+'[^=]{1,10}' 9 | \b(?i:or)\b\s+\d{1,10}\s*?[=<>] 10 | \b(?i:xor)\b\s+\d{1,10}\s*?[=<>] 11 | \b(?i:or)\b\s+'[^=]{1,10}'\s*?[=<>] 12 | \b(?i:xor)\b\s+'[^=]{1,10}'\s*?[=<>] 13 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942400.data: -------------------------------------------------------------------------------- 1 | \band\b\s+\d{1,10}\s*?[=<>] 2 | \band\b\s+'[^=]{1,10}'\s*?[=<>] 3 | \band\b\s+\d{1,10} 4 | \band\b\s+'[^=]{1,10}' 5 | \band\b ?\d{1,10} ?[=<>]+ 6 | \band\b ?[\'\"][^=]{1,10}[\'\"] ?[=<>]+ 7 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942470.data: -------------------------------------------------------------------------------- 1 | autonomous_transaction 2 | dba_users 3 | dbms_java 4 | nvarchar 5 | openowa_util 6 | openquery 7 | openrowset 8 | sp_addextendedproc 9 | sp_execute 10 | sp_executesql 11 | sp_help 12 | sp_is_srvrolemember 13 | sp_makewebtask 14 | sp_oacreate 15 | sp_password 16 | sp_prepare 17 | sp_replwritetovarbin 18 | sp_sqlexec 19 | sql_longvarchar 20 | sql_variant 21 | tbcreator 22 | utl_file 23 | utl_http 24 | varchar 25 | xp_availablemedia 26 | xp_cmdshell 27 | xp_dirtree 28 | xp_enumdsn 29 | xp_execresultset 30 | xp_filelist 31 | xp_loginconfig 32 | xp_makecab 33 | xp_ntsec 34 | xp_ntsec_enumdomains 35 | xp_regaddmultistring 36 | xp_regdeletekey 37 | xp_regdeletevalue 38 | xp_regenumkeys 39 | xp_regenumvalues 40 | xp_regread 41 | xp_regremovemultistring 42 | xp_regwrite 43 | xp_servicecontrol 44 | xp_terminate 45 | xp_terminate_process 46 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-942480.data: -------------------------------------------------------------------------------- 1 | \bdbms_\w+\.\b 2 | \bdelete\b\W*?\bfrom\b 3 | \bgroup\b.*?\bby\b.{1,100}?\bhaving\b 4 | \binner\b\W*?\bjoin\b 5 | \binsert\b\W*?\binto\b 6 | \binto\b\W*?\bdumpfile\b 7 | \binto\b\W*?\boutfile\b 8 | \bload\b\W*?\bdata\b.*?\binfile\b 9 | \bprint\b\W*?\@\@ 10 | \bselect\b.{1,100}?\b.*?\bdump\b.*\bfrom\b 11 | \bselect\b.{1,100}?\bcount\b.{1,100}?\bfrom\b 12 | \bselect\b.{1,100}?\bdata_type\b 13 | \bselect\b.{1,100}?\bfrom\b.{1,100}?\bwhere\b 14 | \bselect\b.{1,100}?\binstr\b 15 | \bselect\b.{1,100}?\blength\b.{1,100}?\bfrom\b 16 | \bselect\b.{1,100}?\bto_char\b 17 | \bselect\b.{1,100}?\bto_number\b 18 | \bselect\b.{1,100}?\btop\b.{1,100}?\bfrom\b 19 | \bsys_context\b 20 | \bunion\b.{1,100}?\bselect\b 21 | \butl_inaddr\b 22 | collation\W*?\(a\b 23 | 'dbo' 24 | 'msdasql' 25 | 'sa' 26 | 'sqloledb' 27 | \@\@version\b 28 | ;\W*?\bdrop\b 29 | ;\W*?\bshutdown\b 30 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-assemble-v2.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # Create one regexp from a set of regexps. 4 | # Regexps can be submitted via standard input, one per line. 5 | # 6 | # Requires Regexp::Assemble Perl module. 7 | # To install: cpan install Regexp::Assemble 8 | # 9 | # See: https://coreruleset.org/20190826/optimizing-regular-expressions/ 10 | # 11 | 12 | use strict; 13 | use Regexp::Assemble; 14 | 15 | my $ra = Regexp::Assemble->new; 16 | while (<>) 17 | { 18 | # Handle possessive qualifiers 19 | # https://rt.cpan.org/Public/Bug/Display.html?id=50228#txn-672717 20 | my $arr = $ra->lexstr($_); 21 | for (my $n = 0; $n < $#$arr - 1; ++$n) 22 | { 23 | if ($arr->[$n] =~ /\+$/ and $arr->[$n + 1] eq '+') { 24 | $arr->[$n] .= splice(@$arr, $n + 1, 1); 25 | } 26 | } 27 | $ra->insert(@$arr); 28 | } 29 | print $ra->as_string() . "\n"; 30 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-assemble.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # Create one regexp from a set of regexps. 4 | # Regexps can be submitted via standard input, one per line. 5 | # 6 | # Requires Regexp::Assemble Perl module. 7 | # To install: cpan install Regexp::Assemble 8 | # 9 | # See: https://coreruleset.org/20190826/optimizing-regular-expressions/ 10 | # 11 | 12 | use strict; 13 | use Regexp::Assemble; 14 | 15 | my $ra = Regexp::Assemble->new; 16 | while (<>) 17 | { 18 | $ra->add($_); 19 | } 20 | print $ra->as_string() . "\n"; 21 | -------------------------------------------------------------------------------- /util/regexp-assemble/regexp-cmdline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Convert a word list to a list of regexps usable by Regexp::Assemble. 4 | # 5 | # Examples: 6 | # cat regexp-932100.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl 7 | # cat regexp-932110.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl 8 | # cat regexp-932150.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl 9 | # 10 | # Refer to rule 932100, 932110, 932150 for documentation. 11 | # 12 | 13 | import fileinput, string, sys 14 | 15 | # Convert a single line to regexp format, and insert anti-cmdline 16 | # evasions between characters. 17 | def regexp_str(str, evasion): 18 | # By convention, if the line starts with ' char, copy the rest 19 | # verbatim. 20 | if str[0] == "'": 21 | return str[1:] 22 | 23 | result = '' 24 | for i, char in enumerate(str): 25 | if i > 0: 26 | result += evasion 27 | result += regexp_char(char, evasion) 28 | 29 | return result 30 | 31 | # Ensure that some special characters are escaped 32 | def regexp_char(char, evasion): 33 | char = str.replace(char, '.', '\.') 34 | char = str.replace(char, '-', '\-') 35 | char = str.replace(char, '+', r'''(?:\s|<|>).*''') 36 | # Unix: "cat foo", "catfoo" 37 | char = str.replace(char, '@', r'''(?:[\s,;]|\.|/|<|>).*''') 38 | # Windows: "more foo", "more,foo", "more;foo", "more.com", "more/e", 39 | # "morefoo" 40 | char = str.replace(char, ' ', '\s+') 41 | # Ensure multiple spaces are matched 42 | return char 43 | 44 | # Insert these sequences between characters to prevent evasion. 45 | # This emulates the relevant parts of t:cmdLine. 46 | evasions = { 47 | 'unix': r'''[\\\\'\"]*''', 48 | 'windows': r'''[\"\^]*''', 49 | } 50 | 51 | # Parse arguments 52 | if len(sys.argv) <= 1 or not sys.argv[1] in evasions: 53 | print(sys.argv[0] + ' unix|windows [infile]') 54 | sys.exit(1) 55 | 56 | evasion = evasions[sys.argv[1]] 57 | del sys.argv[1] 58 | 59 | # Process lines from input file, or if not specified, standard input 60 | for line in fileinput.input(): 61 | line = line.rstrip('\n ') 62 | line = line.split('#')[0] 63 | if line != '': 64 | print(regexp_str(line, evasion)) 65 | -------------------------------------------------------------------------------- /util/regression-tests/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920181.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | meta: 3 | author: "fgsch" 4 | enabled: true 5 | name: "920181.yaml" 6 | description: "Description" 7 | tests: 8 | - 9 | test_title: 920181-1 10 | stages: 11 | - 12 | stage: 13 | input: 14 | dest_addr: "127.0.0.1" 15 | port: 80 16 | method: "POST" 17 | uri: "/" 18 | headers: 19 | Host: "localhost" 20 | Accept: "*/*" 21 | Content-Length: 7 22 | Content-Type: "application/x-www-form-urlencoded" 23 | Transfer-Encoding: "chunked" 24 | User-Agent: "ModSecurity CRS 3 Tests" 25 | data: 26 | - "7" 27 | - "foo=bar" 28 | - "0" 29 | - "" 30 | - "" 31 | stop_magic: true 32 | output: 33 | # Apache unsets the Content-Length header if 34 | # Transfer-Encoding is found! 35 | no_log_contains: id "920181" 36 | --------------------------------------------------------------------------------