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/restricted-upload.data:
--------------------------------------------------------------------------------
1 | # Apache webserver
2 | .htaccess
3 | .htdigest
4 | .htpasswd
5 | # WordPress configuration file
6 | wp-config.php
7 | # Symfony configuration files
8 | config.yml
9 | config_dev.yml
10 | config_prod.yml
11 | config_test.yml
12 | parameters.yml
13 | routing.yml
14 | security.yml
15 | services.yml
16 | # Drupal configuration files
17 | default.settings.php
18 | settings.php
19 | settings.local.php
20 | # Magento configuration files
21 | local.xml
22 | # dotenv configuration file
23 | .env
24 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941320.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian S.J. Peron"
4 | description: None
5 | enabled: true
6 | name: 941320.yaml
7 | tests:
8 | -
9 | test_title: 941320-1
10 | desc: "XSS Attack - HTML Tag Handler"
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=document.cookie="sessionid=1234;%20domain=.example.dom";
30 | version: HTTP/1.1
31 | output:
32 | log_contains: id "943100"
33 |
--------------------------------------------------------------------------------
/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-942-APPLICATION-ATTACK-SQLI/942350.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian S.J. Peron, Franziska Bühler"
4 | description: None
5 | enabled: true
6 | name: 942350.yaml
7 | tests:
8 | -
9 | test_title: 942350-1
10 | desc: "MySQL UDF injection and other data/structure manipulation"
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 | # ; insert INTO table (word) VALUES('dfsd')
21 | uri: "/?var=%3bINSERT%20INTO%20table%20%28col%29%20VALUES"
22 | version: HTTP/1.0
23 | output:
24 | log_contains: id "942350"
25 | -
26 | test_title: 942350-2
27 | desc: "Fix for FP reported in GitHub issue 1587"
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | headers:
34 | Host: localhost
35 | method: GET
36 | port: 80
37 | # ;insertion_424242
38 | uri: "/?var=%3Binsertion_424242"
39 | version: HTTP/1.0
40 | output:
41 | no_log_contains: id "942350"
42 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941150.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "zmallen"
4 | enabled: true
5 | name: "941150.yaml"
6 | description: "Tests to trigger, or not trigger 941150"
7 | tests:
8 | -
9 | test_title: 941150-1
10 | desc: Disallowed HTML entities, ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: '941150-1%3D%3Ca%20href%3D%22test%22'
23 | output:
24 | log_contains: id "941150"
25 | -
26 | test_title: 941150-2
27 | desc: Disallowed HTML entities, ARGS
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: POST
34 | port: 80
35 | uri: '/'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: "payload=XSS"
40 | output:
41 | log_contains: id "941150"
42 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942480.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Jose Nazario"
4 | description: None
5 | enabled: true
6 | name: 942480.yaml
7 | tests:
8 | -
9 | test_title: 942480-1
10 | desc: "SQL Injection Attack"
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: "127.0.0.1"
16 | headers:
17 | Host: "localhost"
18 | Cache-Control: "no-cache, no-store, must-revalidate"
19 | method: GET
20 | port: 80
21 | # variable name boundary attacks
22 | uri: "/?'msdasql'"
23 | version: HTTP/1.0
24 | output:
25 | log_contains: "id \"942480"
26 | -
27 | test_title: 942480-2
28 | desc: "SQL Injection Attack"
29 | stages:
30 | -
31 | stage:
32 | input:
33 | dest_addr: "127.0.0.1"
34 | headers:
35 | Host: "localhost"
36 | Cache-Control: "no-cache, no-store, must-revalidate"
37 | # variable name boundary attacks
38 | Cookie: "'msdasql'"
39 | method: POST
40 | port: 80
41 | version: HTTP/1.0
42 | output:
43 | log_contains: "id \"942480"
44 |
45 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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-941-APPLICATION-ATTACK-XSS/941280.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian S.J. Peron"
4 | description: None
5 | enabled: true
6 | name: 941280.yaml
7 | tests:
8 | -
9 | test_title: 941280-1
10 | desc: "IE XSS Filters"
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 | uri: "/?var=%3cBASE%20dsfds%20HREF%20%2f%20%3d"
21 | version: HTTP/1.0
22 | output:
23 | log_contains: id "941280"
24 | -
25 | test_title: 941280-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 | Content-Length: 113
35 | User-Agent: ModSecurity CRS 3 Tests
36 | Content-Type: application/x-www-form-urlencoded
37 | method: POST
38 | port: 80
39 | uri: "/"
40 | version: HTTP/1.0
41 | data: 'payload=xss> /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-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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920280.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "920280.yaml"
6 | description: "Description"
7 | tests:
8 | -
9 | test_title: 920280-1
10 | stages:
11 | -
12 | stage:
13 | input:
14 | dest_addr: "127.0.0.1"
15 | port: 80
16 | version: "HTTP/1.0"
17 | headers:
18 | User-Agent: "ModSecurity CRS 3 Tests"
19 | output:
20 | log_contains: "id \"920280\""
21 | -
22 | test_title: 920280-2
23 | stages:
24 | -
25 | stage:
26 | input:
27 | dest_addr: "127.0.0.1"
28 | port: 80
29 | headers:
30 | User-Agent: "ModSecurity CRS 3 Tests"
31 | Host: "localhost"
32 | output:
33 | no_log_contains: "id \"920280\""
34 | -
35 | test_title: 920280-3
36 | stages:
37 | -
38 | stage:
39 | input:
40 | dest_addr: "127.0.0.1"
41 | port: 80
42 | version: "HTTP/0.9"
43 | headers:
44 | User-Agent: "ModSecurity CRS 3 Tests"
45 | output:
46 | # Technically valid but Apache doesn't allow 0.9 anymore
47 | status: 400
48 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920311.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "920311.yaml"
6 | description: "Description"
7 | tests:
8 | -
9 | test_title: 920311-1
10 | stages:
11 | -
12 | stage:
13 | input:
14 | dest_addr: "127.0.0.1"
15 | port: 80
16 | headers:
17 | Host: "localhost"
18 | Accept: ""
19 | output:
20 | log_contains: "id \"920311\""
21 | -
22 | test_title: 920311-2
23 | stages:
24 | -
25 | stage:
26 | input:
27 | dest_addr: "127.0.0.1"
28 | port: 80
29 | method: "OPTIONS"
30 | headers:
31 | Host: "localhost"
32 | Accept: ""
33 | output:
34 | no_log_contains: "id \"920311\""
35 | -
36 | test_title: 920311-3
37 | stages:
38 | -
39 | stage:
40 | input:
41 | dest_addr: "127.0.0.1"
42 | port: 80
43 | headers:
44 | User-Agent: "ModSecurity CRS 3 Tests Enterprise"
45 | Host: "localhost"
46 | Accept: "text/plain, text/html"
47 | output:
48 | no_log_contains: "id \"920311\""
49 |
50 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941170.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "941170.yaml"
6 | description: "Tests to trigger, or not trigger 941170"
7 | tests:
8 | -
9 | test_title: 941170-1
10 | desc: XSS in XML Test as described in http://www.client9.com/article/five-interesting-injection-attacks/
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/char_test?mime=text/xml&body=%3Cx:script%20xmlns:x=%22http://www.w3.org/1999/xhtml%22%20src=%22data:,alert(1)%22%20/%3E'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | output:
23 | log_contains: id "941170"
24 | -
25 | test_title: 941170-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 | method: POST
33 | port: 80
34 | headers:
35 | User-Agent: ModSecurity CRS 3 Tests
36 | Host: localhost
37 | uri: '/'
38 | data: "payload=javascript:/*-->"
39 | output:
40 | log_contains: id "941170"
41 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-933-APPLICATION-ATTACK-PHP/933131.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: csanders-git
4 | description: Tests functionality of stricter sibling 933131
5 | enabled: true
6 | name: 933131.yaml
7 | tests:
8 | -
9 | test_title: 933131-1
10 | desc: SERVER request URLEncoded
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: /?x=$_%53ERVER['test'];
20 | output:
21 | no_log_contains: id "933131"
22 | -
23 | test_title: 933131-2
24 | desc: SERVER request URLEncoded
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: /?%24_COOKIE=value;
34 | output:
35 | no_log_contains: id "933131"
36 | -
37 | test_title: 933131-3
38 | desc: SERVER index listed with obfuscated SERVER
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: /?x=$_%53%20ERVER['REQUEST_URI'];
48 | output:
49 | log_contains: id "933131"
50 |
--------------------------------------------------------------------------------
/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/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/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/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920370.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: csanders-git
4 | description: None
5 | # PCRE limits need to be set higher to process this
6 | enabled: false
7 | name: 920370.yaml
8 | tests:
9 | -
10 | test_title: 920370-1
11 | desc: Argument value too long (920370) from old modsec 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/5.0 (Windows; U; Windows NT 5.1; en-US; rv
26 | method: GET
27 | port: 80
28 | uri: /?foo=11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
29 | version: HTTP/1.0
30 | output:
31 | log_contains: id "920370"
32 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920290.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "920290.yaml"
6 | description: "Description"
7 | tests:
8 | -
9 | # Apache will block this with a 400 and it will
10 | # never get to CRS. We will fix this more when
11 | # FTW supports the OR operator for outputs.
12 | test_title: 920290-1
13 | stages:
14 | -
15 | stage:
16 | input:
17 | dest_addr: "127.0.0.1"
18 | port: 80
19 | headers:
20 | User-Agent: "ModSecurity CRS 3 Tests"
21 | Host: ""
22 | output:
23 | status: [403, 400]
24 | #log_contains: "id \"920290\""
25 | #-
26 | #test_title: 920290-2
27 | #stages:
28 | # -
29 | # stage:
30 | # input:
31 | # dest_addr: "127.0.0.1"
32 | # port: 80
33 | # headers:
34 | # User-Agent: "ModSecurity CRS 3 Tests"
35 | # Host: "%00"
36 | # output:
37 | # no_log_contains: "id \"920290\""
38 | # -
39 | # test_title: 920290-3
40 | # stages:
41 | # -
42 | # stage:
43 | # input:
44 | # dest_addr: "127.0.0.1"
45 | # port: 80
46 | # headers:
47 | # User-Agent: "ModSecurity CRS 3 Tests"
48 | # Host: "localhost"
49 | # output:
50 | # no_log_contains: "id \"920290\""
51 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920350.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "920350.yaml"
6 | description: "Description"
7 | tests:
8 | -
9 | test_title: 920350-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: "127.0.0.1"
20 | protocol: "http"
21 | uri: "/"
22 | output:
23 | log_contains: "id \"920350\""
24 | -
25 | test_title: 920350-2
26 | stages:
27 | -
28 | stage:
29 | input:
30 | dest_addr: "localhost"
31 | method: "GET"
32 | port: 80
33 | headers:
34 | User-Agent: "ModSecurity CRS 3 Tests"
35 | Host: "localhost"
36 | protocol: "http"
37 | uri: "/"
38 | output:
39 | no_log_contains: "id \"920350\""
40 | -
41 | test_title: 920350-3
42 | stages:
43 | -
44 | stage:
45 | input:
46 | dest_addr: "localhost"
47 | method: "GET"
48 | port: 80
49 | headers:
50 | User-Agent: "ModSecurity CRS 3 Tests"
51 | Host: "1.2.3.4"
52 | protocol: "http"
53 | uri: "/"
54 | output:
55 | log_contains: "id \"920350\""
56 |
--------------------------------------------------------------------------------
/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-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/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/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920500.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Andrea Menin"
4 | enabled: true
5 | name: "920500.yaml"
6 | description: "Tests for backup or working file extensions"
7 | tests:
8 | - test_title: 920500-1
9 | desc: "Check request filename ends with ~"
10 | stages:
11 | - stage:
12 | input:
13 | dest_addr: "127.0.0.1"
14 | port: 80
15 | method: "GET"
16 | uri: "/index.php~"
17 | headers:
18 | User-Agent: "ModSecurity CRS 3 Tests"
19 | Host: "localhost"
20 | output:
21 | log_contains: "id \"920500\""
22 | - test_title: 920500-2
23 | desc: "Check request filename contains file that ends with ~ but not at end of string (bypass)"
24 | stages:
25 | - stage:
26 | input:
27 | dest_addr: "127.0.0.1"
28 | port: 80
29 | method: "GET"
30 | uri: "/index.php~/foo/bar/"
31 | headers:
32 | User-Agent: "ModSecurity CRS 3 Tests"
33 | Host: "localhost"
34 | output:
35 | log_contains: "id \"920500\""
36 | - test_title: 920500-3
37 | desc: "Rules 920500 should not block user dir such as /~user/"
38 | stages:
39 | - stage:
40 | input:
41 | dest_addr: "127.0.0.1"
42 | port: 80
43 | method: "GET"
44 | uri: "/~user/"
45 | headers:
46 | User-Agent: "ModSecurity CRS 3 Tests"
47 | Host: "localhost"
48 | output:
49 | no_log_contains: "id \"920500\""
50 |
--------------------------------------------------------------------------------
/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-941-APPLICATION-ATTACK-XSS/941180.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "zmallen"
4 | enabled: true
5 | name: "941180.yaml"
6 | description: "Tests to trigger, or not trigger 941180"
7 | tests:
8 | -
9 | test_title: 941180-1
10 | desc: Node-validator blacklist keywords, ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: '941180-1=window.location'
23 | output:
24 | log_contains: id "941180"
25 | -
26 | test_title: 941180-2
27 | desc: Node-validator blacklist keywords, ARGS_NAMES
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: GET
34 | port: 80
35 | uri: '/bar'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: 'document.cookie=941180-2'
40 | output:
41 | log_contains: id "941180"
42 | -
43 | test_title: 941180-3
44 | desc: Node-validator blacklist keywords, ARGS_NAMES
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | method: GET
51 | port: 80
52 | uri: '/baz'
53 | headers:
54 | User-Agent: ModSecurity CRS 3 Tests
55 | Host: localhost
56 | Cookie: 'window.location=941180-3'
57 | output:
58 | log_contains: id "941180"
59 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941200.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "zmallen"
4 | enabled: true
5 | name: "941200.yaml"
6 | description: "Tests to trigger, or not trigger 941200"
7 | tests:
8 | -
9 | test_title: 941200-1
10 | desc: Microsoft vmlframe xss, ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: '941200-1=%3Cv%3Avmlframe%20src%3D%22foo.com%2Fsup.fml%22%2F%3E'
23 | output:
24 | log_contains: id "941200"
25 | -
26 | test_title: 941200-2
27 | desc: Microsoft vmlframe xss, ARGS_NAMES
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: GET
34 | port: 80
35 | uri: '/bar'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: '%3Cv%3Avmlframe%20src%3D%22foo.com%2Fsup.fml%22%2F%3E=941200-2'
40 | output:
41 | log_contains: id "941200"
42 | -
43 | test_title: 941200-3
44 | desc: Microsoft vmlframe xss, REQUEST_COOKIE_NAMES
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | method: GET
51 | port: 80
52 | uri: '/baz'
53 | headers:
54 | User-Agent: ModSecurity CRS 3 Tests
55 | Host: localhost
56 | Cookie: '%3Cv%3Avmlframe%20src%3D%22foo.com%2Fsup.fml%22%2F%3E=941200-3'
57 | output:
58 | log_contains: id "941200"
59 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941210.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "zmallen"
4 | enabled: true
5 | name: "941210.yaml"
6 | description: "Tests to trigger, or not trigger 941210. This checks for abuses of javascript: with different encodings/html etc"
7 | tests:
8 | -
9 | test_title: 941210-1
10 | desc: Obsfucated javascript tag in GET data, ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: '941210-1=ja%26tab%3Bvascript%3A%20'
23 | output:
24 | log_contains: id "941210"
25 | -
26 | test_title: 941210-2
27 | desc: Obfuscated javascript tag in ARGS_NAMES, with tab
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: GET
34 | port: 80
35 | uri: '/bar'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: 'ja%26tab%3Bvascript%3A%09=941210-2'
40 | output:
41 | log_contains: id "941210"
42 | -
43 | test_title: 941210-3
44 | desc: Microsoft vmlframe xss, REQUEST_COOKIE_NAMES
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | method: GET
51 | port: 80
52 | uri: '/baz'
53 | headers:
54 | User-Agent: ModSecurity CRS 3 Tests
55 | Host: localhost
56 | Cookie: 'ja%26newline%3Bvascript%3A%20=941210-3'
57 | output:
58 | log_contains: id "941210"
59 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921120.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: csanders-git
4 | description: None
5 | enabled: true
6 | name: 921120.yaml
7 | tests:
8 | -
9 | test_title: 921120-1
10 | desc: HTTP response splitting (921120) 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%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2019%0d%0a%0d%0aShazam
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-941-APPLICATION-ATTACK-XSS/941190.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "941190.yaml"
6 | description: "Tests to trigger, or not trigger 941190"
7 | tests:
8 | -
9 | test_title: 941190-1
10 | desc: Node-validator blacklist keywords, ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: "941190-1="
23 | output:
24 | log_contains: id "941190"
25 | -
26 | test_title: 941190-2
27 | desc: Node-validator blacklist keywords, ARGS_NAMES
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: GET
34 | port: 80
35 | uri: '/bar'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: "x="
40 | output:
41 | log_contains: id "941190"
42 | -
43 | test_title: 941190-3
44 | desc: Node-validator blacklist keywords, COOKIES_NAMES
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | method: GET
51 | port: 80
52 | uri: '/baz'
53 | headers:
54 | User-Agent: ModSecurity CRS 3 Tests
55 | Host: localhost
56 | Cookie: ''
57 | output:
58 | log_contains: id "941190"
59 |
--------------------------------------------------------------------------------
/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/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-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-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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920490.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian Folini"
4 | enabled: true
5 | name: "920490.yaml"
6 | description: "Tests for the charset protection in combination with the x-up-devcap-post-charset header"
7 | tests:
8 | - test_title: 920490-1
9 | stages:
10 | - stage:
11 | input:
12 | dest_addr: "127.0.0.1"
13 | port: 80
14 | method: "POST"
15 | headers:
16 | User-Agent: "UP ModSecurity CRS 3 Tests"
17 | Host: "localhost"
18 | Content-Type: "application/x-www-form-urlencoded; charset=utf-8"
19 | x-up-devcap-post-charset: "ibm500"
20 | data: "%89%95%97%A4%A3%F1=%A7%A7%A7%A7%A7%A7%A7"
21 | output:
22 | log_contains: "id \"920490\""
23 | - test_title: 920490-2
24 | stages:
25 | - stage:
26 | input:
27 | dest_addr: "127.0.0.1"
28 | port: 80
29 | method: "POST"
30 | headers:
31 | User-Agent: "ModSecurity CRS 3 Tests"
32 | Host: "localhost"
33 | Content-Type: "application/x-www-form-urlencoded; charset=utf-8"
34 | x-up-devcap-post-charset: "ibm500"
35 | data: "%89%95%97%A4%A3%F1=%A7%A7%A7%A7%A7%A7%A7"
36 | output:
37 | no_log_contains: "id \"920490\""
38 | - test_title: 920490-3
39 | stages:
40 | - stage:
41 | input:
42 | dest_addr: "127.0.0.1"
43 | port: 80
44 | method: "POST"
45 | headers:
46 | User-Agent: "UP ModSecurity CRS 3 Tests"
47 | Host: "localhost"
48 | Content-Type: "application/x-www-form-urlencoded; charset=utf-8"
49 | data: "%89%95%97%A4%A3%F1=%A7%A7%A7%A7%A7%A7%A7"
50 | output:
51 | no_log_contains: "id \"920490\""
52 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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-941-APPLICATION-ATTACK-XSS/941310.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: Christian S.J. Peron, Federico G. Schwindt
4 | description: US-ASCII Malformed Encoding XSS Filter
5 | enabled: true
6 | name: 941310.yaml
7 | tests:
8 | -
9 | test_title: 941310-1
10 | desc: Positive test using single byte
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | headers:
17 | Host: localhost
18 | Content-type: us-ascii
19 | method: POST
20 | port: 80
21 | uri: /
22 | data: var=\xbcscript\xbealert(\xa2XSS\xa2)\xbc/script\xbe
23 | output:
24 | log_contains: id "941310"
25 | -
26 | test_title: 941310-2
27 | desc: Positive test using utf-8
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | headers:
34 | Host: localhost
35 | Content-type: us-ascii
36 | method: POST
37 | port: 80
38 | uri: /
39 | data: var=\xc2\xbcscript\xc2\xbealert(\xc2\xa2XSS\xc2\xa2)\xc2\xbc/script\xc2\xbe
40 | output:
41 | log_contains: id "941310"
42 | -
43 | test_title: 941310-3
44 | desc: Negative test for opening tag
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | headers:
51 | Host: localhost
52 | Content-type: us-ascii
53 | method: POST
54 | port: 80
55 | uri: /
56 | data: var=\xbc\xbc
57 | output:
58 | no_log_contains: id "941310"
59 | -
60 | test_title: 941310-4
61 | desc: Negative test for closing tag
62 | stages:
63 | -
64 | stage:
65 | input:
66 | dest_addr: 127.0.0.1
67 | headers:
68 | Host: localhost
69 | Content-type: us-ascii
70 | method: POST
71 | port: 80
72 | uri: /
73 | data: var=\xbe\xbe
74 | output:
75 | no_log_contains: id "941310"
76 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941140.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "zmallen"
4 | enabled: true
5 | name: "941140.yaml"
6 | description: "Tests to trigger, or not trigger 941130"
7 | tests:
8 | -
9 | test_title: 941140-1
10 | desc: XSS vectors making use of javascript uri and tags, e.g.,
, in ARGS
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | method: GET
17 | port: 80
18 | uri: '/foo'
19 | headers:
20 | User-Agent: ModSecurity CRS 3 Tests
21 | Host: localhost
22 | data: '9411400-1=%3Cp%20style%3D%22background%3Aurl(javascript%3Aalert(1))%22%3E'
23 | output:
24 | log_contains: id "941140"
25 | -
26 | test_title: 941140-2
27 | desc: XSS vectors making use of javascript uri and tags, e.g.,
, in ARGS_NAMES
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | method: GET
34 | port: 80
35 | uri: '/bar'
36 | headers:
37 | User-Agent: ModSecurity CRS 3 Tests
38 | Host: localhost
39 | data: '%3Cp%20style%3D%22background%3Aurl(javascript%3Aalert(1))%22%3E=941140-2'
40 | output:
41 | log_contains: id "941140"
42 | -
43 | test_title: 941140-3
44 | desc: XSS vectors making use of javascript uri and tags, e.g.,
, in COOKIE
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | method: GET
51 | port: 80
52 | uri: '/bar'
53 | headers:
54 | User-Agent: ModSecurity CRS 3 Tests
55 | Host: localhost
56 | Cookie: '%3Cp%20style%3D%22background%3Aurl(javascript%3Aalert(1))%22%3E=941140-2'
57 | output:
58 | log_contains: id "941140"
59 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942320.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian S.J. Peron, Christoph Hansen"
4 | description: None
5 | enabled: true
6 | name: 942320.yaml
7 | tests:
8 | -
9 | test_title: 942320-1
10 | desc: "Detects MySQL and PostgreSQL stored procedure/function injections"
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=procedure%20analyse%20%28"
21 | version: HTTP/1.0
22 | output:
23 | log_contains: id "942320"
24 | -
25 | test_title: 942320-2
26 | desc: "Detects MySQL and PostgreSQL stored procedure/function injections"
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 | uri: "/"
37 | data: "pay=exec+%28%40%0A"
38 | version: HTTP/1.0
39 | output:
40 | log_contains: id "942320"
41 | -
42 | test_title: 942320-3
43 | desc: "Detects MySQL and PostgreSQL stored procedure/function injections"
44 | stages:
45 | -
46 | stage:
47 | input:
48 | dest_addr: 127.0.0.1
49 | headers:
50 | Host: localhost
51 | method: POST
52 | port: 80
53 | uri: "/"
54 | data: "pay=declare+%40b%0A"
55 | version: HTTP/1.0
56 | output:
57 | log_contains: id "942320"
58 | -
59 | test_title: 942320-4
60 | desc: "Detects MySQL and PostgreSQL stored procedure/function injections"
61 | stages:
62 | -
63 | stage:
64 | input:
65 | dest_addr: 127.0.0.1
66 | headers:
67 | Host: localhost
68 | method: POST
69 | port: 80
70 | uri: "/"
71 | data: "pay=DECLARE%2F%2A%2A%2F%40x%0A"
72 | version: HTTP/1.0
73 | output:
74 | log_contains: id "942320"
75 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920400.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: csanders-git
4 | description: None
5 | enabled: true
6 | name: 920400.yaml
7 | tests:
8 | -
9 | test_title: 920400-1
10 | desc: Uploaded file size too large (920400) 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 | Content-Length: '10485760'
22 | Content-Type: multipart/form-data; boundary=---------------------------265001916915724
23 | Host: localhost
24 | Keep-Alive: '300'
25 | Proxy-Connection: keep-alive
26 | Referer: http
27 | User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv
28 | method: POST
29 | port: 80
30 | uri: /
31 | version: HTTP/1.1
32 | data:
33 | - '-----------------------------265001916915724'
34 | - 'Content-Disposition: form-data; name="file"; filename="test"'
35 | - 'Content-Type: application/octet-stream'
36 | - ''
37 | - Rotem & Ayala
38 | - ''
39 | - '-----------------------------265001916915724'
40 | - 'Content-Disposition: form-data; name="name"'
41 | - ''
42 | - tt2
43 | - '-----------------------------265001916915724'
44 | - 'Content-Disposition: form-data; name="B1"'
45 | - ''
46 | - Submit
47 | - '-----------------------------265001916915724--'
48 | output:
49 | # Most web servers simply won't respond to invalid requests like
50 | # like this they'll just time out when we get OR type checks
51 | # we'll be able to check for both an error or the rule firing
52 | expect_error: true
53 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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= 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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: "= 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/tests/REQUEST-933-APPLICATION-ATTACK-PHP/933151.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: lifeforms
4 | description: None
5 | enabled: true
6 | name: 933151.yaml
7 | tests:
8 | -
9 | test_title: 933151-1
10 | desc: pmf + chain; must run test in PL2!
11 | stages:
12 | - stage:
13 | input:
14 | data: x=Print_r%28%20%29
15 | dest_addr: 127.0.0.1
16 | headers:
17 | Host: localhost
18 | User-Agent: ModSecurity CRS 3 Tests
19 | method: POST
20 | port: 80
21 | uri: /array_diff%20foo%20%28
22 | output:
23 | log_contains: id "933151"
24 | -
25 | test_title: 933151-2
26 | desc: pmf + chain; must run test in PL2!
27 | stages:
28 | - stage:
29 | input:
30 | data: x=Print_r%28%20%29
31 | dest_addr: 127.0.0.1
32 | headers:
33 | Host: localhost
34 | User-Agent: ModSecurity CRS 3 Tests
35 | method: POST
36 | port: 80
37 | uri: /?date_ADD%28%29
38 | output:
39 | log_contains: id "933151"
40 | -
41 | test_title: 933151-3
42 | desc: non-dangorous PHP functions, removed to reduce FP
43 | stages:
44 | - stage:
45 | input:
46 | data: x=Print_r%28%20%29
47 | dest_addr: 127.0.0.1
48 | headers:
49 | Host: localhost
50 | User-Agent: ModSecurity CRS 3 Tests
51 | method: POST
52 | port: 80
53 | uri: /?foo=filemtime%28%24foo%29
54 | output:
55 | no_log_contains: id "933151"
56 | -
57 | test_title: 933151-4
58 | desc: pmf + chain; must run test in PL2!
59 | stages:
60 | - stage:
61 | input:
62 | data: gethostbynamE(
63 | dest_addr: 127.0.0.1
64 | headers:
65 | Host: localhost
66 | User-Agent: ModSecurity CRS 3 Tests
67 | method: POST
68 | port: 80
69 | uri: /gethost
70 | output:
71 | log_contains: id "933151"
72 | -
73 | test_title: 933151-5
74 | desc: No peren after keyword
75 | stages:
76 | - stage:
77 | input:
78 | dest_addr: 127.0.0.1
79 | headers:
80 | Host: localhost
81 | User-Agent: ModSecurity CRS 3 Tests
82 | method: POST
83 | port: 80
84 | uri: /?foo=array_diff
85 | output:
86 | no_log_contains: id "933151"
87 |
88 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920460.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "csanders-git"
4 | enabled: true
5 | name: "920460.yaml"
6 | description: "Description"
7 | tests:
8 | -
9 | test_title: 920460-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: 22
22 | Content-Type: "application/x-www-form-urlencoded"
23 | User-Agent: "ModSecurity CRS 3 Tests"
24 | data: 'file=cat+/etc/\passw\d'
25 | stop_magic: true
26 | output:
27 | log_contains: "id \"920460\""
28 | -
29 | test_title: 920460-2
30 | stages:
31 | -
32 | stage:
33 | input:
34 | dest_addr: "127.0.0.1"
35 | port: 80
36 | uri: "/?file=cat+/etc/pa\\ssw\\d"
37 | headers:
38 | User-Agent: "ModSecurity CRS 3 Tests"
39 | Host: "localhost"
40 | output:
41 | log_contains: "id \"920460\""
42 | -
43 | test_title: 920460-3
44 | stages:
45 | -
46 | stage:
47 | input:
48 | dest_addr: "127.0.0.1"
49 | port: 80
50 | uri: "/?file=\\c"
51 | headers:
52 | User-Agent: "ModSecurity CRS 3 Tests"
53 | Host: "localhost"
54 | output:
55 | log_contains: "id \"920460\""
56 | -
57 | test_title: 920460-4
58 | stages:
59 | -
60 | stage:
61 | input:
62 | dest_addr: "127.0.0.1"
63 | port: 80
64 | uri: "/?file=\\\\c"
65 | headers:
66 | User-Agent: "ModSecurity CRS 3 Tests"
67 | Host: "localhost"
68 | output:
69 | no_log_contains: "id \"920460\""
70 | -
71 | test_title: 920460-5
72 | stages:
73 | -
74 | stage:
75 | input:
76 | dest_addr: "127.0.0.1"
77 | port: 80
78 | uri: "/?file=\\\\\\c"
79 | headers:
80 | User-Agent: "ModSecurity CRS 3 Tests"
81 | Host: "localhost"
82 | output:
83 | no_log_contains: "id \"920460\""
84 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | })();
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-933-APPLICATION-ATTACK-PHP/933130.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: csanders-git
4 | description: Tests functionality of 933130
5 | enabled: true
6 | name: 933130.yaml
7 | tests:
8 | -
9 | test_title: 933130-1
10 | desc: Basic Request nothing should trigger
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: /
20 | output:
21 | no_log_contains: id "933130"
22 | -
23 | test_title: 933130-2
24 | desc: Trigger a basic request
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: /?x=$_SERVER['test'];
34 | output:
35 | log_contains: id "933130"
36 | -
37 | test_title: 933130-3
38 | desc: Non-Server Request
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: /?x=$_SE%20RVER['test'];
48 | output:
49 | no_log_contains: id "933130"
50 | -
51 | test_title: 933130-4
52 | desc: SERVER request URLEncoded
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: /?x=$_%53ERVER['test'];
62 | output:
63 | log_contains: id "933130"
64 | -
65 | test_title: 933130-5
66 | desc: SERVER request URLEncoded
67 | stages:
68 | - stage:
69 | input:
70 | dest_addr: 127.0.0.1
71 | headers:
72 | Host: localhost
73 | User-Agent: ModSecurity CRS 3 Tests
74 | port: 80
75 | uri: /?%24_COOKIE=value;
76 | output:
77 | log_contains: id "933130"
78 | -
79 | test_title: 933130-6
80 | desc: SERVER index listed with obfuscated SERVER
81 | stages:
82 | - stage:
83 | input:
84 | dest_addr: 127.0.0.1
85 | headers:
86 | Host: localhost
87 | User-Agent: ModSecurity CRS 3 Tests
88 | port: 80
89 | uri: /?x=$_%53%20ERVER['request_uri'];
90 | output:
91 | no_log_contains: id "933130"
92 |
93 |
94 |
--------------------------------------------------------------------------------
/tests/regression/tests/REQUEST-921-PROTOCOL-ATTACK/921110.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | meta:
3 | author: "Christian S.J. Peron"
4 | description: None
5 | enabled: true
6 | name: 921110.yaml
7 | tests:
8 | -
9 | test_title: 921110-1
10 | desc: "HTTP Response Splitting"
11 | stages:
12 | -
13 | stage:
14 | input:
15 | dest_addr: 127.0.0.1
16 | headers:
17 | Host: "localhost"
18 | Cache-Control: "no-cache, no-store, must-revalidate"
19 | method: POST
20 | port: 80
21 | data: "var=%0aPOST / HTTP/1.0"
22 | version: HTTP/1.0
23 | output:
24 | log_contains: id "921110"
25 | -
26 | test_title: 921110-2
27 | desc: "HTTP Response Splitting"
28 | stages:
29 | -
30 | stage:
31 | input:
32 | dest_addr: 127.0.0.1
33 | headers:
34 | Host: "localhost"
35 | Cache-Control: "no-cache, no-store, must-revalidate"
36 | method: POST
37 | port: 80
38 | data: "var=aaa%0aGET+/+HTTP/1.1"
39 | version: HTTP/1.0
40 | output:
41 | log_contains: id "921110"
42 | -
43 | test_title: 921110-3
44 | desc: "HTTP Response Splitting"
45 | stages:
46 | -
47 | stage:
48 | input:
49 | dest_addr: 127.0.0.1
50 | headers:
51 | Host: "localhost"
52 | Cache-Control: "no-cache, no-store, must-revalidate"
53 | method: POST
54 | port: 80
55 | data: "var=aaa%0dHEAD+http://example.com/+HTTP/1.1"
56 | version: HTTP/1.0
57 | output:
58 | log_contains: id "921110"
59 | -
60 | test_title: 921110-4
61 | desc: "HTTP Response Splitting"
62 | stages:
63 | -
64 | stage:
65 | input:
66 | dest_addr: 127.0.0.1
67 | headers:
68 | Host: "localhost"
69 | Cache-Control: "no-cache, no-store, must-revalidate"
70 | method: POST
71 | port: 80
72 | data: "var=aaa%0d%0aGet+/foo%0d"
73 | version: HTTP/1.0
74 | output:
75 | log_contains: id "921110"
76 | -
77 | test_title: 921110-5
78 | desc: "HTTP Response Splitting"
79 | stages:
80 | -
81 | stage:
82 | input:
83 | dest_addr: 127.0.0.1
84 | headers:
85 | Host: "localhost"
86 | Cache-Control: "no-cache, no-store, must-revalidate"
87 | method: POST
88 | port: 80
89 | data: "var=aaa%0d%0aGet+foo+bar"
90 | version: HTTP/1.0
91 | output:
92 | no_log_contains: id "921110"
93 |
--------------------------------------------------------------------------------