Update coreruleset to version 4.0.0

This commit is contained in:
Théophile Diot 2024-02-15 11:09:20 +01:00
parent 3db316490d
commit 154889a667
No known key found for this signature in database
GPG key ID: 248FEA4BAE400D06
606 changed files with 59684 additions and 18214 deletions

View file

@ -25,6 +25,7 @@
- [DEPS] Updated lua-resty-core to v0.1.28
- [DEPS] Updated zlib version to v1.3.1
- [DEPS] Updated ModSecurity version to v3.0.12
- [DEPS] Updated coreruleset version to v4.0.0
- [DEPS] Updated lua-resty-mlcache version to v2.6.1
## v1.5.5 - 2024/01/12

View file

@ -0,0 +1,24 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# Matches multiple files with brace expansion notation
# Set default charset
[*.py]
charset = utf-8
# 4 space indentation
indent_style = space
indent_size = 4
# Indentation override for all JS under lib directory
[tests/regression/tests/**/*.yaml]
indent_style = space
indent_size = 2

View file

@ -0,0 +1 @@
custom: https://coreruleset.org/donate

View file

@ -1,31 +1,68 @@
---
name: 'False positive'
about: Report a false positive (incorrect blocking)
about: Report a false positive (blocking of benign traffic)
title: ''
labels: 'False Positive'
labels: ':heavy_plus_sign: False Positive'
assignees: ''
---
<!--
Please do not open issues for help and support running ModSecurity or the
OWASP Core Rule Set. Instead, use one of the following channels to reach
our project:
* https://security.stackexchange.com/questions/tagged/owasp-crs
* https://twitter.com/coreruleset
* https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project
* https://owasp.org/slack/invite (-> Channel #coreruleset)
-->
### Description
<!-- Please provide a copy of the audit log entry. You can usually -->
<!-- find this at /var/log/modsec_audit.log. -->
<!-- Include any relevant CVEs or research links. -->
<!--
We want to be able to understand and to reproduce your problem. Please describe
it here in detail.
### Audit Logs / Triggered Rule Numbers
It is safest if you assume we know nothing about your service or software.
-->
<!-- Everything you can provide about a blocked request/response -->
<!-- or, at least, a list of triggered CRS rule numbers. -->
### How to reproduce the misbehavior (-> curl call)
<!--
It is easiest for us, if you submit a curl request that triggers your problem.
If you can not do this, then please skip this section but be sure to fill out
the next one in detail.
Please test your curl call against the CRS Sandbox before submitting.
https://coreruleset.org/docs/development/sandbox/
-->
### Logs
<!--
Feel free to skip this section if you provided a curl call above.
Ideally, you provide a full audit log of the request, relevant infos out of
the error log or at least a screenshot where we can see the payload so we
can reproduce the behavior.
Usually, you find the logs at a location like /var/log/modsec_audit.log.
When using a CDN or cloud server, the naming of the logs and their location
depends on the provider. Please refer to their documentation.
If you cannot submit neither curl call nor log files nor a payload to reproduce
the behavior, there is litterally nothing we can do for you. Please help us to
get access to the information we need to help you.
-->
### Your Environment
<!-- Include as many relevant details about the environment you -->
<!-- experienced the bug in: -->
<!-- Please provide all relevant information about your environment. -->
* CRS version (e.g., v3.2.0):
* Paranoia level setting:
* ModSecurity version (e.g., 2.9.3):
* Web Server and version (e.g., apache 2.4.41):
* CRS version (e.g., v3.3.4):
* Paranoia level setting (e.g. PL1) :
* ModSecurity version (e.g., 2.9.6):
* Web Server and version or cloud provider / CDN (e.g., Apache httpd 2.4.54):
* Operating System and version:
### Confirmation

View file

@ -1,30 +1,68 @@
---
name: 'False negative'
about: Report a false negative (incorrect bypass)
about: Report a false negative (ignoring of malicious traffic)
title: ''
labels: 'False Negative - Evasion'
labels: ':heavy_minus_sign: False Negative - Evasion'
assignees: ''
---
<!--
Please do not open issues for help and support running ModSecurity or the
OWASP Core Rule Set. Instead, use one of the following channels to reach
our project:
* https://security.stackexchange.com/questions/tagged/owasp-crs
* https://twitter.com/coreruleset
* https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project
* https://owasp.org/slack/invite (-> Channel #coreruleset)
-->
### Description
<!-- Please provide the payload you are sending. For complex payloads -->
<!-- with headers, please include a curl command. -->
<!-- Include any relevant CVEs or research links. -->
<!-- If the bypass works in paranoia level 4, please consider sending -->
<!-- us an email instead. See -->
<!-- https://github.com/SpiderLabs/owasp-modsecurity-crs/security/policy -->
<!-- for details. -->
<!--
We want to be able to understand and to reproduce your problem. Please describe
it here in detail.
It is safest if you assume we know nothing about your service or software.
-->
### How to reproduce the misbehavior (-> curl call)
<!--
It is easiest for us, if you submit a curl request that triggers your problem.
If you can not do this, then please skip this section but be sure to fill out
the next one in detail.
Please test your curl call against the CRS Sandbox before submitting.
https://coreruleset.org/docs/development/sandbox/
-->
### Logs
<!--
Feel free to skip this section if you provided a curl call above.
Ideally, you provide a full audit log of the request, relevant infos out of
the error log or at least a screenshot where we can see the payload so we
can reproduce the behavior.
Usually, you find the logs at a location like /var/log/modsec_audit.log.
When using a CDN or cloud server, the naming of the logs and their location
depends on the provider. Please refer to their documentation.
If you cannot submit neither curl call nor log files nor a payload to reproduce
the behavior, there is litterally nothing we can do for you. Please help us to
get access to the information we need to help you.
-->
### Your Environment
<!-- Include as many relevant details about the environment you -->
<!-- experienced the bug in: -->
<!-- Please provide all relevant information about your environment. -->
* CRS version (e.g., v3.2.0):
* Paranoia level setting:
* ModSecurity version (e.g., 2.9.3):
* Web Server and version (e.g., apache 2.4.41):
* CRS version (e.g., v3.3.4):
* Paranoia level setting (e.g. PL1) :
* ModSecurity version (e.g., 2.9.6):
* Web Server and version or cloud provider / CDN (e.g., Apache httpd 2.4.54):
* Operating System and version:
### Confirmation

View file

@ -2,7 +2,7 @@
name: '🐞 Bug report'
about: Create a report to help us improve
title: ''
labels: 'Bug'
labels: ':bug: bug'
assignees: ''
---

View file

@ -2,10 +2,16 @@
name: '🚀 Feature request'
about: Suggest an idea for this project
title: ''
labels: 'Feature Request'
labels: ':+1: Feature Request'
assignees: ''
---
<!--
For help and support please go here:
- https://security.stackexchange.com/questions/tagged/owasp-crs
Ask general usage questions and participate in discussions on the CRS:
- https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project
-->
### Motivation
<!-- A clear and concise description of what the motivation for the -->

View file

@ -4,5 +4,5 @@ contact_links:
url: https://security.stackexchange.com/questions/tagged/owasp-crs
about: For help and support please go here.
- name: OWASP Core Rule Set mailing list
url: https://groups.google.com/a/owasp.org/forum/#!forum/modsecurity-core-rule-set-project
url: https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project
about: Ask general usage questions and participate in discussions on the CRS.

View file

@ -0,0 +1,30 @@
## Proposed changes
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
<!-- Github Tip: adding the text 'Fixes #<issue>' or 'Closes #<issue>' will automatically close the mentioned issue. -->
## PR Checklist
<!-- _Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._ -->
- [ ] I have read the [CONTRIBUTING](https://github.com/coreruleset/coreruleset/blob/v4.0/dev/CONTRIBUTING.md) doc
- [ ] I have added positive tests proving my fix/feature works as intended.
- [ ] I have added negative tests that prove my fix/feature considers common cases that might end in false positives
- [ ] In case you changed a regular expression, you are not adding a ReDOS for pcre. You can check this using [regexploit](https://github.com/doyensec/regexploit)
- [ ] My test use the `comment` field to write the expected behavior
- [ ] I have added documentation for the rule or change (when appropriate)
## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... If there are no additional comments, you may remove this section. -->
## For the reviewer
<!-- Don't remove this part. Reviewers will use it as guidance for the review process. -->
- [ ] Positive and negative tests were added
- [ ] Tests cover the intended fix/feature properly
- [ ] No usage of dangerous constructs like `ctl:requestBodyAccess=Off` were used in the rule
- [ ] In case a regular expression was changed, [there is no ReDOS](https://github.com/coreruleset/coreruleset/wiki/Testing-for-Regular-Expresion-DoS)
- [ ] Documentation is clear for the rule/change

View file

@ -0,0 +1,184 @@
#! /usr/bin/env python
import subprocess
import json
import datetime
import sys
import os
import re
DEVELOPERS = dict()
def get_pr(repository: str, number: int) -> dict:
command = f"""gh pr view \
--repo "{repository}" \
"{number}" \
--json mergeCommit,mergedBy,title,author,baseRefName,number
"""
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pr_json, errors = proc.communicate()
if proc.returncode != 0:
print(errors)
exit(1)
return json.loads(pr_json)
def get_prs(repository: str, day: datetime.date) -> list:
print(f"Fetching PRs for {day}")
command = f"""gh search prs \
--repo "{repository}" \
--merged-at "{day}" \
--json number \
-- \
-label:changelog-pr # ignore changelog prs
"""
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
prs_json, errors = proc.communicate()
if proc.returncode != 0:
print(errors)
exit(1)
prs = list()
for result in json.loads(prs_json):
prs.append(get_pr(repository, result["number"]))
return prs
def parse_prs(prs: list) -> dict:
pr_map = dict()
for pr in prs:
merged_by = pr["mergedBy"]["login"]
if merged_by not in pr_map:
pr_list = list()
pr_map[merged_by] = pr_list
else:
pr_list = pr_map[merged_by]
pr_list.append(pr)
return pr_map
def create_prs(repository: str, merged_by_prs_map: dict, day: datetime.date):
for author in merged_by_prs_map.keys():
create_pr(repository, author, merged_by_prs_map[author], day)
def create_pr(repository: str, merged_by: str, prs: list, day: datetime.date):
if len(prs) == 0:
return
print(f"Creating changelog PR for @{merged_by}")
sample_pr = prs[0]
base_branch = sample_pr["baseRefName"]
pr_branch_name = create_pr_branch(day, merged_by, base_branch)
pr_body, changelog_lines = generate_content(prs, merged_by)
create_commit(changelog_lines)
push_pr_branch(pr_branch_name)
command = f"""gh pr create \
--repo "{repository}" \
--assignee "{merged_by}" \
--base "{base_branch}" \
--label "changelog-pr" \
--title "chore: changelog updates for {day}, merged by @{merged_by}" \
--body-file -
"""
proc = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
outs, errors = proc.communicate(input=pr_body.encode())
if proc.returncode != 0:
print(errors)
exit(1)
print(f"Created PR: {outs.decode()}")
def create_commit(changelog_lines: str):
with open('.changes-pending.md', 'a') as changelog:
changelog.write(changelog_lines)
command = "git commit .changes-pending.md -m 'Add pending changelog entries'"
proc = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
_, errors = proc.communicate()
if proc.returncode != 0:
print(errors)
exit(1)
def generate_content(prs: list, merged_by: str) -> (str, str):
changelog_lines = ""
pr_body = f"This PR was auto-generated to update the changelog with the following entries, merged by @{merged_by}:\n```\n"
pr_links = ""
for pr in prs:
pr_number = pr["number"]
pr_title = pr["title"]
pr_author = get_pr_author_name(pr["author"]["login"])
new_line = f" * {pr_title} ({pr_author}) [#{pr_number}]\n"
pr_body += new_line
pr_links += f"- #{pr_number}\n"
changelog_lines += new_line
pr_body += "```\n\n" + pr_links
return pr_body, changelog_lines
def get_pr_author_name(login: str) -> str:
if len(DEVELOPERS) == 0:
parse_contributors()
return DEVELOPERS[login] if login in DEVELOPERS else f"@{login}"
def parse_contributors():
regex = re.compile(r'^\s*?-\s*?\[([^]]+)\]\s*?\(http.*/([^/]+)\s*?\)')
with open('CONTRIBUTORS.md', 'rt') as handle:
line = handle.readline()
while not ('##' in line and 'Contributors' in line):
match = regex.match(line)
if match:
DEVELOPERS[match.group(2)] = match.group(1)
line = handle.readline()
def create_pr_branch(day: datetime.date, author: str, base_branch: str) -> str:
branch_name = f"changelog-updates-for-{day}-{author} {base_branch}"
command = f"git checkout -b {branch_name}"
proc = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
_, errors = proc.communicate()
if proc.returncode != 0:
print(errors)
exit(1)
return branch_name
def push_pr_branch(branch_name: str):
command = f"git push -u origin {branch_name}"
proc = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
_, errors = proc.communicate()
if proc.returncode != 0:
print(errors)
exit(1)
def run(source_repository: str, target_repository: str, today: datetime.date):
day = today - datetime.timedelta(days=1)
prs = get_prs(source_repository, day)
prs_length = len(prs)
print(f"Found {prs_length} PRs")
if prs_length == 0:
return
merged_by_prs_map = parse_prs(prs)
create_prs(target_repository, merged_by_prs_map, day)
if __name__ == "__main__":
# disable pager
os.environ["GH_PAGER"] = ''
# set variables for Git
os.environ["GIT_AUTHOR_NAME"] = "changelog-pr-bot"
os.environ["GIT_AUTHOR_EMAIL"] = "dummy@coreruleset.org"
os.environ["GIT_COMMITTER_NAME"] = "changelog-pr-bot"
os.environ["GIT_COMMITTER_EMAIL"] = "dummy@coreruleset.org"
source_repository = 'coreruleset/coreruleset'
target_repository = source_repository
# the cron schedule for the workflow uses UTC
today = datetime.datetime.now(datetime.timezone.utc).date()
if len(sys.argv) > 1:
source_repository = sys.argv[1]
if len(sys.argv) > 2:
target_repository = sys.argv[2]
if len(sys.argv) > 3:
today = datetime.date.fromisoformat(sys.argv[3])
run(source_repository, target_repository, today)

View file

@ -0,0 +1,19 @@
name: Check PR dependencies
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
jobs:
check_dependencies:
runs-on: ubuntu-latest
name: Check Dependencies
permissions:
pull-requests: read # Reason: To check PRs for dependencies.
steps:
- uses: gregsdennis/dependencies-action@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -0,0 +1,16 @@
name: Check PR title
on:
pull_request_target:
types:
- opened
- reopened
- edited
- synchronize
jobs:
check-pr-title:
runs-on: ubuntu-latest
steps:
- uses: aslafy-z/conventional-pr-title-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,4 +1,3 @@
---
name: Lint
on: [push, pull_request]
@ -6,12 +5,9 @@ on: [push, pull_request]
jobs:
check-syntax:
runs-on: ubuntu-latest
strategy:
fail-fast: true
# check why is failing and change afterwards
steps:
- name: Checkout repo
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Lint Yaml
uses: ibiqlik/action-yamllint@v3
@ -25,7 +21,7 @@ jobs:
id: linelint
- name: Set up Python 3
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.7
@ -35,3 +31,35 @@ jobs:
pip install secrules-parsing
secrules-parser -c --output-type github -f rules/*.conf
- name: "Check CRS formatting"
run: |
pip install --upgrade setuptools
pip install -r ./util/crs-rules-check/requirements.txt
./util/crs-rules-check/rules-check.py --output=github -r crs-setup.conf.example -r rules/*.conf -t util/APPROVED_TAGS
- name: "Find rules without test"
run: |
pip install --upgrade setuptools
pip install -r ./util/find-rules-without-test/requirements.txt
./util/find-rules-without-test/find-rules-without-test.py --output=github .
- name: "Install crs-toolchain"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release download -R coreruleset/crs-toolchain -p '*_linux_amd64.tar.gz'
ls crs-toolchain*
tar xzf crs-toolchain*_linux_amd64.tar.gz
rm crs-toolchain*_linux_amd64.tar.gz
- name: "Check that all assembly files are properly formatted"
run: |
./crs-toolchain regex format -aco github
- name: "Check that all rules are up to date"
run: |
./crs-toolchain regex compare -ao github
- name: "Check that all tests are properly numbered"
run: |
./crs-toolchain util renumber-tests -cao github

View file

@ -0,0 +1,61 @@
name: Nightly Release
on:
schedule:
- cron: '0 2 * * *' # run at 2 AM UTC
jobs:
nightly:
name: Nightly Release
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
- name: Delete previous nightly release
run: |
gh release delete --repo coreruleset/coreruleset --cleanup-tag --yes nightly
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create nightly release
run: |
notes=$(cat <<"EOF"
Nightly releases are snapshots of the development activity on the Core Rule Set project that may include new features and bug fixes scheduled for upcoming releases. These releases are made available to make it easier for users to test their existing configurations against the Core Rule Set code base for potential issues or to experiment with new features, with a chance to provide feedback on ways to improve the changes before being released.
As these releases are snapshots of the latest code, you may encounter an issue compared to the latest stable release so users are encouraged to run nightly releases in a non production environment. If you encounter an issue, please check our issue tracker to see if the issue has already been reported; if a report hasn't been made, please report it so we can review the issue and make any needed fixes.
EOF
)
gh release create \
--repo coreruleset/coreruleset \
--latest \
--prerelease \
--draft=false \
--title "Latest Nightly" \
--notes "${notes}" \
nightly
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish draft if necessary
run: |
echo "A race condition in the GH API can cause a release published for a previously existing tag to be published as draft."
echo "Wait for 30 seconds for the API to catch up to the actual state, then check that the release has been properly published."
echo "If the release is still a draft, publish it."
sleep 30
if gh release list --repo coreruleset/coreruleset --exclude-drafts | grep --quiet nightly; then
echo "Nightly release was created properly"
exit 0
fi
echo "Nightly release was created as draft. Publishing now."
gh release edit \
--repo coreruleset/coreruleset \
--latest \
--prerelease \
--draft=false \
nightly
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -10,10 +10,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v1
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
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'
stale-issue-message: 'This issue has been open 30 days waiting for feedback. Remove the stale label or comment, or this will be closed in 14 days'
stale-issue-label: 'Stale issue'
days-before-stale: 120
days-before-stale: 30
days-before-close: 14
only-issue-labels: ':hourglass_flowing_sand: awaiting feedback'

View file

@ -1,4 +1,3 @@
---
name: Regression Tests
on:
@ -11,6 +10,7 @@ on:
paths:
- 'rules/**'
- 'tests/**'
- 'util/**'
- '.github/**'
jobs:
@ -21,12 +21,12 @@ jobs:
modsec_version: [modsec2-apache]
steps:
- name: "Checkout repo"
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: "Install dependencies"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GO_FTW_VERSION: '0.4.6'
GO_FTW_VERSION: '0.6.4'
run: |
gh release download -R coreruleset/go-ftw v${GO_FTW_VERSION} -p "ftw_${GO_FTW_VERSION}_linux_amd64.tar.gz" -O - | tar -xzvf - ftw
@ -39,7 +39,7 @@ jobs:
./ftw check -d tests/regression/tests
./ftw run -d tests/regression/tests --show-failures-only
env:
FTW_LOGFILE: './tests/logs/modsec2-apache/error.log'
FTW_LOGFILE: './tests/logs/${{ matrix.modsec_version }}/error.log'
- name: "Change permissions if failed"
if: failure()
@ -47,7 +47,7 @@ jobs:
# we want to get the audit log, so change permissions (file is only for root on docker)
sudo chmod 644 tests/logs/${{ matrix.modsec_version }}/modsec_audit.log
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
if: failure()
with:
name: waf-logs

View file

@ -0,0 +1,23 @@
name: Create changelog PRs
on:
schedule:
- cron: '0 2 * * *' # run at 2 AM UTC
jobs:
create-changelog-prs:
name:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
- name: Set up Python 3
uses: actions/setup-python@v4
with:
python-version: 3.12
- name: "Run script"
run: ".github/create-changelog-prs.py"
env:
# Required for the use of the gh CLI in the script
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -10,6 +10,10 @@ rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
# util/upgrade.py geoip
util/geo-location/GeoIP.dat
# PHP functions frequency list generated and updated by running
# util/php-dictionary-gen.sh
util/php-dictionary-gen/frequencylist.txt
# Unit test caches
.cache
@ -19,3 +23,12 @@ __pycache__/
*$py.class
.idea/
# Ignore test logs
tests/logs/
# ignore .env in tests for docker-compose variables
tests/.env
# Ignore Go-FTW configuration file
.ftw.yaml

View file

@ -1,4 +1,4 @@
[submodule "docs/OWASP-CRS-Documentation"]
path = docs/OWASP-CRS-Documentation
url = https://github.com/SpiderLabs/OWASP-CRS-Documentation
branch = master
url = https://github.com/coreruleset/documentation.git
branch = main

View file

@ -10,3 +10,4 @@ rules:
# will be ignored only by this rule
ignore:
- .pytest_cache/*
- .changes-pending.md

View file

@ -0,0 +1,13 @@
---
# Update the rev variable with the release version that you want, from the yamllint repo
# You can pass your custom .yamllint with args attribute.
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
args: [--allow-multiple-documents]
- id: end-of-file-fixer
- id: trailing-whitespace
exclude: '^regex-assembly/'
args: [--markdown-linebreak-ext=md]

View file

@ -1,31 +0,0 @@
os: linux
language: python
python:
- 2.7
# no more required in travis
#sudo: required
services:
- docker
jobs:
include:
script:
- |
if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then
docker run -ti --name crs-test --entrypoint /docker-entrypoint.sh -e REPO=$TRAVIS_PULL_REQUEST_SLUG -e BRANCH=$TRAVIS_PULL_REQUEST_BRANCH themiddle/crs-test
else
docker run -ti --name crs-test --entrypoint /docker-entrypoint.sh -e REPO=$TRAVIS_REPO_SLUG -e BRANCH=$TRAVIS_BRANCH themiddle/crs-test
fi
# safelist
branches:
only:
- v3.1/dev
- v3.2/dev
- v3.3/dev
- fix-travis
#notifications:
# irc: "chat.freenode.net#modsecurity"

View file

@ -11,6 +11,8 @@ rules:
tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920380.yaml
tests/regression/tests/REQUEST-920-PROTOCOL-ENFORCEMENT/920390.yaml
tests/regression/tests/REQUEST-941-APPLICATION-ATTACK-XSS/941360.yaml
tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942521.yaml
tests/regression/tests/REQUEST-942-APPLICATION-ATTACK-SQLI/942522.yaml
# don't bother me with this rule
indentation: disable

File diff suppressed because it is too large Load diff

View file

@ -1,152 +1,470 @@
# Contributing to the CRS
# Contribution Guidelines
We value third-party contributions. To keep things simple for you and us,
please adhere to the following contributing guidelines.
**Note:** An HTML version of these guidelines can be found on the CRS documentation site at https://coreruleset.org/docs/development/contribution_guidelines/
## Getting Started
> The CRS project values third party contributions. To make the contribution process as easy as possible, a helpful set of contribution guidelines are in place which all contributors and developers are asked to adhere to.
* You will need a [GitHub account](https://github.com/signup/free).
* Submit a [ticket for your issue](https://github.com/SpiderLabs/owasp-modsecurity-crs/issues), assuming one does not already exist.
* Clearly describe the issue including steps to reproduce when it is a bug.
* Make sure you specify the version that you know has the issue.
* Bonus points for submitting a failing test along with the ticket.
* If you don't have push access, fork the repository on GitHub.
## Getting Started with a New Contribution
1. Sign in to [GitHub](https://github.com/join).
2. Open a [new issue](https://github.com/coreruleset/coreruleset/issues) for the contribution, *assuming a similar issue doesn't already exist*.
* **Clearly describe the issue**, including steps to reproduce if reporting a bug.
* **Specify the CRS version in question** if reporting a bug.
* Bonus points for submitting tests along with the issue.
3. Fork the repository on GitHub and begin making changes there.
4. Signed commits are preferred. (For more information and help with this, refer to the [GitHub documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits)).
## Making Changes
* Please base your changes on branch ```v3.3/dev```
* Create a topic branch for your feature or bug fix.
* Please fix only one problem at a time; this will help to quickly test and merge your change. If you intend to fix multiple unrelated problems, please use a separate branch for each problem.
* Base any changes on branch `main`.
* Create a topic branch for each new contribution.
* Fix only one problem at a time. This helps to quickly test and merge submitted changes. If intending to fix *multiple unrelated problems* then use a separate branch for each problem.
* Make commits of logical units.
* Make sure your commits adhere to the rules guidelines below.
* Make sure your commit messages are in the [proper format](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html): The first line of the message should have 50 characters or less, separated by a blank line from the (optional) body. The body should be wrapped at 70 characters and paragraphs separated by blank lines. Bulleted lists are also fine.
* Make sure commits adhere to the contribution guidelines presented in this document.
* Make sure commit messages follow the [standard Git format](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
* Make sure changes are submitted as a pull request (PR) on [GitHub](https://github.com/coreruleset/coreruleset/pulls).
* PR titles should follow the [Conventional Commits format](https://www.conventionalcommits.org/en/v1.0.0/), for example: `fix(rce): Fix a FP in rule 912345 with keyword 'time'`.
* If a PR only affects a single rule then the rule ID should be included in the title.
* If a PR title does not follow the correct format then a CRS developer will fix it.
## General Formatting Guidelines for rules contributions
## General Formatting Guidelines for Rules Contributions
- 4 spaces per indentation level, no tabs
- no trailing whitespace at EOL or trailing blank lines at EOF
- comments are good, especially when they clearly explain the rule
- try to adhere to a 80 character line length limit
- if it is a [chained rule](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#chain), alignment should be like
* American English should be used throughout.
* 4 spaces should be used for indentation (no tabs).
* Files must end with a single newline character.
* No trailing whitespace at EOL.
* No trailing blank lines at EOF (only the required single EOF newline character is allowed).
* Adhere to an 80 character line length limit where possible.
* Add comments where possible and clearly explain any new rules.
* Comments must not appear between chained rules and should instead be placed before the start of a rule chain.
* All [chained rules](https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v2.x)#chain) should be indented like so, for readability:
```
SecRule .. ..\
"...."
SecRule .. ..\
SecRule .. .. \
"..."
SecRule .. .. \
"..."
SecRule .. .. \
"..."
SecRule .. ..\
".."
```
- use quotes even if there is only one action, it improves readability (e.g., use `"chain"`, not `chain`, or `"ctl:requestBodyAccess=Off"` instead of `ctl:requestBodyAccess=Off`)
- always use numbers for phases, instead of names
- format your `SecMarker` between double quotes, using UPPERCASE and separating words using hyphens. Examples are:
- Action lists in rules must always be enclosed in double quotes for readability, even if there is only one action (e.g., use `"chain"` instead of `chain`, and `"ctl:requestBodyAccess=Off"` instead of `ctl:requestBodyAccess=Off`).
- Always use numbers for phases instead of names.
- Format all use of `SecMarker` using double quotes, using UPPERCASE, and separating words with hyphens. For example:
```
SecMarker "END-RESPONSE-959-BLOCKING-EVALUATION"
SecMarker "END-REQUEST-910-IP-REPUTATION"
SecMarker "END-RESPONSE-959-BLOCKING-EVALUATION"
SecMarker "END-REQUEST-910-IP-REPUTATION"
```
- the proposed order for actions is:
- Rule actions should appear in the following order, for consistency:
```
id
phase
allow | block | deny | drop | pass | proxy | redirect
status
capture
t:xxx
log
nolog
auditlog
noauditlog
msg
logdata
tag
sanitiseArg
sanitiseRequestHeader
sanitiseMatched
sanitiseMatchedBytes
ctl
ver
severity
multiMatch
initcol
setenv
setvar
expirevar
chain
skip
skipAfter
id
phase
allow | block | deny | drop | pass | proxy | redirect
status
capture
t:xxx
log
nolog
auditlog
noauditlog
msg
logdata
tag
sanitiseArg
sanitiseRequestHeader
sanitiseMatched
sanitiseMatchedBytes
ctl
ver
severity
multiMatch
initcol
setenv
setvar
expirevar
chain
skip
skipAfter
```
- Rule operators must always be explicitly specified. Although ModSecurity defaults to using the `@rx` operator, for clarity `@rx` should always be explicitly specified when used. For example, write:
```
SecRule ARGS "@rx foo" "id:1,phase:1,pass,t:none"
```
instead of
```
SecRule ARGS "foo" "id:1,phase:1,pass,t:none"
```
* Only the tags listed in the [util/APPROVED_TAGS](util/APPROVED_TAGS) file can be added to a rule. If you want to add a new tag, you **must** add it to this file.
## Variable Naming Conventions
* Variable names should be lowercase and should use the characters a-z, 0-9, and underscores only.
* To reflect the different syntax between *defining* a variable (using `setvar`) and *using* a variable, the following visual distinction should be applied:
* **Variable definition:** Lowercase letters for collection name, dot as the separator, variable name. E.g.: `setvar:tx.foo_bar_variable`
* **Variable use:** Capital letters for collection name, colon as the separator, variable name. E.g.: `SecRule TX:foo_bar_variable`
## Writing Regular Expressions
* Use the following character class, in the stated order, to cover alphanumeric characters plus underscores and hyphens: `[a-zA-Z0-9_-]`
### Portable Backslash Representation
CRS uses `\x5c` to represent the backslash `\` character in regular expressions. Some of the reasons for this are:
* It's portable across web servers and WAF engines: it works with Apache, Nginx, and Coraza.
* It works with the [crs-toolchain](https://coreruleset.org/docs/development/crs_toolchain/) for building optimized regular expressions.
The older style of representing a backslash using the character class `[\\\\]` must _not_ be used. This was previously used in CRS to get consistent results between Apache and Nginx, owing to a quirk with how Apache would "double un-escape" character escapes. For future reference, the decision was made to stop using this older method because:
* It can be confusing and difficult to understand how it works.
* It doesn't work with [crs-toolchain](https://coreruleset.org/docs/development/crs_toolchain/).
* It doesn't work with Coraza.
* It isn't obvious how to use it in a character class, e.g., `[a-zA-Z<portable-backslash>]`.
### Forward Slash Representation
CRS uses literal, *unescaped* forward slash `/` characters in regular expressions.
Regular expression engines and libraries based on PCRE use the forward slash `/` character as the default delimiter. As such, forward slashes are often escaped in regular expression patterns. In the interests of readability, CRS does *not* escape forward slashes in regular expression patterns, which may seem unusual at first to new contributors.
If testing a CRS regular expression using a third party tool, it may be useful to change the delimiter to something other than `/` if a testing tool raises errors because a CRS pattern features unescaped forward slashes.
### When and Why to Anchor Regular Expressions
Engines running the OWASP CRS will use regular expressions to _search_ the input string, i.e., the regular expression engine is asked to find the first match in the input string. If an expression needs to match the entire input then the expression must be anchored appropriately.
#### Beginning of String Anchor (^)
It is often necessary to match something at the start of the input to prevent false positives that match the same string in the middle of another argument, for example. Consider a scenario where the goal is to match the value of `REQUEST_HEADERS:Content-Type` to `multipart/form-data`. The following regular expression could be used:
```python
"@rx multipart/form-data"
```
## Variable naming conventions
HTTP headers can contain multiple values, and it may be necessary to guarantee that the value being searched for is the _first_ value of the header. There are different ways to do this but the simplest one is to use the `^` caret anchor to match the beginning of the string:
* Variable names are lowercase using chars from `[a-z0-9_]`
* To somewhat reflect the fact that the syntax for variable usage is different when you define it (using setvar) and when you use it, we propose the following visual distinction:
* Lowercase letters for collection, dot as separator, variable name. E.g.,: `setvar:tx.foo_bar_variable`
* Capital letters for collection, colon as separator, variable name. E.g.,: `SecRule TX:foo_bar_variable`
```python
"@rx ^multipart/form-data"
```
## Rules compliance with each Paranoia Level (PL)
It will also be useful to ignore case sensitivity in this scenario:
Rules in the CRS are organized in Paranoia Levels, which allows you to choose the desired level of rule checks.
```python
"@rx (?i)^multipart/form-data"
```
Please read file ```crs-setup.conf.example``` for an introduction and a more detailed explanation of Paranoia Levels in the section `# -- [[ Paranoia Level Initialization ]]`.
#### End of String Anchor ($)
**PL0:**
Consider, for example, needing to find the string `/admin/content/assets/add/evil` in the `REQUEST_FILENAME`. This could be achieved with the following regular expression:
* Modsec installed, but almost no rules
```python
"@rx /admin/content/assets/add/evil"
```
**PL1:**
If the input is changed, it can be seen that this expression can easily produce a false positive: `/admin/content/assets/add/evilbutactuallynot/nonevilfile`. If it is known that the file being searched for can't be in a subdirectory of `add` then the `$` anchor can be used to match the end of the input:
* Default level, keep in mind that most installations will normally use this one
* If there is a complex memory consuming/evaluation rule it surely will be on upper levels, not this one
* Normally we will use atomic checks in single rules
* Confirmed matches only, all scores are allowed
* No false positives / Low FP (Try to avoid adding rules with potential false positives!)
```python
"@rx /admin/content/assets/add/evil$"
```
This could be made a bit more general:
```python
"@rx /admin/content/assets/add/[a-z]+$"
```
#### Matching the Entire Input String
It is sometimes necessary to match the entire input string to ensure that it _exactly_ matches what is expected. It might be necessary to find the "edit" action transmitted by WordPress, for example. To avoid false positives on variations (e.g., "myedit", "the edit", "editable", etc.), the `^` caret and `$` dollar anchors can be used to indicate that an exact string is expected. For example, to only match the _exact_ strings `edit` or `editpost`:
```python
"@rx ^(?:edit|editpost)$"
```
#### Other Anchors
Other anchors apart from `^` caret and `$` dollar exist, such as `\A`, `\G`, and `\Z` in PCRE. CRS **strongly discourages** the use of other anchors for the following reasons:
- Not all regular expression engines support all anchors and the OWASP CRS should be compatible with as many regular expression engines as possible.
- Their function is sometimes not trivial.
- They aren't well known and would require additional documentation.
- In most cases that would justify their use the regular expression can be transformed into a form that doesn't require them, or the rule can be transformed (e.g., with an additional chain rule).
### Use Capture Groups Sparingly
Capture groups, i.e., parts of the regular expression surrounded by parentheses (`(` and `)`), are used to store the matched information from a string in memory for later use. Capturing input uses both additional CPU cycles and additional memory. In many cases, parentheses are *mistakenly* used for grouping and ensuring precedence.
To group parts of a regular expression, or to ensure that the expression uses the precedence required, surround the concerning parts with `(?:` and `)`. Such a group is referred to as being "non-capturing". The following will create a capture group:
```python
"@rx a|(b|c)d"
```
On the other hand, this will create a _non-capturing_ group, guaranteeing the precedence of the alternative _without_ capturing the input:
```python
"@rx a|(?:b|c)d"
```
### Lazy Matching
The question mark `?` can be used to turn "greedy" quantifiers into "lazy" quantifiers, i.e., `.+` and `.*` are greedy while `.+?` and `.*?` are lazy. Using lazy quantifiers can help with writing certain expressions that wouldn't otherwise be possible. However, in backtracking regular expression engines, like PCRE, lazy quantifiers can also be a source of performance issues. The following is an example of an expression that uses a lazy quantifier:
```python
"@rx (?i)\.cookie\b.*?;\W*?(?:expires|domain)\W*?="
```
This expression matches cookie values in HTML to detect session fixation attacks. The input string could be `document.cookie = "name=evil; domain=https://example.com";`.
The lazy quantifiers in this expression are used to reduce the amount of backtracking that engines such as PCRE have to perform (others, such as RE2, are not affected by this). Since the asterisk `*` is greedy, `.*` would match every character in the input up to the end, at which point the regular expression engine would realize that the next character, `;`, can't be matched and it will backtrack to the previous position (`;`). A few iterations later, the engine will realize that the character `d` from `domain` can't be matched and it will backtrack again. This will happen again and again, until the `;` at `evil;` is found. Only then can the engine proceed with the next part of the expression.
Using lazy quantifiers, the regular expression engine will instead match _as few characters as possible_. The engine will match ` ` (a space), then look for `;` and will not find it. The match will then be expanded to ` =` and, again, a match of `;` is attempted. This continues until the match is ` = "name=evil` and the engine finds `;`. While lazy matching still includes some work, in this case, backtracking would require many more steps.
Lazy matching can have the inverse effect, though. Consider the following expression:
```python
"@rx (?i)\b(?:s(?:tyle|rc)|href)\b[\s\S]*?="
```
It matches some HTML attributes and then expects to see `=`. Using a somewhat contrived input, the lazy quantifier will require more steps to match then the greedy version would: `style                     =`. With the lazy quantifier, the regular expression engine will expand the match by one character for each of the space characters in the input, which means 21 steps in this case. With the greedy quantifier, the engine would match up to the end in a single step, backtrack one character and then match `=` (note that `=` is included in `[\s\S]`), which makes 3 steps.
To summarize: **be very mindful about when and why you use lazy quantifiers in your regular expressions**.
### Possessive Quantifiers and Atomic Groups
Lazy and greedy matching change the order in which a regular expression engine processes a regular expression. However, the order of execution does not influence the backtracking behavior of backtracking engines.
Possessive quantifiers (e.g., `x++`) and atomic groups (e.g., `(?>x)`) are tools that can be used to prevent a backtracking engine from backtracking. They _can_ be used for performance optimization but are only supported by backtracking engines and, therefore, are not permitted in CRS rules.
### Writing Regular Expressions for Non-Backtracking Compatibility
Traditional regular expression engines use backtracking to solve some additional problems, such as finding a string that is preceded or followed by another string. While this functionality can certainly come in handy and has its place in certain applications, it can also lead to performance issues and, in uncontrolled environments, open up possibilities for attacks (the term "[ReDoS](https://en.wikipedia.org/wiki/ReDoS)" is often used to describe an attack that exhausts process or system resources due to excessive backtracking).
The OWASP CRS tries to be compatible with non-backtracking regular expression engines, such as RE2, because:
- Non-backtracking engines are less vulnerable to ReDoS attacks.
- Non-backtracking engines can often outperform backtracking engines.
- CRS aims to leave the choice of the engine to the user/system.
To ensure compatibility with non-backtracking regular expression engines, the following operations are **not** permitted in regular expressions:
- positive lookahead (e.g., `(?=regex)`)
- negative lookahead (e.g., `(?!regex)`)
- positive lookbehind (e.g., `(?<=regex)`)
- negative lookbehind (e.g., `(?<!regex)`)
- named capture groups (e.g., `(?P<name>regex)`)
- backreferences (e.g., `\1`)
- named backreferences (e.g., `(?P=name)`)
- conditionals (e.g., `(?(regex)then|else)`)
- recursive calls to capture groups (e.g., `(?1)`)
- possessive quantifiers (e.g., `(?:regex)++`)
- atomic (or possessive) groups (e.g., `(?>regex`))
This list is not exhaustive but covers the most important points. The [RE2 documentation](https://github.com/google/re2/wiki/Syntax) includes a complete list of supported and unsupported features that various engines offer.
### When and How to Optimize Regular Expressions
Optimizing regular expressions is hard. Often, a change intended to improve the performance of a regular expression will change the original semantics by accident. In addition, optimizations usually make expressions harder to read. Consider the following example of URL schemes:
```python
mailto|mms|mumble|maven
```
An optimized version (produced by the [crs-toolchain]({{< ref "crs_toolchain" >}})) could look like this:
```python
m(?:a(?:ilto|ven)|umble|ms)
```
The above expression is an optimization because it reduces the number of backtracking steps when a branch fails. The regular expressions in the CRS are often comprised of lists of tens or even hundreds of words. Reading such an expression in an optimized form is difficult: even the _simple_ optimized example above is difficult to read.
In general, contributors should not try to optimize contributed regular expressions and should instead strive for clarity. New regular expressions will usually be required to be submitted as a `.ra` file for the [crs-toolchain]({{< ref "crs_toolchain" >}}) to process. In such a file, the regular expression is decomposed into individual parts, making manual optimizations much harder or even impossible (and unnecessary with the `crs-toolchain`). The `crs-toolchain` performs some common optimizations automatically, such as the one shown above.
Whether optimizations make sense in a contribution is assessed for each case individually.
## Rules Compliance with Paranoia Levels
The rules in CRS are organized into **paranoia levels** (PLs) which makes it possible to define how aggressive CRS is. See the documentation on [paranoia levels](https://coreruleset.org/docs/concepts/paranoia_levels/) for an introduction and more detailed explanation.
Each rule that is placed into a paranoia level must contain the tag `paranoia-level/N`, where *N* is the PL value, however this tag can only be added if the rule does **not** use the nolog action.
The types of rules that are allowed at each paranoia level are as follows:
**PL 0:**
* ModSecurity / WAF engine installed, but almost no rules
**PL 1:**
* Default level: keep in mind that most installations will normally use this level
* Any complex, memory consuming evaluation rules will surely belong to a higher level, not this one
* CRS will normally use atomic checks in single rules at this level
* Confirmed matches only; all scores are allowed
* No false positives / low false positives: try to avoid adding rules with potential false positives!
* False negatives could happen
**PL2:**
**PL 2:**
* Chains usage are OK
* [Chain](https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-%28v2.x%29#chain) usage is allowed
* Confirmed matches use score critical
* Matches that cause false positives are limited to use score notice or warning
* Low False positive rates
* Matches that cause false positives are limited to using scores notice or warning
* Low false positive rates
* False negatives are not desirable
**PL3:**
**PL 3:**
* Chains usage with complex regex look arounds and macro expansions
* Confirmed matches use score warning or critical
* Matches that cause false positives are limited to use score notice
* False positive rates increased but limited to multiple matches (not single string)
* Chain usage with complex regular expression look arounds and macro expansions are allowed
* Confirmed matches use scores warning or critical
* Matches that cause false positives are limited to using score notice
* False positive rates are higher but limited to multiple matches (not single strings)
* False negatives should be a very unlikely accident
**PL4:**
**PL 4:**
* Every item is inspected
* Variable creations allowed to avoid engine limitations
* Confirmed matches use score notice, warning or critical
* Matches that cause false positives are limited to use score notice and warning
* False positive rates increased (even on single string)
* False negatives should not happen here
* Check everything against RFC and white listed values for most popular elements
* Variable creations are allowed to avoid engine limitations
* Confirmed matches use scores notice, warning, or critical
* Matches that cause false positives are limited to using scores notice or warning
* False positive rates are higher (even on single strings)
* False negatives should not happen at this level
* Check everything against RFCs and allow listed values for the most popular elements
## ID Numbering Scheme
The CRS project used the numerical id rule namespace from 900,000 to 999,999 for the CRS rules as well as 9,000,000 to 9,999,999 for default CRS rule exclusion packages.
The CRS project uses the numerical ID rule namespace from 900,000 to 999,999 for CRS rules, as well as 9,000,000 to 9,999,999 for default CRS rule exclusion packages and plugins.
Rules applying to the incoming request use the id range 900,000 to 949,999.
Rules applying to the outgoing response use the id range 950,000 to 999,999.
- Rules applying to the **incoming request** use the ID range 900,000 to 949,999.
- Rules applying to the **outgoing response** use the ID range 950,000 to 999,999.
The rules are grouped by vulnerability class they address (SQLi, RCE, etc.) or functionality (initialization). These groups occupy blocks of thousands (e.g. SQLi: 942,000 - 942,999).
The grouped rules are defined in files dedicated to a single group or functionality. The filename takes up the first three digits of the rule ids defined within the file (e.g. SQLi: REQUEST-942-APPLICATION-ATTACK-SQLI.conf).
The rules are grouped by the vulnerability class they address (SQLi, RCE, etc.) or the functionality they provide (e.g., initialization). These groups occupy blocks of thousands (e.g., SQLi: 942,000 - 942,999). These grouped rules are defined in files dedicated to a single group or functionality. The filename takes up the first three digits of the rule IDs defined within the file (e.g., SQLi: `REQUEST-942-APPLICATION-ATTACK-SQLI.conf`).
The individual rule files for the vulnerability classes are organized by the paranoia level of the rules. PL 1 is first, then PL 2 etc.
The individual rules within each file for a vulnerability class are organized by the paranoia level of the rules. PL 1 is first, then PL 2, etc.
The block from 9XX000 - 9XX099 is reserved for use by CRS helper functionality. There are no blocking or filtering rules in this block.
The ID block 9xx000 - 9xx099 is reserved for use by CRS helper functionality. There are no blocking or filtering rules in this block.
Among the rules serving a CRS helper functionality are rules that skip rules depending on the paranoia level. These rules always use the following reserved rule ids: 9XX011-9XX018 with very few exceptions.
Among the rules providing CRS helper functionality are rules that skip other rules depending on the paranoia level. These rules always use the following reserved rule IDs: 9xx011 - 9xx018, with very few exceptions.
The blocking or filter rules start with 9XX100 with a step width of 10. E.g. 9XX100, 9XX110, 9XX120 etc. The rule id does not correspond directly with the paranoia level of a rule. Given the size of a rule group and the organization by lower PL rules first, PL2 and above tend to have rule IDs with higher numbers.
The blocking and filter rules start at 9xx100 with a step width of 10, e.g., 9xx100, 9xx110, 9xx120, etc.
Within a rule file / block, there are sometimes smaller groups of rules that belong to together. They are closely linked and very often represent copies of the original rules with a stricter limit (alternatively, they can represent the same rule addressing a different target in a second rule where this was necessary). These are stricter siblings of the base rule. Stricter siblings usually share the first five digits of the rule ID and raise the rule ID by one. E.g., Base rule at 9XX160, stricter sibling at 9XX161.
The ID of a rule does not correspond directly with its paranoia level. Given the size of rule groups and how they're organized by paranoia level (starting with the lower PL rules first), PL 2 and above tend to be composed of rules with higher ID numbers.
Stricter siblings often have a different paranoia level. This means that the base rule and the stricter sibling do not reside next to one another in the rule file. Instead they are ordered in their appropriate paranoia level and can be linked via the first digits of the rule id. It is a good practice to introduce stricter siblings together with the base rule in the comments of the base rule and to reference the base rule with the keyword stricter sibling in the comments of the stricter sibling. E.g., "... This is
performed in two separate stricter siblings of this rule: 9XXXX1 and 9XXXX2", "This is a stricter sibling of rule 9XXXX0."
### Stricter Siblings
Within a rule file / block, there are sometimes smaller groups of rules that belong together. They're closely linked and very often represent copies of the original rules with a stricter limit (alternatively, they can represent the same rule addressing a different *target* in a second rule, where this is necessary). These are **stricter siblings** of the base rule. Stricter siblings usually share the first five digits of the rule ID and raise the rule ID by one, e.g., a base rule at 9xx160 and a stricter sibling at 9xx161.
Stricter siblings often have different paranoia levels. This means that the base rule and the stricter siblings don't usually reside next to each another in the rule file. Instead, they're ordered by paranoia level and are linked by the first digits of their rule IDs. It's good practice to introduce all stricter siblings together as part of the definition of the base rule: this can be done in the comments of the base rule. It's also good practice to refer back to the base rule with the keywords "stricter sibling" in the comments of the stricter siblings themselves. For example: "...This is performed in two separate stricter siblings of this rule: 9xxxx1 and 9xxxx2", and "This is a stricter sibling of rule 9xxxx0."
## Writing Tests
Each rule should be accompanied by tests. Rule tests are an invaluable way to check that a rule behaves as expected:
- Does the rule correctly match against the payloads and behaviors that the rule is designed to detect? (**Positive tests**)
- Does the rule correctly **not** match against legitimate requests, i.e., the rule doesn't cause obvious false positives? (**Negative tests**)
Rule tests also provide an excellent way to test WAF engines and implementations to ensure they behave and execute CRS rules as expected.
The rule tests are located under `tests/regression/tests`. Each CRS rule *file* has a corresponding *directory* and each individual *rule* has a corresponding *YAML file* containing all the tests for that rule. For example, the tests for rule 911100 *(Method is not allowed by policy)* are in the file `REQUEST-911-METHOD-ENFORCEMENT/911100.yaml`.
Full documentation of the required formatting and available options of the YAML tests can be found at https://github.com/coreruleset/ftw/blob/main/docs/YAMLFormat.md.
Documentation on how to run the CRS test suite can be found in the [online documentation](https://coreruleset.org/docs/development/testing/).
### Positive Tests
Example of a simple *positive test*:
```yaml
- test_title: 932230-26
desc: "Unix command injection"
stages:
- stage:
input:
dest_addr: 127.0.0.1
headers:
Host: localhost
User-Agent: "OWASP CRS test agent"
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
method: POST
port: 80
uri: "/post"
data: "var=` /bin/cat /etc/passwd`"
version: HTTP/1.1
output:
log_contains: id "932230"
```
This test will succeed if the log output contains `id "932230"`, which would indicate that the rule in question matched and generated an alert.
It's important that tests consistently include the HTTP header fields `Host`, `User-Agent`, and `Accept`. CRS includes rules that detect if these headers are missing or empty, so these headers should be included in each test to avoid unnecessarily causing those rules to match. Ideally, *each positive test should cause* **only** *the rule in question to match*.
The rule's description field, `desc`, is important. It should describe what is being tested: what *should* match, what should *not* match, etc.
### Negative Tests
Example of a simple *negative test*:
```yaml
- test_title: 932260-4
stages:
- stage:
input:
dest_addr: "127.0.0.1"
method: "POST"
port: 80
headers:
User-Agent: "OWASP CRS test agent"
Host: "localhost"
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
data: 'foo=ping pong tables'
uri: '/post'
output:
no_log_contains: id "932260"
```
This test will succeed if the log output does **not** contain `id "932260"`, which would indicate that the rule in question did **not** match and so did **not** generate an alert.
### Encoded and Raw Requests
It is possible to *encode* an entire test request. This encapsulates the request and means that the request headers and payload don't need to be explicitly declared. This is useful when a test request needs to use unusual bytes which might break YAML parsers, or when a test request must be intentionally malformed in a way that is impossible to describe otherwise. An encoded request is sent exactly as intended.
The `encoded_request` field works like so:
```yaml
encoded_request: <Base64 string>
```
For example:
```yaml
encoded_request: "R0VUIFwgSFRUUA0KDQoK"
```
where `R0VUIFwgSFRUUA0KDQoK` is the base64-encoded equivalent of `GET \ HTTP\r\n\r\n`.
The older method of using `raw_request` is deprecated as it's difficult to maintain and less portable than `encoded_request`.
### Using The Correct HTTP Endpoint
The CRS project uses [kennthreitz/httpbin](https://hub.docker.com/r/kennethreitz/httpbin) as the backend server for tests. This backend provides one dedicated endpoint for each HTTP method. Tests should target these endpoints to:
- improve test throughput (prevent HTML from being returned by the backend)
- add automatic HTTP method verification (the backend will respond with status code `405` (method not allowed) to requests whose method does not match the endpoint)
Test URIs should be structured as follows, where `<method>` must be replaced by the name of the HTTP method the test uses:
```yaml
#...
method: <method>
uri: /<method>/some/arbitrary/url
#...
```
## Further Guidance on Rule Writing
### Leaving Audit Log Configuration Unchanged
Former versions of CRS dynamically included the HTTP response body in the audit log via special `ctl` statements on certain individual response rules. This was never applied in a systematic way and, regardless, CRS should not change the format of the audit log by itself, namely because this can lead to information leakages. Therefore, the use of `ctl:auditLogParts=+E` or any other form of `ctl:auditLogParts` is not allowed in CRS rules.
## Non-Rules General Guidelines
* Remove trailing spaces from files (if they're not needed). This will make linters happy.
* EOF should have an EOL.
The `pre-commit` framework can be used to check for and fix these issues automatically. First, go to the [pre-commit](https://pre-commit.com/) website and download the framework. Then, after installing, use the command `pre-commit install` so that the tools are installed and run each time a commit is made. CRS provides a config file that will keep the repository clean.

View file

@ -13,8 +13,11 @@
- [Christoph Hansen](https://github.com/emphazer)
- [Ervin Hegedus](https://github.com/airween)
- [Andrew Howe](https://github.com/RedXanadu)
- [Karel Knibbe](https://github.com/karelorigin)
- [Max Leske](https://github.com/theseion)
- [Andrea Menin](https://github.com/theMiddleBlue)
- [Matteo Pace](https://github.com/M4tteoP)
- [Jitendra Patro](https://github.com/Xhoenix)
- [Chaim Sanders](https://github.com/csanders-git)
- [Federico G. Schwindt](https://github.com/fgsch)
- [Manuel Leos Rivas](https://github.com/spartantri)
@ -33,6 +36,7 @@
- [Peter Bittner](https://github.com/bittner)
- [Allan Boll](https://github.com/allanbomsft)
- [Jeremy Brown](https://github.com/jwbrown77)
- [Esad Cetiner](https://github.com/esadcetiner/)
- [Brent Clark](https://github.com/brentclark)
- [Jonathan Claudius](https://github.com/claudijd)
- [coolt](https://github.com/coolt)
@ -50,7 +54,6 @@
- [Pásztor Gábor](https://github.com/gpasztor87)
- [Jan Gora](https://github.com/terjanq)
- [Aaron Haaf](https://github.com/Everspace)
- [Karel Knibbe](https://github.com/karelorigin)
- [Michael Haas](https://github.com/MichaelHaas)
- [henkworks](https://github.com/henkworks)
- [Tim Herren](https://github.com/nerrehmit)
@ -111,3 +114,30 @@
- Josh Zlatin
- [Zou Guangxian](https://github.com/zouguangxian)
- [4ft35t](https://github.com/4ft35t)
- [Andy Clapson](https://github.com/Homesteady)
- [Anuraag Agrawal](https://github.com/anuraaga)
- [Christian Aistleitner](https://github.com/somechris)
- [Dennis Brown](https://github.com/MutableLoss)
- [Dexter Chang](https://github.com/dextermallo)
- [Esa Jokinen](https://github.com/oh2fih)
- [Finn Westendorf](https://github.com/wfinn)
- [Gwendal Le Coguic](https://github.com/gwen001)
- [Jean-François Viguier](https://github.com/jf-viguier)
- [Juan Pablo Tosso](https://github.com/jptosso)
- [Karel](https://github.com/karelorigin)
- [Khiem Doan](https://github.com/khiemdoan)
- [Mark Zeman](https://github.com/KramNamez)
- [Priyam Patel](https://github.com/priyam001)
- [Robert DeBoer](https://github.com/robertdeboer)
- [Somdev Sangwan](https://github.com/s0md3v)
- [Stephen Sigwart](https://github.com/ssigwart)
- [Zerorigin](https://github.com/Zerorigin)
- [Syin Wu](https://github.com/bxlxx)
- [henkdswiss](https://github.com/henkworks)
- [ignatiev](https://github.com/ignatiev)
- [oct0pus7](https://github.com/oct0pus7)
- [Timo](https://github.com/ntimo)
- [rekter0](https://github.com/rekter0)
- [ThanhPT](https://github.com/thanhpt1708)
- [Vandan Rohatgi](https://github.com/vandanrohatgi)
- [NiceYouKnow](https://github.com/NiceYouKnow)

View file

@ -1,305 +0,0 @@
_____ _____ _____ ____
/ ____| __ \ / ____| |___ \
| | | |__) | (___ __) |
| | | _ / \___ \ |__ <
| |____| | \ \ ____) | ___) |
\_____|_| \_\_____/ |____/
OWASP Core Rule Set 3.x
Installing ModSecurity
=====================
This document does NOT detail how to install ModSecurity. Rather,
only information pertaining to the installation of the OWASP Core
Rule Set (CRS) is provided. However, ModSecurity is a prerequisite
for the CRS installation. Information on installing ModSecurity
can be found within the ModSecurity project at
https://github.com/SpiderLabs/ModSecurity or at ModSecurity.org.
Installing From a Package Manager
=================================
The OWASP Core Rule Set (CRS) is available from many sources. On
multiple platforms this includes package managers. These packages are
maintained by independent packagers who package CRS in their own time.
Historically, many of these packages have been out of date. As such,
it is recommended that you install, where possible, from our GitHub
repository. The following CRS 3.x packages are known to exist:
modsecurity-crs - Debian
mod_security_crs - Fedora
modsecurity-crs - Gentoo
Packages of CRS 2.x are incompatible with CRS 3.x.
Installing
==========
You can download a copy of the CRS from the following URL:
https://coreruleset.org/installation/
Our release zip/tar.gz files are the preferred way to install CRS.
However, if you want to follow rule development closely and get
the newest protections quickly, you can also clone our GitHub
repository to get the current work-in-progress for the next release.
Prerequisites
-------------
CRS is designed to be used with ModSecurity (although many other
projects also use the provided rules). CRS version 3.x is designed for
ModSecurity 2.8 or above. CRS version 3.x makes use of libinjection
and libXML2. Failure to provide these prerequisites may result in
serious false negatives and CRS version 3.x should NOT be run without
these. Note, however, that libinjection is bundled with ModSecurity
since version 2.8. Additionally, if you are downloading from the
GitHub repo you will need to install 'git' on your system.
Upgrading from CRS 2.x
----------------------
CRS 3.x is a major release incompatible with CRS 2.x.
The rule IDs have changed. The file id_renumbering/IdNumbering.csv
contains a list with old and new rule IDs. However, a key feature
of the release 3.x is the reduction of false positives in the
default installation and we recommend you start with a fresh
install from scratch.
Key parameter variables have changed their name and new features
have been introduced. Your former modsecurity_crs_10_setup.conf
file is thus no longer usable.
We recommend you to start with a fresh install from scratch.
Installing on Apache
--------------------
1. Install ModSecurity for Apache
2. Ensure that ModSecurity is loading correctly by checking error.log
at start up for lines indicating ModSecurity is installed. An example
might appear as follows:
```ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/) configured.```
3. The most common method of deploying ModSecurity we have seen is
to create a new folder underneath the Apache directory (typically
/usr/local/apache/, /etc/httpd/, or /etc/apache2). Often this folder
is called 'modsecurity.d'. Create this folder and cd into it.
4. Download our release from https://coreruleset.org/installation/
and unpack it into a new owasp-modsecurity-crs folder.
5. Move the crs-setup.conf.example file to crs-setup.conf.
Please take the time to go through this file and customize the settings
for your local environment. Failure to do so may result in false
negatives and false positives. See the section entitled OWASP CRS
Configuration for more detail.
6. Rename rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example and
rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example to remove the
'.example' extension. This will allow you to add exclusions without updates
overwriting them in the future.
7. Add the following line to your httpd.conf/apache2.conf (the following
assumes you've put CRS into modsecurity.d/owasp-modsecurity-crs). You
can alternatively place these in any config file included by Apache:
```
<IfModule security2_module>
Include modsecurity.d/owasp-modsecurity-crs/crs-setup.conf
Include modsecurity.d/owasp-modsecurity-crs/rules/*.conf
</IfModule>
```
8. Restart web server and ensure it starts without errors
9. Make sure your web sites are still running fine.
10. Proceed to the section "Testing the Installation" below.
Installing on Nginx
-------------------
1. Compile ModSecurity into Nginx
2. Ensure that ModSecurity is loading correctly by checking error.log
at start up for lines indicating ModSecurity is installed. An example
might appear as follows:
```ModSecurity for nginx (STABLE)/2.9.1 (http://www.modsecurity.org/) configured.```
3. The most common method of deploying ModSecurity we have seen is
to create a new folder underneath the Nginx directory (typically
/usr/local/nginx/conf/). Often this folder
is called 'owasp-modsecurity-crs'. Create this folder and cd into it.
4. Download our release from https://coreruleset.org/installation/
and unpack it into a new owasp-modsecurity-crs folder.
5. Move the crs-setup.conf.example file to crs-setup.conf.
Please take this time to go through this
file and customize the settings for your local environment. Failure to
do so may result in false negatives and false positives. See the
section entitled OWASP CRS Configuration for more detail.
6. Rename rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example and
rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example to remove the
'.example' extension. This will allow you to add exceptions without updates
overwriting them in the future.
7. Nginx requires the configuration of a single ModSecurity
configuration file within the nginx.conf file using the
'ModSecurityConfig' directive (when using ModSecurity 2.x).
Best practice is to set 'ModSecurityConfig' to a file from
which you will include your other ModSecurity configuration
files. In this example we will use:
```ModSecurityConfig modsec_includes.conf;```
7. Within modsec_includes.conf create your includes to the
CRS folder similar to as follows (The modsecurity.conf file from the
ModSecurity installation is included in this example):
```
include modsecurity.conf
include owasp-modsecurity-crs/crs-setup.conf
include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9003-NEXTCLOUD-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9004-DOKUWIKI-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9005-CPANEL-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-903.9006-XENFORO-EXCLUSION-RULES.conf
include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf
include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
include owasp-modsecurity-crs/rules/REQUEST-934-APPLICATION-ATTACK-NODEJS.conf
include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
include owasp-modsecurity-crs/rules/REQUEST-944-APPLICATION-ATTACK-JAVA.conf
include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
```
8. Restart web server and ensure it starts without errors
9. Make sure your web sites are still running fine.
10. Proceed to the section "Testing the Installation" below.
Installing on IIS
-----------------
The IIS installer comes with an optional version of CRS built in.
To upgrade or install this after the fact follow the following
steps.
1. Navigate to "[drive_letters]:\Program Files\ModSecurity IIS\"
2. Download our release from https://coreruleset.org/installation/
and unpack it into the current folder.
3. Move the crs-setup.conf.example file to crs-setup.conf.
Please take this time to go through this
file and customize the settings for your local environment. Failure to
do so may result in false negatives and false positives. See the
section entitled OWASP CRS Configuration for more detail.
4. Rename rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example and
rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example to remove the
'.example' extension. This will allow you to add exceptions without updates
overwriting them in the future.
5. Navigate back to the 'ModSecurity IIS' folder and modify the
'modsecurity_iis' to include the following:
```
include owasp-modsecurity-crs/crs-setup.conf
include owasp-modsecurity-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
include owasp-modsecurity-crs/rules/REQUEST-901-INITIALIZATION.conf
include owasp-modsecurity-crs/rules/REQUEST-905-COMMON-EXCEPTIONS.conf
include owasp-modsecurity-crs/rules/REQUEST-910-IP-REPUTATION.conf
include owasp-modsecurity-crs/rules/REQUEST-911-METHOD-ENFORCEMENT.conf
include owasp-modsecurity-crs/rules/REQUEST-912-DOS-PROTECTION.conf
include owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf
include owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf
include owasp-modsecurity-crs/rules/REQUEST-921-PROTOCOL-ATTACK.conf
include owasp-modsecurity-crs/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf
include owasp-modsecurity-crs/rules/REQUEST-931-APPLICATION-ATTACK-RFI.conf
include owasp-modsecurity-crs/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf
include owasp-modsecurity-crs/rules/REQUEST-933-APPLICATION-ATTACK-PHP.conf
include owasp-modsecurity-crs/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf
include owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
include owasp-modsecurity-crs/rules/REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
include owasp-modsecurity-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-950-DATA-LEAKAGES.conf
include owasp-modsecurity-crs/rules/RESPONSE-951-DATA-LEAKAGES-SQL.conf
include owasp-modsecurity-crs/rules/RESPONSE-952-DATA-LEAKAGES-JAVA.conf
include owasp-modsecurity-crs/rules/RESPONSE-953-DATA-LEAKAGES-PHP.conf
include owasp-modsecurity-crs/rules/RESPONSE-954-DATA-LEAKAGES-IIS.conf
include owasp-modsecurity-crs/rules/RESPONSE-959-BLOCKING-EVALUATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf
include owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
```
6. Restart web server and ensure it starts without errors
7. Make sure your web sites are still running fine.
8. Proceed to the section "Testing the Installation" below.
Testing the Installation
========================
To test your installation you should be able to use any number
of attacks. A typical request which should trigger CRS would be
```http://localhost/?param="><script>alert(1);</script>```
Upon sending this request you should see events reported in the
error log (nginx apache) or the event viewer (IIS).
If have not changed the defaults with regards to anomaly scoring,
blocking and sampling percentage, then this request should have
been blocked and access forbidden. Likewise if you have configured
ModSecurity debug logging and/or audit logging this event should
log to these locations as well.
OWASP CRS Configuration
=======================
The crs-setup.conf file includes management rules
and directives that can control important CRS functions.
The crs-setup.conf file comes with extensive comments.
This section here brings only the essential parts.
By default we do not include settings within the crs-setup.conf
that configure ModSecurity itself. Instead those configuration
settings are set during the installation of ModSecurity proper.
An example for such such a
configuration file is available via the ModSecurity project
(https://github.com/SpiderLabs/ModSecurity/blob/master/modsecurity.conf-recommended).
Be aware the crs-setup.conf file DOES specify
configuration directives such as SecDefaultAction. The default
is the anomaly scoring mode with the appropriate
SecDefaultAction as defined in the crs-setup.conf.
Alternative configuration modes are supported and explained
in crs-setup.conf.
The default anomaly/correlation mode establishes an incoming
anomaly score threshold of 5 and an outgoing anomaly score
threshold of 4. The default installation has been tuned to
reduce false positives in a way that will allow most requests
to pass in this default setup.
However, testing the setup and tuning false positives
before going to production is vital. This is especially true
if you raise the paranoia level with is set to 1 by default.
Higher paranoia levels ranging from 2 to 4 include more
aggressive rules which will raise additional false positives
but also raise the security level of your service.
If you are unsure about the performance impact of the CRS
or if you are unsure about the number of false positives, then
you may want to use the sampling percentage. This number,
which is set to 100 by default, controls the percentage
of requests which is funneled into the CRS. Fresh installs
on high traffic sites are advised to start with a low, or
very low number of percentages and raise the number
slowly up to 100. Be aware that any number below 100 allows
a random number of requests to bypass the ruleset completely.
Update the TX policy settings for allowed Request Methods, File
Extensions, maximum numbers of arguments, etc to better reflect
your environment that is being protected.
Make sure your GeoIP and Project Honeypot settings are specified
if you are using them.
The GeoIP database is no longer included with the CRS. Instead
you are advised to download it regularly.
The use of Project Honeypot requires a
free API key. These require an account but can be obtained at
https://www.projecthoneypot.org/httpbl_configure.php.
Be sure to check out the other settings present within the
crs-setup.conf file. There are many other options that have to
do with aspects of web application security that are beyond
this document but are well explained in crs-setup.conf.

View file

@ -0,0 +1,185 @@
# Installing CRS
This guide aims to get a CRS installation up and running. This guide assumes that a compatible ModSecurity engine is already present and working. If unsure then refer to the [extended install](https://coreruleset.org/docs/deployment/extended_install/) page for full details.
## Downloading the Rule Set
The first step is to download the CRS itself. The CRS project strongly recommends using a [supported version](https://github.com/coreruleset/coreruleset/security/policy).
Official CRS releases can be found at the following URL: https://github.com/coreruleset/coreruleset/releases.
For *production* environments, it is recommended to use the latest release, which is v4.0.0. For *testing* the bleeding edge CRS version, nightly releases are also provided.
### Verifying Releases
{{% notice note %}}
Releases are signed using the CRS project's [GPG key](https://coreruleset.org/security.asc) (fingerprint: 3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72). Releases can be verified using GPG/PGP compatible tooling.
To retrieve the CRS project's public key from public key servers using `gpg`, execute: `gpg --keyserver pgp.mit.edu --recv 0x38EEACA1AB8A6E72` (this ID should be equal to the last sixteen hex characters in the fingerprint).
It is also possible to use `gpg --fetch-key https://coreruleset.org/security.asc` to retrieve the key directly.
{{% /notice %}}
The following steps assume that a \*nix operating system is being used. Installation is similar on Windows but likely involves using a zip file from the CRS [releases page](https://github.com/coreruleset/coreruleset/releases).
To download the release file and the corresponding signature:
```bash
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.0.0.tar.gz
wget https://github.com/coreruleset/coreruleset/releases/download/v4.0.0/coreruleset-4.0.0.tar.gz.asc
```
To verify the integrity of the release:
```bash
gpg --verify coreruleset-4.0.0.tar.gz.asc v4.0.0.tar.gz
gpg: Signature made Wed Jun 30 10:05:48 2021 -03
gpg: using RSA key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg: Good signature from "OWASP Core Rule Set <security@coreruleset.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72
```
If the signature was good then the verification succeeds. If a warning is displayed, like the above, it means the CRS project's public key is *known* but is not *trusted*.
To trust the CRS project's public key:
```bash
gpg --edit-key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg> trust
Your decision: 5 (ultimate trust)
Are you sure: Yes
gpg> quit
```
The result when verifying a release will then look like so:
```bash
gpg --verify coreruleset-4.0.0.tar.gz.asc v4.0.0.tar.gz
gpg: Signature made Wed Jun 30 15:05:48 2021 CEST
gpg: using RSA key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg: Good signature from "OWASP Core Rule Set <security@coreruleset.org>" [ultimate]
```
## Installing the Rule Set
### Extracting the Files
Once the rule set has been downloaded and verified, extract the rule set files to a well known location on the server. This will typically be somewhere in the web server directory.
The examples presented below demonstrate using Apache. For information on configuring Nginx or IIS see the [extended install](https://coreruleset.org/docs/deployment/extended_install/) page.
Note that while it's common practice to make a new `modsecurity.d` folder, as outlined below, this isn't strictly necessary. The path scheme outlined is common on RHEL-based operating systems; the Apache path used may need to be adjusted to match the server's installation.
```bash
mkdir /etc/crs4
tar -xzvf v4.0.0.tar.gz --strip-components 1 -C /etc/crs4
```
Now all the CRS files will be located below the `/etc/crs4` directory.
### Setting Up the Main Configuration File
After extracting the rule set files, the next step is to set up the main OWASP CRS configuration file. An example configuration file is provided as part of the release package, located in the main directory: `crs-setup.conf.example`.
{{% notice note %}}
Other aspects of ModSecurity, particularly engine-specific parameters, are controlled by the ModSecurity "recommended" configuration rules, `modsecurity.conf-recommended`. This file comes packaged with ModSecurity itself.
{{% /notice %}}
In many scenarios, the default example CRS configuration will be a good enough starting point. It is, however, a good idea to take the time to look through the example configuration file *before* deploying it to make sure it's right for a given environment.
Once any settings have been changed within the example configuration file, as needed, it should be renamed to remove the .example portion, like so:
```bash
cd /etc/crs4
mv crs-setup.conf.example crs-setup.conf
```
### Include-ing the Rule Files
The last step is to tell the web server where the rules are. This is achieved by `include`-ing the rule configuration files in the `httpd.conf` file. Again, this example demonstrates using Apache, but the process is similar on other systems (see the [extended install](https://coreruleset.org/docs/deployment/extended_install/) page for details).
```bash
echo 'IncludeOptional /etc/crs4/crs-setup.conf' >> /etc/httpd/conf/httpd.conf
echo 'IncludeOptional /etc/crs4/plugins/*-config.conf' >> /etc/httpd/conf/httpd.conf
echo 'IncludeOptional /etc/crs4/plugins/*-before.conf' >> /etc/httpd/conf/httpd.conf
echo 'IncludeOptional /etc/crs4/rules/*.conf' >> /etc/httpd/conf/httpd.conf
echo 'IncludeOptional /etc/crs4/plugins/*-after.conf' >> /etc/httpd/conf/httpd.conf
```
Now that everything has been configured, it should be possible to restart and being using the OWASP CRS. The CRS rules typically require a bit of tuning with rule exclusions, depending on the site and web applications in question. For more information on tuning, see [false positives and tuning](https://coreruleset.org/docs/concepts/false_positives_tuning/).
```bash
systemctl restart httpd.service
```
## Alternative: Using Containers
Another quick option is to use the official CRS [pre-packaged containers](https://coreruleset.org/docs/development/useful_tools/#official-crs-maintained-docker-images). Docker, Podman, or any compatible container engine can be used. The official CRS images are published in the Docker Hub. The image most often deployed is `owasp/modsecurity-crs`: it already has everything needed to get up and running quickly.
The CRS project pre-packages both Apache and Nginx web servers along with the appropriate corresponding ModSecurity engine. More engines, like [Coraza](https://coraza.io/), will be added at a later date.
To protect a running web server, all that's required is to get the appropriate image and set its configuration variables to make the WAF receives requests and proxies them to your backend server.
Below is an example `docker-compose` file that can be used to pull the container images. All that needs to be changed is the `BACKEND` variable so that the WAF points to the backend server in question:
```docker-compose
services:
modsec2-apache:
container_name: modsec2-apache
image: owasp/modsecurity-crs:apache
environment:
SERVERNAME: modsec2-apache
BACKEND: http://<backend server>
PORT: "80"
MODSEC_RULE_ENGINE: DetectionOnly
BLOCKING_PARANOIA: 2
TZ: "${TZ}"
ERRORLOG: "/var/log/error.log"
ACCESSLOG: "/var/log/access.log"
MODSEC_AUDIT_LOG_FORMAT: Native
MODSEC_AUDIT_LOG_TYPE: Serial
MODSEC_AUDIT_LOG: "/var/log/modsec_audit.log"
MODSEC_TMP_DIR: "/tmp"
MODSEC_RESP_BODY_ACCESS: "On"
MODSEC_RESP_BODY_MIMETYPE: "text/plain text/html text/xml application/json"
COMBINED_FILE_SIZES: "65535"
volumes:
ports:
- "80:80"
```
That's all that needs to be done. Simply starting the container described above will instantly provide the protection of the latest stable CRS release in front of a given backend server or service. There are [lots of additional variables](https://github.com/coreruleset/modsecurity-crs-docker) that can be used to configure the container image and its behavior, so be sure to read the full documentation.
## Verifying that the CRS is active
Always verify that CRS is installed correctly by sending a 'malicious' request to your site or application, for instance:
```bash
curl 'https://www.example.com/?foo=/etc/passwd&bar=/bin/sh'
```
Depending on your configurated thresholds, this should be detected as a malicious request. If you use blocking mode, you should receive an Error 403. The request should also be logged to the audit log, which is usually in `/var/log/modsec_audit.log`.
## Upgrading
### Upgrading from CRS 3.x to CRS 4
The most impactful change is the removal of application exclusion packages in favor of a plugin system. If you had activated the exclusion packages in CRS 3, you should download the plugins for them and place them in the plugins subdirectory. We maintain the list of plugins in our [Plugin Registry](https://github.com/coreruleset/plugin-registry). You can find detailed information on working with plugins in our [plugins documentation]()https://coreruleset.org/docs/concepts/plugins/.
In terms of changes to the detection rules, the amount of changes is smaller than in the CRS 2—3 changeover. Most rules have only evolved slightly, so it is recommended that you keep any existing custom exclusions that you have made under CRS 3.
We recommend to start over by copying our `crs-setup.conf.example` to `crs-setup.conf` with a copy of your old file at hand, and re-do the customizations that you had under CRS 3.
Please note that we added a large number of new detections, and any new detection brings a certain risk of false alarms. Therefore, we recommend to test first before going live.
### Upgrading from CRS 2.x to CRS 3
In general, you can update by unzipping our new release over your older one, and updating the `crs-setup.conf` file with any new settings. However, CRS 3.0 is a major rewrite, incompatible with CRS 2.x. Key setup variables have changed their name, and new features have been introduced. Your former modsecurity_crs_10_setup.conf file is thus no longer usable. We recommend you to start with a fresh crs-setup.conf file from scratch.
Most rule IDs have been changed to reorganize them into logical sections. This means that if you have written custom configuration with exclusion rules (e.g. `SecRuleRemoveById`, `SecRuleRemoveTargetById`, `ctl:ruleRemoveById` or `ctl:ruleRemoveTargetById`) you must renumber the rule numbers in that configuration. You can do this using the supplied utility util/id_renumbering/update.py or find the changes in util/id_renumbering/IdNumbering.csv.
However, a key feature of the CRS 3 is the reduction of false positives in the default installation, and many of your old exclusion rules may no longer be necessary. Therefore, it is a good option to start fresh without your old exclusion rules.
If you are experienced in writing exclusion rules for CRS 2.x, it may be worthwhile to try running CRS 3 in Paranoia Level 2 (PL2). This is a stricter mode, which blocks additional attack patterns, but brings a higher number of false positives — in many situations the false positives will be comparable with CRS 2.x. This paranoia level however will bring you a higher protection level than CRS 2.x or a CRS 3 default install, so it can be worth the investment.

View file

@ -1,9 +1,10 @@
== OWASP ModSecurity Core Rule Set (CRS) KNOWN BUGS ==
# CRS KNOWN BUGS
== Report Bugs/Issues to GitHub Issues Tracker or the mailinglist ==
* https://github.com/SpiderLabs/owasp-modsecurity-crs/issues
## Report Bugs/Issues to GitHub Issues Tracker or the mailinglist
* https://github.com/coreruleset/coreruleset/issues
or the CRS Google Group at
* https://groups.google.com/a/owasp.org/forum/#!forum/modsecurity-core-rule-set-project
* https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project
* There are still false positives for standard web applications in
the default install (paranoia level 1). Please report these when
@ -26,7 +27,7 @@ or the CRS Google Group at
We advise to upgrade your Apache version. If upgrading is not possible,
we have provided a script in the util/join-multiline-rules directory
which converts the rules into a format that works around the bug.
You have to re-run this script whenever you modify or update
You have to re-run this script whenever you modify or update
the CRS rules.
* Debian up to and including Jessie lacks YAJL/JSON support in ModSecurity,
which causes the following error in the Apache ErrorLog or SecAuditLog:
@ -38,13 +39,11 @@ or the CRS Google Group at
type by default, as specified in RFC 3902. OF IMPORTANCE, application/soap+xml is
indicative that XML will be provided. In accordance with this, ModSecurity's XML
Request Body Processor should also be configured to support this MIME type. Within
the ModSecurity project, commit 5e4e2af
(https://github.com/SpiderLabs/ModSecurity/commit/5e4e2af7a6f07854fee6ed36ef4a381d4e03960e)
the ModSecurity project, [commit 5e4e2af](https://github.com/owasp-modsecurity/ModSecurity/commit/5e4e2af7a6f07854fee6ed36ef4a381d4e03960e)
has been merged to support this endeavour. However, if you are running a modified or
preexisting version of the modsecurity.conf provided by this repository, you may
wish to upgrade rule '200000' accordingly. The rule now appears as follows:
```
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
```
```
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
"id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
```

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2006 the OWASP Core Rule Set contributors
Copyright 2024 OWASP CRS project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -1,34 +1,33 @@
![GHA build main](https://github.com/coreruleset/coreruleset/workflows/Regression%20Tests/badge.svg?branch=main)</br>
![GHA build v4.0/dev](https://github.com/coreruleset/coreruleset/workflows/Regression%20Tests/badge.svg?branch=v4.0%2Fdev)
![GHA build v3.3/dev](https://github.com/coreruleset/coreruleset/workflows/Regression%20Tests/badge.svg?branch=v3.3%2Fdev)
![GHA build v3.2/dev](https://github.com/coreruleset/coreruleset/workflows/Regression%20Tests/badge.svg?branch=v3.2%2Fdev)
![GHA build v3.1/dev](https://github.com/coreruleset/coreruleset/workflows/Regression%20Tests/badge.svg?branch=v3.1%2Fdev)
[![OWASP Flagship](https://img.shields.io/badge/owasp-flagship%20project-38a047.svg)](https://owasp.org/projects/)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1390/badge)](https://bestpractices.coreinfrastructure.org/projects/1390)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
# OWASP ModSecurity Core Rule Set (CRS)
# OWASP CRS
The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. The CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts.
The OWASP CRS is a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. The CRS aims to protect web applications from a wide range of attacks, including the OWASP Top Ten, with a minimum of false alerts.
## CRS Resources
Please see the [OWASP ModSecurity Core Rule Set page](https://coreruleset.org/) to get introduced to the CRS and view resources on installation, configuration, and working with the CRS.
Please see the [OWASP CRS page](https://coreruleset.org/) to get introduced to the CRS and view resources on installation, configuration, and working with the CRS.
## Contributing to the CRS
We strive to make the OWASP ModSecurity CRS accessible to a wide audience of beginner and experienced users. We are interested in hearing any bug reports, false positive alert reports, evasions, usability issues, and suggestions for new detections.
We strive to make the OWASP ModSecurity CRS accessible to a wide audience of beginner and experienced users. We are interested in hearing any bug reports, false-positive alert reports, evasions, usability issues, and suggestions for new detections.
[Create an issue on GitHub](https://github.com/coreruleset/coreruleset/issues) to report a false positive or false negative (evasion). Please include your installed version and the relevant portions of your ModSecurity audit log.
[Create an issue on GitHub](https://github.com/coreruleset/coreruleset/issues) to report a false positive or false negative (evasion). Please include your installed version and the relevant portions of your ModSecurity audit log. We will try and address your issue and potentially ask for additional information to reproduce your problem. Please also note that stale issues will be flagged and closed after 120 days. You can search for stale issues with the following [search query](https://github.com/coreruleset/coreruleset/issues?q=label%3A%22Stale+issue%22).
[Sign up for our Google Group](https://groups.google.com/a/owasp.org/forum/#!forum/modsecurity-core-rule-set-project) to ask general usage questions and participate in discussions on the CRS. Also [here](https://lists.owasp.org/pipermail/owasp-modsecurity-core-rule-set/index) you can find the archives for the previous mailing list.
[Sign up for our Google Group](https://groups.google.com/a/owasp.org/g/modsecurity-core-rule-set-project) to ask general usage questions and participate in discussions on the CRS. Also [here](https://lists.owasp.org/pipermail/owasp-modsecurity-core-rule-set/index) you can find the archives for the previous mailing list.
[Join the #coreruleset channel on OWASP Slack](http://owaspslack.com) to chat about the CRS.
[Join the #coreruleset channel on OWASP Slack](https://owasp.slack.com/) to chat about the CRS. ([Click here](https://owasp.org/slack/invite) to get an invitation if you are not yet registered on the OWASP slack. It's open to non-members too.)
## License
Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.</br>
Copyright (c) 2021-2024 CRS project. All rights reserved.
Copyright (c) 2021-2022 Core Rule Set project. All rights reserved.
The OWASP ModSecurity Core Rule Set is distributed under Apache Software License (ASL) version 2. Please see the enclosed LICENSE file for full details.
The OWASP CRS is distributed under Apache Software License (ASL) version 2. Please see the enclosed LICENSE file for full details.

View file

@ -1,4 +1,90 @@
# Security Policy
See policy here: https://github.com/coreruleset/coreruleset/blob/v4.0/dev/SECURITY.md
## Supported Versions
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.).
For more information see our [wiki](https://github.com/coreruleset/coreruleset/wiki/Release-Policy).
The OWASP CRS officially supports the two latest point releases with severe security patches.
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.
Along those lines, OWASP CRS team may not issue security notifications for unsupported software.
| Version | Supported |
| --------- | ------------------ |
| 4.0.0 | :white_check_mark: |
| 3.3.x | :white_check_mark: |
| 3.2.x | :x: |
| 3.1.x | :x: |
| 3.0.x | :x: |
| 2.x | :x: |
## GPG Signed Releases
Releases are signed using [our GPG key](https://coreruleset.org/security.asc), (fingerprint: 3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72). You can verify the release using GPG/PGP compatible tooling.
### Importing the GPG Key
To get our key using gpg: `gpg --keyserver pgp.mit.edu --recv 0x38EEACA1AB8A6E72` (this id should be equal to the last sixteen hex characters in our fingerprint).
You can also use `gpg --fetch-key https://coreruleset.org/security.asc` directly.
### Verifying the CRS Release
Download the release file and the corresponding signature. The following example shows how to do it for `v4.0.0` release:
```bash
$ wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.0.0.tar.gz
$ wget https://github.com/coreruleset/coreruleset/releases/download/v4.0.0/coreruleset-4.0.0.tar.gz.asc
```
**Verification**:
```bash
gpg --verify coreruleset-4.0.0.tar.gz.asc v4.0.0.tar.gz
gpg: Signature made Wed Jun 30 10:05:48 2021 -03
gpg: using RSA key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg: Good signature from "OWASP Core Rule Set <security@coreruleset.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72
```
If the signature was good, the verification succeeded. If you see a warning like the above, it means you know our public key, but you are not trusting it. You can trust it by using the following method:
```bash
gpg edit-key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg> trust
Your decision: 5 (ultimate trust)
Are you sure: Yes
gpg> quit
```
Then you will see this result when verifying:
```bash
gpg --verify coreruleset-4.0.0.tar.gz.asc v4.0.0.tar.gz
gpg: Signature made Wed Jun 30 15:05:48 2021 CEST
gpg: using RSA key 36006F0E0BA167832158821138EEACA1AB8A6E72
gpg: Good signature from "OWASP Core Rule Set <security@coreruleset.org>" [ultimate]
```
## Reporting a Vulnerability
We strive to make the OWASP CRS accessible to a wide audience of beginner and experienced users.
We welcome bug reports, false positive alert reports, evasions, usability issues, and suggestions for new detections.
Submit these types of non-vulnerability related issues via Github.
Please include your installed version and the relevant portions of your audit log.
False negative or common bypasses should [create an issue](https://github.com/coreruleset/coreruleset/issues/new) so they can be addressed.
Do this before submitting a vulnerability using our email:
1) Verify that you have the latest version of OWASP CRS.
2) Validate which Paranoia Level this bypass applies to. If it works in PL4, please send us an email.
3) If you detected anything that causes unexpected behavior of the engine via manipulation of existing CRS provided rules, please send it by email.
We also provide you with the [Sandbox project](https://coreruleset.org/docs/development/sandbox/), where you can test your bypass and report back to us. If testing using the sandbox, please include the `X-Unique-ID` from the response in your email.
Our email is [security@coreruleset.org](mailto:security@coreruleset.org). You can send us encrypted email using the same GPG key we use to sign releases, fingerprint: `3600 6F0E 0BA1 6783 2158 8211 38EE ACA1 AB8A 6E72`.
We are happy to work with the community to provide CVE identifiers for any discovered security issues if requested.
If in doubt, feel free to reach out to us!
The OWASP CRS Team.

View file

@ -1,13 +1,8 @@
## GOLD SPONSORS
* Edgio
* Google
* Microsoft
* Nginx (Part of F5)
* United Security Providers
* VMWare
## SILVER SPONSORS
* Bug Bounty Switzerland
* Swiss Post

View file

@ -1,9 +1,9 @@
# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.3.3.5
# OWASP CRS ver.4.0.0
# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
# Copyright (c) 2021-2023 Core Rule Set project. All rights reserved.
# Copyright (c) 2021-2024 CRS project. All rights reserved.
#
# The OWASP ModSecurity Core Rule Set is distributed under
# The OWASP CRS is distributed under
# Apache Software License (ASL) version 2
# Please see the enclosed LICENSE file for full details.
# ------------------------------------------------------------------------
@ -12,15 +12,15 @@
#
# -- [[ Introduction ]] --------------------------------------------------------
#
# The OWASP ModSecurity Core Rule Set (CRS) is a set of generic attack
# The OWASP CRS is a set of generic attack
# detection rules that provide a base level of protection for any web
# application. They are written for the open source, cross-platform
# ModSecurity Web Application Firewall.
#
# See also:
# https://coreruleset.org/
# https://github.com/SpiderLabs/owasp-modsecurity-crs
# https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
# https://github.com/coreruleset/coreruleset
# https://owasp.org/www-project-modsecurity-core-rule-set/
#
@ -175,12 +175,12 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# Uncomment this rule to change the default:
#
#SecAction \
# "id:900000,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.paranoia_level=1"
# "id:900000,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.blocking_paranoia_level=1"
# It is possible to execute rules from a higher paranoia level but not include
@ -189,24 +189,24 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# the new rules would lead to false positives that raise your score above the
# threshold.
# This optional feature is enabled by uncommenting the following rule and
# setting the tx.executing_paranoia_level.
# Technically, rules up to the level defined in tx.executing_paranoia_level
# will be executed, but only the rules up to tx.paranoia_level affect the
# setting the tx.detection_paranoia_level.
# Technically, rules up to the level defined in tx.detection_paranoia_level
# will be executed, but only the rules up to tx.blocking_paranoia_level affect the
# anomaly scores.
# By default, tx.executing_paranoia_level is set to tx.paranoia_level.
# tx.executing_paranoia_level must not be lower than tx.paranoia_level.
# By default, tx.detection_paranoia_level is set to tx.blocking_paranoia_level.
# tx.detection_paranoia_level must not be lower than tx.blocking_paranoia_level.
#
# Please notice that setting tx.executing_paranoia_level to a higher paranoia
# Please notice that setting tx.detection_paranoia_level to a higher paranoia
# level results in a performance impact that is equally high as setting
# tx.paranoia_level to said level.
# tx.blocking_paranoia_level to said level.
#
#SecAction \
# "id:900001,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.executing_paranoia_level=1"
# "id:900001,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.detection_paranoia_level=1"
#
@ -225,16 +225,16 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# Uncomment this rule to change the default:
#
#SecAction \
# "id:900010,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.enforce_bodyproc_urlencoded=1"
# "id:900010,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.enforce_bodyproc_urlencoded=1"
#
# -- [[ Anomaly Mode Severity Levels ]] ----------------------------------------
# -- [[ Anomaly Scoring Mode Severity Levels ]] --------------------------------
#
# Each rule in the CRS has an associated severity level.
# These are the default scoring points for each severity level.
@ -258,19 +258,19 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# that all configuration variables are set before the CRS rules are processed.)
#
#SecAction \
# "id:900100,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.critical_anomaly_score=5,\
# setvar:tx.error_anomaly_score=4,\
# setvar:tx.warning_anomaly_score=3,\
# setvar:tx.notice_anomaly_score=2"
# "id:900100,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.critical_anomaly_score=5,\
# setvar:tx.error_anomaly_score=4,\
# setvar:tx.warning_anomaly_score=3,\
# setvar:tx.notice_anomaly_score=2"
#
# -- [[ Anomaly Mode Blocking Threshold Levels ]] ------------------------------
# -- [[ Anomaly Scoring Mode Blocking Threshold Levels ]] ----------------------
#
# Here, you can specify at which cumulative anomaly score an inbound request,
# or outbound response, gets blocked.
@ -310,57 +310,121 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# Uncomment this rule to change the defaults:
#
#SecAction \
# "id:900110,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.inbound_anomaly_score_threshold=5,\
# setvar:tx.outbound_anomaly_score_threshold=4"
# "id:900110,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.inbound_anomaly_score_threshold=5,\
# setvar:tx.outbound_anomaly_score_threshold=4"
#
# -- [[ Application Specific Rule Exclusions ]] ----------------------------------------
# -- [[ Application Specific Rule Exclusions ]] --------------------------------
#
# Some well-known applications may undertake actions that appear to be
# malicious. This includes actions such as allowing HTML or Javascript within
# parameters. In such cases the CRS aims to prevent false positives by allowing
# administrators to enable prebuilt, application specific exclusions on an
# application by application basis.
# These application specific exclusions are distinct from the rules that would
# be placed in the REQUEST-900-EXCLUSION-RULES-BEFORE-CRS configuration file as
# they are prebuilt for specific applications. The 'REQUEST-900' file is
# designed for users to add their own custom exclusions. Note, using these
# application specific exclusions may loosen restrictions of the CRS,
# especially if used with an application they weren't designed for. As a result
# they should be applied with care.
# To use this functionality you must specify a supported application. To do so
# uncomment rule 900130. In addition to uncommenting the rule you will need to
# specify which application(s) you'd like to enable exclusions for. Only a
# (very) limited set of applications are currently supported, please use the
# filenames prefixed with 'REQUEST-903' to guide you in your selection.
# Such filenames use the following convention:
# REQUEST-903.9XXX-{APPNAME}-EXCLUSIONS-RULES.conf
# CRS 3.x contained exclusion packages to tweak the CRS for use with common
# web applications, lowering the number of false positives.
#
# It is recommended if you run multiple web applications on your site to limit
# the effects of the exclusion to only the path where the excluded webapp
# resides using a rule similar to the following example:
# SecRule REQUEST_URI "@beginsWith /wordpress/" setvar:tx.crs_exclusions_wordpress=1
# In CRS 4, these are no longer part of the CRS itself, but they are available
# as "CRS plugins". Some plugins improve support for web applications, and others
# may bring new functionality. Plugins are not installed by default, but can be
# downloaded from the plugin registry:
# https://github.com/coreruleset/plugin-registry
#
# For detailed information about using and installing plugins, please see:
# https://coreruleset.org/docs/concepts/plugins/
#
# Modify and uncomment this rule to select which application:
# -- [[ Anomaly Score Reporting Level ]] ---------------------------------------
#
# When a request is blocked due to the anomaly score meeting or exceeding the
# anomaly threshold then the blocking rule will also report the anomaly score.
# This applies to the separate inbound and outbound anomaly scores.
#
# In phase 5, there are additional rules that can perform additional reporting
# of anomaly scores with a verbosity that depends on the reporting level defined
# below.
#
# By setting the reporting level you control whether you want additional
# reporting beyond the blocking rule or not and, if yes, which requests should
# be covered. The higher the reporting level, the more verbose the reporting is.
#
# There are 6 reporting levels:
#
# 0 - Reporting disabled
# 1 - Reporting for requests with a blocking anomaly score >= a threshold
# 2 - Reporting for requests with a detection anomaly score >= a threshold
# 3 - Reporting for requests with a blocking anomaly score greater than 0
# 4 - Reporting for requests with a detection anomaly score greater than 0
# 5 - Reporting for all requests
#
# Note: Reporting levels 1 and 2 make it possible to differentiate between
# requests that are blocked and requests that are *not* blocked but would have
# been blocked if the blocking PL was equal to detection PL. This may be useful
# for certain FP tuning methodologies, for example moving to a higher PL.
#
# A value of 5 can be useful on platforms where you are interested in logging
# non-scoring requests, yet it is not possible to report this information in
# the request/access log. This applies to Nginx, for example.
#
#SecAction \
# "id:900130,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.crs_exclusions_cpanel=1,\
# setvar:tx.crs_exclusions_drupal=1,\
# setvar:tx.crs_exclusions_dokuwiki=1,\
# setvar:tx.crs_exclusions_nextcloud=1,\
# setvar:tx.crs_exclusions_wordpress=1,\
# setvar:tx.crs_exclusions_xenforo=1"
# "id:900115,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.reporting_level=4"
#
# -- [[ Early Anomaly Scoring Mode Blocking ]] ------------------------------
#
# The anomaly scores for the request and the responses are generally summed up
# and evaluated at the end of phase:2 and at the end of phase:4 respectively.
# However, it is possible to enable an early evaluation of these anomaly scores
# at the end of phase:1 and at the end of phase:3.
#
# If a request (or a response) hits the anomaly threshold in this early
# evaluation, then blocking happens immediately (if blocking is enabled) and
# the phase 2 (and phase 4 respectively) will no longer be executed.
#
# Enable the rule 900120 that sets the variable tx.early_blocking to 1 in order
# to enable early blocking. The variable tx.early_blocking is set to 0 by
# default. Early blocking is thus disabled by default.
#
# Please note that early blocking will hide potential alerts from you. This
# means that a payload that would appear in an alert in phase 2 (or phase 4)
# does not get evaluated if the request is being blocked early. So when you
# disabled early blocking again at some point in the future, then new alerts
# from phase 2 might pop up.
#SecAction \
# "id:900120,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.early_blocking=1"
#
# -- [[ Initialize Default Collections ]] -----------------------------------
#
# CRS provides a centralized option to initialize and populate collections
# meant to be used by plugins (E.g.DoS protection plugin).
# By default, Global and IP collections (see rule 901320),
# being not used by core rules, are not initialized.
#
# Uncomment this rule to change the default:
#
#SecAction \
# "id:900130,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.enable_default_collections=1"
#
# -- [[ HTTP Policy Settings ]] ------------------------------------------------
@ -371,7 +435,6 @@ SecDefaultAction "phase:2,log,auditlog,pass"
#
# These variables are used in the following rule files:
# - REQUEST-911-METHOD-ENFORCEMENT.conf
# - REQUEST-912-DOS-PROTECTION.conf
# - REQUEST-920-PROTOCOL-ENFORCEMENT.conf
# HTTP methods that a client is allowed to use.
@ -381,12 +444,12 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# MERGE MKACTIVITY MKCOL MOVE PROPFIND PROPPATCH PUT UNLOCK
# Uncomment this rule to change the default.
#SecAction \
# "id:900200,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"
# "id:900200,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"
# Content-Types that a client is allowed to send in a request.
# Default: |application/x-www-form-urlencoded| |multipart/form-data| |multipart/related|
@ -407,105 +470,141 @@ SecDefaultAction "phase:2,log,auditlog,pass"
#
# To prevent blocking request with not allowed content-type by default, you can create an exclusion
# rule that removes rule 920420. For example:
# SecRule REQUEST_HEADERS:Content-Type "@rx ^text/plain" \
# "id:1234,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# ctl:ruleRemoveById=920420,\
# chain"
# SecRule REQUEST_URI "@rx ^/foo/bar" "t:none"
#SecRule REQUEST_HEADERS:Content-Type "@rx ^text/plain" \
# "id:1234,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# ctl:ruleRemoveById=920420,\
# chain"
# SecRule REQUEST_URI "@rx ^/foo/bar" \
# "t:none"
#
# Uncomment this rule to change the default.
#
#SecAction \
# "id:900220,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|'"
# "id:900220,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.allowed_request_content_type=|application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|'"
# Allowed HTTP versions.
# Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0
# Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0
# Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0
# Example for legacy clients: HTTP/0.9 HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0
# Note that some web server versions use 'HTTP/2', some 'HTTP/2.0', so
# we include both version strings by default.
# Uncomment this rule to change the default.
#SecAction \
# "id:900230,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0'"
# "id:900230,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.allowed_http_versions=HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0 HTTP/3 HTTP/3.0'"
# Forbidden file extensions.
# Guards against unintended exposure of development/configuration files.
# Default: .asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/
# Default: .asa/ .asax/ .ascx/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/
# Example: .bak/ .config/ .conf/ .db/ .ini/ .log/ .old/ .pass/ .pdb/ .rdb/ .sql/
# Note that .axd was removed due to false positives (see PR 1925).
#
# To additionally guard against configuration/install archive files from being
# accidentally exposed, common archive file extensions can be added to the
# restricted extensions list. An example list of common archive file extensions
# is presented below:
# .7z/ .br/ .bz/ .bz2/ .cab/ .cpio/ .gz/ .img/ .iso/ .jar/ .rar/ .tar/ .tbz2/ .tgz/ .txz/ .xz/ .zip/ .zst/
# (Source: https://en.wikipedia.org/wiki/List_of_archive_formats)
#
# Uncomment this rule to change the default.
#SecAction \
# "id:900240,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'"
# "id:900240,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'"
# Forbidden request headers.
# Header names should be lowercase, enclosed by /slashes/ as delimiters.
# Default: /accept-charset/ /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/
# Restricted request headers.
# The HTTP request headers that CRS restricts are split into two categories:
# basic (always forbidden) and extended (may be forbidden). All header names
# should be lowercase and enclosed by /slashes/ as delimiters.
#
# Note: Accept-Charset is a deprecated header that should not be used by clients and
# ignored by servers. It can be used for a response WAF bypass, by asking for a charset
# that the WAF cannot decode.
# Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset
# [ Basic ]
# Includes deprecated headers and headers with known security risks. Always
# forbidden.
# Default: /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/
#
# Note: Content-Encoding is used to list any encodings that have been applied to the
# original payload. It is only used for compression, which isn't supported by CRS by
# default since it blocks newlines and null bytes inside the request body. Most
# compression algorithms require at least null bytes per RFC. Blocking it shouldn't
# break anything and increases security since ModSecurity is incapable of properly
# scanning compressed request bodies.
# /content-encoding/
# Used to list any encodings that have been applied to the original payload.
# Only used for compression, which isn't supported by CRS by default since CRS
# blocks newlines and null bytes inside the request body. Most compression
# algorithms require at least null bytes per RFC. Blocking Content-Encoding
# shouldn't break anything and increases security since WAF engines, including
# ModSecurity, are typically incapable of properly scanning compressed request
# bodies.
#
# Note: Blocking Proxy header prevents 'httpoxy' vulnerability: https://httpoxy.org
# /proxy/
# Blocking this prevents the 'httpoxy' vulnerability: https://httpoxy.org
#
# /lock-token/
#
# /content-range/
#
# /if/
#
# /x-http-method-override/
# /x-http-method/
# /x-method-override/
# Blocking these headers prevents method override attacks, as described here:
# https://www.sidechannel.blog/en/http-method-override-what-it-is-and-how-a-pentester-can-use-it
#
# Uncomment this rule to change the default.
#SecAction \
# "id:900250,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.restricted_headers=/accept-charset/ /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/'"
# File extensions considered static files.
# Extensions include the dot, lowercase, enclosed by /slashes/ as delimiters.
# Used in DoS protection rule. See section "Anti-Automation / DoS Protection".
# Default: /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/
# "id:900250,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.restricted_headers_basic=/content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/'"
#
# [ Extended ]
# Includes deprecated headers that are still in use (so false positives are
# possible) and headers with possible security risks. Forbidden at a higher
# paranoia level.
# Default: /accept-charset/
#
# /accept-charset/
# Deprecated header that should not be used by clients and should be ignored
# by servers. Can be used for a response WAF bypass by asking for a charset
# that the WAF cannot decode. Considered to be a good indicator of suspicious
# behavior but produces too many false positives to be forbidden by default.
# References:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset
# https://github.com/coreruleset/coreruleset/issues/3140
#
# Uncomment this rule to change the default.
#SecAction \
# "id:900260,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.static_extensions=/.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/'"
# "id:900255,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.restricted_headers_extended=/accept-charset/'"
# Content-Types charsets that a client is allowed to send in a request.
# Default: utf-8|iso-8859-1|iso-8859-15|windows-1252
# The content-types are enclosed by |pipes| as delimiters to guarantee exact matches.
# Default: |utf-8| |iso-8859-1| |iso-8859-15| |windows-1252|
# Uncomment this rule to change the default.
# Use "|" to separate multiple charsets like in the rule defining
# tx.allowed_request_content_type.
#SecAction \
# "id:900280,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.allowed_request_content_type_charset=utf-8|iso-8859-1|iso-8859-15|windows-1252'"
# "id:900280,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:'tx.allowed_request_content_type_charset=|utf-8| |iso-8859-1| |iso-8859-15| |windows-1252|'"
#
# -- [[ HTTP Argument/Upload Limits ]] -----------------------------------------
@ -520,80 +619,82 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# Block request if number of arguments is too high
# Default: unlimited
# Example: 255
# Note that a hard limit by the engine may also apply here (SecArgumentsLimit).
# This would override this soft limit.
# Uncomment this rule to set a limit.
#SecAction \
# "id:900300,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.max_num_args=255"
# "id:900300,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.max_num_args=255"
# Block request if the length of any argument name is too high
# Default: unlimited
# Example: 100
# Uncomment this rule to set a limit.
#SecAction \
# "id:900310,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.arg_name_length=100"
# "id:900310,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.arg_name_length=100"
# Block request if the length of any argument value is too high
# Default: unlimited
# Example: 400
# Uncomment this rule to set a limit.
#SecAction \
# "id:900320,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.arg_length=400"
# "id:900320,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.arg_length=400"
# Block request if the total length of all combined arguments is too high
# Default: unlimited
# Example: 64000
# Uncomment this rule to set a limit.
#SecAction \
# "id:900330,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.total_arg_length=64000"
# "id:900330,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.total_arg_length=64000"
# Block request if the file size of any individual uploaded file is too high
# Default: unlimited
# Example: 1048576
# Uncomment this rule to set a limit.
#SecAction \
# "id:900340,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.max_file_size=1048576"
# "id:900340,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.max_file_size=1048576"
# Block request if the total size of all combined uploaded files is too high
# Default: unlimited
# Example: 1048576
# Uncomment this rule to set a limit.
#SecAction \
# "id:900350,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.combined_file_sizes=1048576"
# "id:900350,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.combined_file_sizes=1048576"
#
# -- [[ Easing In / Sampling Percentage ]] -------------------------------------
#
# Adding the Core Rule Set to an existing productive site can lead to false
# Adding the CRS to an existing productive site can lead to false
# positives, unexpected performance issues and other undesired side effects.
#
# It can be beneficial to test the water first by enabling the CRS for a
@ -612,7 +713,7 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# following directive somewhere after the inclusion of the CRS
# (E.g., RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf).
#
# SecRuleUpdateActionById 901150 "nolog"
#SecRuleUpdateActionById 901450 "nolog"
#
# ATTENTION: If this TX.sampling_percentage is below 100, then some of the
# requests will bypass the Core Rules completely and you lose the ability to
@ -620,148 +721,14 @@ SecDefaultAction "phase:2,log,auditlog,pass"
#
# Uncomment this rule to enable this feature:
#
#SecAction "id:900400,\
# phase:1,\
# pass,\
# nolog,\
# setvar:tx.sampling_percentage=100"
#
# -- [[ Project Honey Pot HTTP Blacklist ]] ------------------------------------
#
# Optionally, you can check the client IP address against the Project Honey Pot
# HTTPBL (dnsbl.httpbl.org). In order to use this, you need to register to get a
# free API key. Set it here with SecHttpBlKey.
#
# Project Honeypot returns multiple different malicious IP types.
# You may specify which you want to block by enabling or disabling them below.
#
# Ref: https://www.projecthoneypot.org/httpbl.php
# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecHttpBlKey
#
# Uncomment these rules to use this feature:
#
#SecHttpBlKey XXXXXXXXXXXXXXXXX
#SecAction "id:900500,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.block_search_ip=1,\
# setvar:tx.block_suspicious_ip=1,\
# setvar:tx.block_harvester_ip=1,\
# setvar:tx.block_spammer_ip=1"
#
# -- [[ GeoIP Database ]] ------------------------------------------------------
#
# There are some rulesets that inspect geolocation data of the client IP address
# (geoLookup). The CRS uses geoLookup to implement optional country blocking.
#
# To use geolocation, we make use of the MaxMind GeoIP database.
# This database is not included with the CRS and must be downloaded.
#
# There are two formats for the GeoIP database. ModSecurity v2 uses GeoLite (.dat files),
# and ModSecurity v3 uses GeoLite2 (.mmdb files).
#
# If you use ModSecurity 3, MaxMind provides a binary for updating GeoLite2 files,
# see https://github.com/maxmind/geoipupdate.
#
# Download the package for your OS, and read https://dev.maxmind.com/geoip/geoipupdate/
# for configuration options.
#
# Warning: GeoLite (not GeoLite2) databases are considered legacy, and not being updated anymore.
# See https://support.maxmind.com/geolite-legacy-discontinuation-notice/ for more info.
#
# Therefore, if you use ModSecurity v2, you need to regenerate updated .dat files
# from CSV files first.
#
# You can achieve this using https://github.com/sherpya/geolite2legacy
# Pick the zip files from maxmind site:
# https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip
#
# Follow the guidelines for installing the tool and run:
# ./geolite2legacy.py -i GeoLite2-Country-CSV.zip \
# -f geoname2fips.csv -o /usr/share/GeoliteCountry.dat
#
# Update the database regularly, see Step 3 of the configuration link above.
#
# By default, when you execute `sudo geoipupdate` on Linux, files from the free database
# will be downloaded to `/usr/share/GeoIP` (both v1 and v2).
#
# Then choose from:
# - `GeoLite2-Country.mmdb` (if you are using ModSecurity v3)
# - `GeoLiteCountry.dat` (if you are using ModSecurity v2)
#
# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html
# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html
#
# Uncomment only one of the next rules here to use this feature.
# Choose the one depending on the ModSecurity version you are using, and change the path accordingly:
#
# For ModSecurity v3:
#SecGeoLookupDB /usr/share/GeoIP/GeoLite2-Country.mmdb
# For ModSecurity v2 (points to the converted one):
#SecGeoLookupDB /usr/share/GeoIP/GeoLiteCountry.dat
#
# -=[ Block Countries ]=-
#
# Rules in the IP Reputation file can check the client against a list of high
# risk country codes. These countries have to be defined in the variable
# tx.high_risk_country_codes via their ISO 3166 two-letter country code:
# https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements
#
# If you are sure that you are not getting any legitimate requests from a given
# country, then you can disable all access from that country via this variable.
# The rule performing the test has the rule id 910100.
#
# This rule requires SecGeoLookupDB to be enabled and the GeoIP database to be
# downloaded (see the section "GeoIP Database" above.)
#
# By default, the list is empty. A list used by some sites was the following:
# setvar:'tx.high_risk_country_codes=UA ID YU LT EG RO BG TR RU PK MY CN'"
#
# Uncomment this rule to use this feature:
#
#SecAction \
# "id:900600,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.high_risk_country_codes='"
# "id:900400,\
# phase:1,\
# pass,\
# nolog,\
# setvar:tx.sampling_percentage=100"
#
# -- [[ Anti-Automation / DoS Protection ]] ------------------------------------
#
# Optional DoS protection against clients making requests too quickly.
#
# When a client is making more than 100 requests (excluding static files) within
# 60 seconds, this is considered a 'burst'. After two bursts, the client is
# blocked for 600 seconds.
#
# Requests to static files are not counted towards DoS; they are listed in the
# 'tx.static_extensions' setting, which you can change in this file (see
# section "HTTP Policy Settings").
#
# For a detailed description, see rule file REQUEST-912-DOS-PROTECTION.conf.
#
# Uncomment this rule to use this feature:
#
#SecAction \
# "id:900700,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:'tx.dos_burst_time_slice=60',\
# setvar:'tx.dos_counter_threshold=100',\
# setvar:'tx.dos_block_timeout=600'"
#
# -- [[ Check UTF-8 encoding ]] ------------------------------------------------
@ -773,80 +740,12 @@ SecDefaultAction "phase:2,log,auditlog,pass"
# Uncomment this rule to use this feature:
#
#SecAction \
# "id:900950,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.crs_validate_utf8_encoding=1"
#
# -- [[ Blocking Based on IP Reputation ]] ------------------------------------
#
# Blocking based on reputation is permanent in the CRS. Unlike other rules,
# which look at the individual request, the blocking of IPs is based on
# a persistent record in the IP collection, which remains active for a
# certain amount of time.
#
# There are two ways an individual client can become flagged for blocking:
# - External information (RBL, GeoIP, etc.)
# - Internal information (Core Rules)
#
# The record in the IP collection carries a flag, which tags requests from
# individual clients with a flag named IP.reput_block_flag.
# But the flag alone is not enough to have a client blocked. There is also
# a global switch named tx.do_reput_block. This is off by default. If you set
# it to 1 (=On), requests from clients with the IP.reput_block_flag will
# be blocked for a certain duration.
#
# Variables
# ip.reput_block_flag Blocking flag for the IP collection record
# ip.reput_block_reason Reason (= rule message) that caused to blocking flag
# tx.do_reput_block Switch deciding if we really block based on flag
# tx.reput_block_duration Setting to define the duration of a block
#
# It may be important to know, that all the other core rules are skipped for
# requests, when it is clear that they carry the blocking flag in question.
#
# Uncomment this rule to use this feature:
#
#SecAction \
# "id:900960,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.do_reput_block=1"
#
# Uncomment this rule to change the blocking time:
# Default: 300 (5 minutes)
#
#SecAction \
# "id:900970,\
# phase:1,\
# nolog,\
# pass,\
# t:none,\
# setvar:tx.reput_block_duration=300"
#
# -- [[ Collection timeout ]] --------------------------------------------------
#
# Set the SecCollectionTimeout directive from the ModSecurity default (1 hour)
# to a lower setting which is appropriate to most sites.
# This increases performance by cleaning out stale collection (block) entries.
#
# This value should be greater than or equal to:
# tx.reput_block_duration (see section "Blocking Based on IP Reputation") and
# tx.dos_block_timeout (see section "Anti-Automation / DoS Protection").
#
# Ref: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#wiki-SecCollectionTimeout
# Please keep this directive uncommented.
# Default: 600 (10 minutes)
SecCollectionTimeout 600
# "id:900950,\
# phase:1,\
# pass,\
# t:none,\
# nolog,\
# setvar:tx.crs_validate_utf8_encoding=1"
#
@ -866,4 +765,4 @@ SecAction \
pass,\
t:none,\
nolog,\
setvar:tx.crs_setup_version=335"
setvar:tx.crs_setup_version=400"

View file

@ -1,8 +1,17 @@
Welcome to the OWASP Core Rule Set (CRS) documentation.
The OWASP CRS documentation is generated as a Sphinx project and is stored in a separate Github repository. While the documentation is available as part of the CRS project it is provided in the form of a git-submodule. Using a git-submodule allow us to update the documentation without making changes to the main rule repository.
The latest version of the documentation can be read at:
https://coreruleset.org/docs/
The OWASP CRS documentation is generated by Hugo and is stored
in a separate Github repository:
https://github.com/coreruleset/documentation/
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 allows us to update the documentation without making
changes to the main rule repository.
You can download the documentation using git:
$ git submodule init
$ git submodule update
Alternatively, the latest version of the documentation is available at https://www.modsecurity.org/CRS/Documentation/
git submodule update --init docs

View file

@ -0,0 +1,7 @@
This is the folder where you install CRS plugins.
See https://github.com/coreruleset/plugin-registry
for a list of registered official and 3rd party plugins.
Plugins are documented in the CRS INSTALL file and
in also with said plugin registry.

View file

@ -0,0 +1,23 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##! Cover the GET method
##! | Path |--- Query ---| Fragment |
^get /[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?$
##! Cover the CONNECT method
##! Meth |----- IPv4 Address ------|- Port -| Protocol |
^connect (?:\d{1,3}\.){3}\d{1,3}\.?(?::\d+)?\s+[\w\./]+$
##! Meth |- Host --|Prt| Protocol |
^connect [\w\-\./]+:\d+\s+[\w\./]+$
##! Cover the OPTIONS method
##! Meth |*| Protocol |
^options \*\s+[\w\./]+$
##! Cover other methods of the form METHOD [[scheme]://[host][:port]]/path[?query][#fragment] protocol
##! Method ---|- Scheme:// -|- Host --|-- Port --| Path |--- Query ---| Fragment | Protocol |
^[a-z]{3,10}\s+(?:\w{3,7}?://[\w\-\./]*(?::\d+)?)?/[^?#]*(?:\?[^#\s]*)?(?:#[\S]*)?\s+[\w\./]+$

View file

@ -0,0 +1,27 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! The HTML entities included in the expression are a best guess selection of frequently
##! used entities. Including too many would further reduce the performance of the expression
##! but there may well be additional entities that would make sense to add to the list.
##! The official list of entities is hosted by the WHATWG:
##! https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references
##!+ i
##!^ ^
##!$ *$
&[aeiouclnrszg]acute;
&[cdelnrstz]caron;
&[cgklnrst]cedil;
&[aeioucghjswy]circ;
&[aeiou]grave;
&[au]ring;
&[anoi]tilde;
&[aeiouy]uml;
&amp;
&apos;
&nbsp;
&oslash;
[^'\";=]

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ ^
##!$ $
##! grab the path, except for the lat path segment (separate rule)
(.*)/
##!=>
##! skip the last path segment, if there is one (non-capturing group)
(?:[^?]+)?
##!=>
##! grab the query string, if there is one
(\?.*)?

View file

@ -0,0 +1,12 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ ^
##!$ $
##! find any percent character
.*%.*
##!=>
##! followed by something that looks like a file extension
\.[^\s.]+

View file

@ -0,0 +1,6 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
%uff[0-9a-f]{2}

View file

@ -0,0 +1,18 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Current Accept-Encoding headers
br
compress
deflate
gzip
identity
\*
^$
##! Deprecated Accept-Encoding headers
aes128gcm
exi
pack200-gzip
zstd
x-compress
x-gzip

View file

@ -0,0 +1,4 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!> include charset-specification

View file

@ -1,5 +1,5 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regexp_assemble/.
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Attacks attempting bypass by forcing JSON body processor leveraging recommended rule 200000
##! Find Content-Type: application/x-www-form-urlencoded;boundary="application/json"

View file

@ -1,5 +1,5 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regexp_assemble/.
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Attacks attempting to bypass content-type restrictions or behaviour
##! Find Content-Type: application/x-www-form-urlencoded;boundary="multipart/form-data"

View file

@ -0,0 +1,4 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!> include charset-specification

View file

@ -0,0 +1,110 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Source: https://github.com/wireghoul/dotdotpwn/blob/master/DotDotPwn/TraversalEngine.pm
##! Attack description: https://doc.lagout.org/security/McGraw.Hill.HackNotes.Web.Security.Portable.Reference.eBook-DDU.pdf
##! Excerpt:
##! In short, IIS turns %c0%af into
##! the ASCII / character, but parses it at a point where security checks for
##! ../ traversals have already occurred!
##! What has really happened? The attack uses an overlong Unicode
##! representation for a forward or backward slash (/ or \).
##! Unicode permits multibyte encoding of the same character.
##! The fundamental representation can be referred to as a one (character) to one (byte field)
##! representation. The overlong representation is a one (character) to many
##! (bytes) version.
##! Two more valid strings that represent the backward slash are %c1%1c
##! and %c1%9c. The difference between these two hex values is 128. More
##! valid slash representations boil down to a matter of math. For example,
##! %c0%9v works even though %9v isnt a hexadecimal value. Try adding
##! the value for “9” (57) to “v” (118); if the result is greater than 127, then
##! subtract 128—hint, the final result should be 47.
##!+ i
##! slash patterns
##!> assemble
\x5c
##! URI encoded
%2f
%5c
##! Hex encoded
0x2f
0x5c
##! Double URI encoded
%252f
%255c
##! Overlong Unicode sequences (target IIS)
%c0%2f
%c0%af
%c0%5c
%c1%9c
%c1%pc
%c0%9v
%c0%qf
%c1%8s
%c1%1c
%c1%af
%bg%qf
##! Unicode 16 "alternative" glyphs
%u2215
%u2216
##! Unknown
%uEFC8
%uF025
##! More double encoding and variations on the above
%%32%%66
%%35%%63
%e0%80%af
%25c1%259c
%25c0%25af
%f0%80%80%af
%f8%80%80%80%af
%2%46
%%32%46
%%32F
%u002f
%1u
/
##!=< slashes
##!=> slashes
##! dot patterns
##! These use the same techniques as for slashes to evade the detection of '.'
\.
\.%00
\.%01
\.\?
\?\.
\?
%2e
0x2e
%c0\.
%252e
%c0%2e
%c0%ae
%c0%5e
%c0%ee
%c0%fe
%uff0e
%%32%%65
%e0%80%ae
%25c0%25ae
%f0%80%80%ae
%f8%80%80%80%ae
%fc%80%80%80%80%ae
%2%45
%u002e
%uff0e
%u2024
%%32%45
%%32E
%c0%6e
##!=>
##! Append {2,3} to the result, as we're looking for two or three dots (e.g. /../, /.../)
{2,3}
##!=>
##!=> slashes
##!<

View file

@ -0,0 +1,17 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! ATTENTION: The rule files 931130.data and 931131.data are meant to be kept in sync.
##! They should result in the same regular expression used on different targets in different phases.
##!+ i
##!> assemble
##!=>
(?:(?:url|jar):)?
##!=>
##!> include url-schemes
##!=>
://(?:[^@]+@)?([^/]*)
##!=>
##!<

View file

@ -0,0 +1,17 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! ATTENTION: The rule files 931129.data and 931131.data are meant to be kept in sync.
##! They should result in the same regular expression used on different targets in different phases.
##!+ i
##!> assemble
##!=>
(?:(?:url|jar):)?
##!=>
##!> include url-schemes
##!=>
://(?:[^@]+@)?([^/]*)
##!=>
##!<

View file

@ -0,0 +1,235 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932125 (RCE Windows command injection - PowerShell aliases)
##!
##! This list comes from the powershell source code. Can be updated using this oneliner:
##! curl -s https://raw.githubusercontent.com/PowerShell/PowerShell/master/src/System.Management.Automation/engine/InitialSessionState.cs -o - | awk -F\" '/new SessionStateAliasEntry\("/ { print $2; }'
##! To prevent some FP for a command, you can require command parameters
##! after a command. Only do this if the command regularly causes FP and if
##! allowing the bare command (without parameters) is not too dangerous.
##! (Note: due to \b following the regexp, a word boundary is also required
##! further on, so some letter/number is needed for a match). Example:
##!
##! diff@
##!+ i
##! Note: the quoting prefixes are part of the command prefixes, except for ^
##! which, for unknown reasons, is not part of the expression
##! extension/switches suffix
##! cmd.com, cmd.exe, etc.
##!$ (?:\.[\"\^]*\w+)?
##! cmd/h
##!$ \b
##! starting tokens prefix
##!> assemble
##! ;cmd
;
##! {cmd
\{
##! |cmd
\|
##! ||cmd
\|\|
##! &cmd
&
##! &&cmd
&&
##! \ncmd
\n
##! \rcmd
\r
##! `cmd
`
##!=>
##! match possible white space between prefix expressions
\s*
##!=>
##! commands prefix
##!> assemble
##! (cmd)
\(
##! ,cmd
,
##! @cmd
@
##! 'cmd'
'
##! "cmd"
\"
##! spacing+cmd
\s
##!<
##!=>
*
##!=>
##! paths prefix
##!> assemble
##! /path/cmd
[\w'\"\./]+/
##! C:\Program Files\cmd
[\x5c'\"\^]*\w[\x5c'\"\^]*:.*\x5c
##! \\net\share\dir\cmd
[\^\.\w '\"/\x5c]*\x5c
##!<
##!=>
?[\"\^]*
##!=>
##!> cmdline windows
ac@
asnp@
cd@
##! disabled for FP: cat@
chdir@
clc@
##! disabled for FP: clear
clhy@
cli@
clp@
cls
clv@
cnsn
##! disabled for FP: compare@
##! disabled for FP: copy@
cp@
cpi@
cpp@
cvpa@
dbp@
del@
diff@
dir@
dnsn
ebp@
epal@
epcsv@
epsn@
##! disabled for FP: erase@
etsn@
exsn@
fc@
fl@
foreach@
ft@
fw@
gal@
gbp@
gc@
gci@
gcm@
gcs@
gdr@
gerr
ghy@
gi@
gjb@
gl@
gm@
gmo@
gp@
gps@
gpv
##! disabled for FP: group
gsn@
gsnp@
gsv@
gu@
gv@
gwmi@
##! disabled for FP: h
##! disabled for FP: history
icm@
iex@
ihy@
ii@
ipal@
ipcsv@
ipmo@
ipsn@
irm@
ise@
iwmi@
iwr@
##! disabled for FP: kill
ls
man@
md@
##! disabled for FP: measure
mi@
mount@
##! disabled for FP: move
mp@
mv@
nal@
ndr@
ni@
nmo@
npssc
nsn@
nv@
ogv@
##! disabled for FP: oh
popd@
pushd@
##! disabled for FP: pwd
##! disabled for FP: r
rbp@
rcjb@
rcsn
rd@
rdr@
ren@
ri@
rjb@
rm@
rmdir@
rmo@
rni@
rnp@
rp@
rsn@
rsnp@
rujb
rv@
rvpa@
rwmi@
sajb@
sal@
saps@
sasv@
sbp@
sc@
##! disabled for FP: select
##! disabled for FP: set
shcm
si@
sl@
##! disabled for FP: sleep
sls@
##! disabled for FP: sort
sp@
spjb@
spps@
spsv@
##! disabled for FP: start
sujb
sv@
swmi@
##! disabled for FP: tee
trcm@
##! disabled for FP: type
##! disabled for FP: where
wjb@
##! disabled for FP: write@
##!<
##!<

View file

@ -0,0 +1,4 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!> include 932130

View file

@ -0,0 +1,7 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Rule 932131 uses the same regular expression as 932130 on a
##! different target.
##!> include 932130

View file

@ -1,2 +1,5 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
\bfor(?:/[dflr].*)? %+[^ ]+ in\(.*\)\s?do
\bif(?:/i)?(?: not)?(?: exist\b| defined\b| errorlevel\b| cmdextversion\b|(?: |\().*(?:\bgeq\b|\bequ\b|\bneq\b|\bleq\b|\bgtr\b|\blss\b|==))

View file

@ -0,0 +1,27 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Prevent command aliasing
##! starting tokens prefix
##!> assemble
\b
##!=>
##!> cmdline unix
alias
##!<
##!=>
##! match white space between command and arguments
\b\s+
##!=>
##! match the alias name
['"\w!%,@]+
##!=>
##! match equals something
=\S
##!=>
##!<

View file

@ -0,0 +1,17 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! - bar;cd+/etc;/bin$u/ca*+passwd
##! - foo;ca\t+/et\c/pa\s\swd
##! - foo;c'at'+/etc/pa's'swd
[*?`\x5c'][^/\n]+/
/[^/]+?[*?`\x5c']
##! - foo;cat$u+/etc$u/passwd
##! - foo;c$-at+/et$-c/pas$-swd
##! - foo;c$_at+/et$_c/pas$_swd
##! - foo;c$?at+/et$?c/pas$?swd
##! - foo;c$*at+/et$*c/pas$*swd
##! - foo;c$@at+/et$@c/pas$@swd
##! - foo;c$!at+/et$!c/pas$!swd
##! - foo;c$$at+/et$$c/pas$$swd
\$[({\[#@!?*\-_$a-zA-Z0-9]

View file

@ -0,0 +1,29 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Prefix to prevent the first `?` (query string marker
##! in URLs) from matching any of the later expressions.
##! If the URL does not have a query string, then instead
##! look for the first `;`.
##! Prefix and suffix markers also form two capture groups
##! that are used for processing and logging in the rule.
##!^ ^[^.]+\.[^?;]+[?;](.*(
##!$ ))
##! The following expressions in this file must be identical to the
##! ones in 932200.
##! - bar;cd+/etc;/bin$u/ca*+passwd
##! - foo;ca\t+/et\c/pa\s\swd
##! - foo;c'at'+/etc/pa's'swd
[*?`\x5c'][^/\n]+/
/[^/]+?[*?`\x5c']
##! - foo;cat$u+/etc$u/passwd
##! - foo;c$-at+/et$-c/pas$-swd
##! - foo;c$_at+/et$_c/pas$_swd
##! - foo;c$?at+/et$?c/pas$?swd
##! - foo;c$*at+/et$*c/pas$*swd
##! - foo;c$@at+/et$@c/pas$@swd
##! - foo;c$!at+/et$!c/pas$!swd
##! - foo;c$$at+/et$$c/pas$$swd
\$[({\[#@!?*\-_$a-zA-Z0-9]

View file

@ -0,0 +1,25 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Prefix to ensure that the rule only matches when the
##! value of the Referer header is not a URL (illegal header
##! value).
##!^ ^[^.]*?
##! The following expressions in this file must be identical to the
##! ones in 932200.
##! - bar;cd+/etc;/bin$u/ca*+passwd
##! - foo;ca\t+/et\c/pa\s\swd
##! - foo;c'at'+/etc/pa's'swd
[*?`\x5c'][^/\n]+/
/[^/]+?[*?`\x5c']
##! - foo;cat$u+/etc$u/passwd
##! - foo;c$-at+/et$-c/pas$-swd
##! - foo;c$_at+/et$_c/pas$_swd
##! - foo;c$?at+/et$?c/pas$?swd
##! - foo;c$*at+/et$*c/pas$*swd
##! - foo;c$@at+/et$@c/pas$@swd
##! - foo;c$!at+/et$!c/pas$!swd
##! - foo;c$$at+/et$$c/pas$$swd
\$[({\[#@!?*\-_$a-zA-Z0-9]

View file

@ -0,0 +1,77 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! This list can be updated using:
##! curl -ks https://raw.githubusercontent.com/sqlite/sqlite/master/src/shell.c.in | grep -oE '^\s+"(\.[a-z0-9]+)' | cut -f2 -d.
##!^ ;\s*\.\s*[\"']?
archive
auth
backup
bail
binary
cd
changes
check
clone
connection
databases
dbconfig
dbinfo
dump
echo
eqp
excel
exit
expert
explain
filectrl
fullschema
headers
help
import
imposter
indexes
iotrace
limit
lint
load
log
mode
nonce
nullvalue
once
open
output
parameter
print
progress
prompt
quit
read
recover
restore
save
scanstats
schema
selftest
separator
session
sh
sha3sum
shell
show
stats
system
tables
testcase
testctrl
timeout
timer
trace
unmodule
vfsinfo
vfslist
vfsname
width

View file

@ -0,0 +1,25 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932220 (RCE Unix command injection)
##!
##! This list comes from (and should be in sync) the `unix-shell.data` file.
##! Not all of the prefixes for the command words will be legal.
##! We've decided to use the same prefix as in 932100 and 932105 here,
##! because we don't know exactly what things are possible after a pipe and
##! we don't want to overcomplicate things by introducing another prefix variation.
##! Not all of the prefixes matched by the expression will actually be valid.
##!+ i
##!^ .\|
##!> assemble
\s*
##!> include unix-shell-evasion-prefix
##!> cmdline unix
##!> include-except unix-shell-upto3 unix-shell-fps-pl2 -- @ "" ~ ""
##!<
##!<

View file

@ -0,0 +1,21 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932230 (RCE for commands of two and three character words)
##!
##! Per discussion in https://github.com/coreruleset/coreruleset/issues/2632, we decided
##! to extend the cmdline evasion regex, so we are applying the evasion to a subset of the
##! original 93210(0|5) rules: the subset of commands from two or three characters that might pose
##! a greater risk of false positives.
##!+ i
##!$ \b
##!> assemble
##!> include unix-shell-evasion-prefix
##!> cmdline unix
##!> include-except unix-shell-upto3 unix-shell-fps-pl1
##!<
##!<

View file

@ -0,0 +1,21 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932231 (RCE Unix command injection part 3/4)
##!
##! To prevent some FP for a command, you can require command parameters
##! after a command. Only do this if the command regularly causes FP and if
##! allowing the bare command (without parameters) is not too dangerous.
##! (Note: due to \b following the regexp, a word boundary is also required
##! further on, so some letter/number is needed for a match). Example:
##!
##! diff+
##! Special regexp case for the '.' (source) command to prevent FP:
##!> assemble
##!> include unix-shell-evasion-prefix
\.\s.*\b
##!<

View file

@ -0,0 +1,16 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932232 (RCE Unix command injection part 4/4)
##!$ \b
##!> assemble
##!> include unix-shell-evasion-prefix
##!> assemble
##!> cmdline unix
##!> include unix-shell-pl3
##!<
##!<
##!<

View file

@ -0,0 +1,11 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!> include unix-shell-evasion-prefix
##! These patterns are approximations of the patterns used by the cmdline
##! processor for `@` and `~`.
##! These patterns are used across multiple files, change with care.
##!> include-except unix-shell-4andup unix-shell-fps-pl1-curated -- @ [\s<>&|)] ~ \S

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!> assemble
##!> include unix-shell-evasion-prefix-start-of-string.ra
##!<
##!=>
##! These patterns are approximations of the patterns used by the cmdline
##! processor for `@` and `~`.
##! These patterns are used across multiple files, change with care.
##!> include-except unix-shell-upto3 unix-shell-fps-pl2 unix-shell-fps-pl2-start-of-string -- @ [\s<>&|)] ~ \S
##!> include-except unix-shell-4andup unix-shell-fps-pl2 unix-shell-fps-pl2-start-of-string -- @ [\s<>&|)] ~ \S

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!^ \b
##!$ (?:\b|\W)
##! These patterns are approximations of the patterns used by the cmdline
##! processor for `@` and `~`.
##! These patterns are used across multiple files, change with care.
##!> include-except unix-shell-upto3 unix-shell-fps-useragents -- @ [\s<>&|)] ~ \S
##!> include-except unix-shell-4andup unix-shell-fps-useragents -- @ [\s<>&|)] ~ \S
##!> include-except unix-shell-pl3 unix-shell-fps-useragents -- @ [\s<>&|)] ~ \S

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!> assemble
##!> include unix-shell-evasion-prefix-start-of-string
##!<
##!=>
##!> assemble
##!> cmdline unix
##!> include unix-shell-pl3
##!<
##!<

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!> assemble
##!> include unix-shell-evasion-prefix-start-of-string
##!<
##!=>
##! These patterns are approximations of the patterns used by the cmdline
##! processor for `@` and `~`.
##! These patterns are used across multiple files, change with care.
##!> include-except unix-shell-upto3 unix-shell-fps-pl2 unix-shell-fps-pl2-start-of-string unix-shell-fps-useragents -- @ [\s<>&|)] ~ \S
##!> include-except unix-shell-4andup unix-shell-fps-pl2 unix-shell-fps-pl2-start-of-string unix-shell-fps-useragents -- @ [\s<>&|)] ~ \S

View file

@ -0,0 +1,44 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Rule 932240 (Generic RCE Unix command evasion detection)
##!
##! Conceptually, we want to match:
##! - at least one character
##! - at least one character from an evasion technique
##!+ i
##! The previous cmdline evasion detection was based on the one from modsecurity: `[\x5c'\"]*`
##! We extended the evasion detection from the cmdline processor with `(?:\$[a-z0-9_@?!#{*-]*)?(?:\x5c)?` to match:
##! - non-existing vars: cu$@rl, una$$me -a, uname$$u -a
##! - vars + spacing: v='u';cu$v\r\l google.com
##! - globbing pattern expansion: {n$u\c$u,-nlvp,777}
##! - globbing: garb=cur[l];$garb+google.com
##! kill '-'9
##!> assemble
[a-z0-9_-]+
##!=>
\s*['\"][^'\"\s]+['\"]
##!=>
[a-z0-9_-]+
##!<
##!> assemble
[a-z0-9_-]+
##!=>
##! py""thon
['\"]['\"]+
[\x5c\[\]]+
\$+[\x5ca-z0-9_@?!#{*-]+
##! process substitution
``
\$\(\)
<\(\)
>\(\)
##!=>
\s*[a-z0-9_-]+
##!=>
##!<

View file

@ -0,0 +1,21 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932250 (RCE Unix command injection)
##!+ i
##!> assemble
##!> include unix-shell-evasion-prefix-start-of-string
##!> assemble
##!> cmdline unix
##!> include-except unix-shell-upto3 unix-shell-fps-pl1 -- @ "" ~ ""
##!<
##!=>
##! This pattern is an approximation of the pattern used by the cmdline
##! processor for `@`.
##! This pattern is used across multiple files, change with care.
[\s<>&|)]
##!<
##!<

View file

@ -0,0 +1,15 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932260 (RCE Unix command injection)
##!+ i
##!> assemble
##!> include unix-shell-evasion-prefix-start-of-string
##! These patterns are approximations of the patterns used by the cmdline
##! processor for `@` and `~`.
##! These patterns are used across multiple files, change with care.
##!> include-except unix-shell-4andup unix-shell-fps-pl1 -- @ [\s<>&|)] ~ \S
##!<

View file

@ -0,0 +1,18 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ (?is)\r\n.*?\b
##! - SMTP Commands
EHLO [a-zA-Z-\.]{1,255}
HELO [a-zA-Z-\.]{1,255}
MAIL FROM:<.{1,64}@.{1,255}>
RCPT TO:(?:<.{1,64}@.{1,255}>|(?: ))?<.{1,64}>
VRFY (?:.{1,64} <.{1,64}@.{1,255}>|.{1,64}@.{1,255})
EXPN (?:.{1,64})
AUTH [A-Z0-9-_]{1,20} (?:=|(?:[\w+/]{4})*(?:[\w+/]{2}==|[\w+/]{3}=))
##! - SMTP Commands without params
STARTTLS\b
RSET\b
NOOP\b(?: .{1,255})?

View file

@ -0,0 +1,13 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ (?s)\r\n.*?\b
##! - SMTP Commands without or optional params
DATA
QUIT
HELP(?: .{1,255})?
##! - SMTP Commands with params
##! Not covered - X<atom> Command (client extensions)

View file

@ -0,0 +1,22 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! All IMAP4 commands start with a "tag"
##!+ is
##!^ \r\n\w{1,50}\b[ ]
##! IMAP4 Commands - PL2
##! - IMAP4Rev1 Commands - with params
APPEND (?:[\w\"\.\-\x5c\/%\*&#]+)?(?: \((?:[a-z\x5c\ ])+\))?(?: \"?\d{1,2}-\w{3}-\d{4} \d{2}:\d{2}:\d{2} [+-]\d{4}\"?)? \{\d{1,20}\+?\}
AUTHENTICATE [a-z0-9-_]{1,20}\r\n
LSUB (?:[\w\"~\/\*#\.]+)? (?:[\w\"\.\x5c\/%\*&]+)?
STATUS (?:[\w\"\.\-\x5c\/%\*&]+)? \((?:UNSEEN|UIDNEXT|MESSAGES|UIDVALIDITY|RECENT| )+\)
UID (?:COPY|FETCH|STORE) (?:[0-9,:\*]+)?
##! - IMAP4Rev1 Commands Extensions - with params
DELETEACL (?:[\w\"\.\-\x5c\/%\*&]+)?
GETACL (?:[\w\"\.\-\x5c\/%\*&]+)?
MYRIGHTS (?:[\w\"\.\-\x5c\/%\*&]+)?
LISTRIGHTS (?:[\w\"\.\-\x5c\/%\*&]+)?
SETACL (?:[\w\"\.\-\x5c\/%\*&]+)? [+-][lrswipckdxtea]+?

View file

@ -0,0 +1,44 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! All IMAP4 commands start with a "tag"
##! TDB: representing charset and language (if needed)
##!+ is
##!^ \r\n\w{1,50}\b[ ]
##! - IMAP4 Commands - PL3
##! - IMAP4Rev1 Commands - with params
CREATE [\w\"\.\-\x5c\/%\*&#]+
COPY [0-9,:\*]+ [\w\"\.\-\x5c\/%\*&#]+
DELETE [\w\"\.\-\x5c%\*&#]+
EXAMINE [\w\"\.\-\x5c%\*&#]+
FETCH [0-9,:\*]+
LIST [\w\"~\-\x5c\/\*#\.]+? [\w\"\.\-\x5c\/%\*&#]+
LOGIN [a-z0-9-_\.\@]{1,40} .*?
RENAME [\w\"\.\-\x5c\/%\*&#]+? [\w\"\.\-\x5c\/%\*&#]+
SELECT [\w\"\.\-\x5c\/%\*&#]+
STORE [0-9,:\*]+? [+-]?FLAGS(?:\.SILENT)? (?:\(\x5c[a-z]{1,20}\))?
SUBSCRIBE [\w\"\.\-\x5c\/%\*&#]+
UNSUBSCRIBE [\w\"\.\-\x5c\/%\*&#]+
##! Search has plenty of variants
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (KEYWORD \x5c)?(?:ALL|ANSWERED|BCC|DELETED|DRAFT|FLAGGED|RECENT|SEEN|UNANSWERED|UNDELETED|UNDRAFT|UNFLAGGED|UNSEEN|NEW|OLD)
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (?:BODY|CC|FROM) .{1,255}
SEARCH(?: CHARSET [\w\-_\.]{1,40})? HEADER .{1,100} .{1,255}
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (?:LARGER \d{1,20}|NOT .{1,255}|[0-9,:\*]+)
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (?:BEFORE|ON|SENTBEFORE|SENTON|SENTSINCE|SINCE) \"?\d{1,2}-\w{3}-\d{4}\"?
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (?:OR .{1,255} .{1,255}|SMALLER \d{1,20}|SUBJECT .{1,255})
SEARCH(?: CHARSET [\w\-_\.]{1,40})? (?:TEXT .{1,255}|TO .{1,255}|UID [0-9,:\*]+?|UNKEYWORD (?:\x5c(Seen|Answered|Flagged|Deleted|Draft|Recent)))
##! - IMAP4rev1 Commands - without params
CAPABILITY
CHECK
CLOSE
EXPUNGE
LOGOUT
NOOP
STARTTLS
UNAUTHENTICATE
##! Not covered - X<atom> Command (client extensions)

View file

@ -0,0 +1,18 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! POP3 Commands - PL2
##!+ is
##!^ \r\n.*?\b
##! POP3 Commands - with args
LIST(?: \d+)?
USER .+?
PASS .+?
RETR \d+?
DELE \d+?
UIDL(?: \d+)?
APOP [\w]+ [a-f0-9]{32}
TOP \d+(?: \d+)?
AUTH [A-Z0-9-_]{1,20} (?:=|(?:[\w+/]{4})*(?:[\w+/]{2}==|[\w+/]{3}=))

View file

@ -0,0 +1,13 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ (?si)\r\n.*?\b
##! POP3 Commands - PL3
##! POP3 Commands - No args
QUIT
STAT
NOOP
RSET
CAPA

View file

@ -0,0 +1,206 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932370 (RCE Windows command injection part 1/2)
##!
##! The list comes from the project LOLBAS. You can get it using the following one-liner:
##! `curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/LOLBAS-Project/LOLBAS/git/trees/master\?recursive\=1 | jq -r '.tree[].path ' | grep ^yml/ | cut -f3 -d/ | cut -f1 -d. | tr 'A-Z' 'a-z' | sort | uniq`
##! To prevent some FP for a command, you can require command parameters
##! after a command. Only do this if the command regularly causes FP and if
##! allowing the bare command (without parameters) is not too dangerous.
##! (Note: due to \b following the regexp, a word boundary is also required
##! further on, so some letter/number is needed for a match). Example:
##!
##! diff@
##!+ i
##! extension/switches suffix
##! cmd.com, cmd.exe, etc.
##!$ (?:\.[\"\^]*\w+)?
##! cmd/h
##!$ \b
##! starting tokens prefix
##!> assemble
##!> include windows-commands-prefix
##!> cmdline windows
acccheckconsole
adplus
advpack
agentexecutor
appinstaller
appvlp
aspnet_compiler
at@
atbroker
bash
bginfo
bitsadmin
cdb
certoc
certreq
certutil
cl_invocation
cl_loadassembly
cl_mutexverifiers
cmd
cmdkey
cmdl32
cmstp
comsvcs
configsecuritypolicy
conhost
control
coregen
createdump
csc
cscript
csi
customshellhost
datasvcutil
defaultpack
desk
desktopimgdownldr
devicecredentialdeployment
devtoolslauncher
dfshim
dfsvc
diantz
diskshadow
dnscmd
dnx
dotnet
dump64
dxcap
esentutl
eventvwr
excel
expand
explorer
extexport
extrac32
findstr
finger
fltmc
forfiles
fsi
fsianycpu
fsutil
ftp
gfxdownloadwrapper
gpscript
hh
ie4uinit
ieadvpack
ieexec
ieframe
ilasm
imewdbld
infdefaultinstall
installutil
jsc
launch-vsdevshell
ldifde
makecab
manage-bde
mavinject
mftrace
microsoft
mmc
mpcmdrun
msbuild
msconfig
msdeploy
msdt
mshta
mshtml
msiexec
msohtmed
mspub
msxsl
netsh
ntdsutil
odbcconf
offlinescannershell
onedrivestandaloneupdater
openconsole
pcalua
pcwrun
pcwutl
pester
pktmon
pnputil
powerpnt
presentationhost
print
printbrm
procdump
protocolhandler
psr
pubprn
rasautou
rcsi
rdrleakdiag
reg
regasm
regedit
regini
register-cimprovider
regsvcs
regsvr32
remote
replace
rpcping
rundll32
runexehelper
runonce
runscripthelper
sc@
schtasks
scriptrunner
setres
settingsynchost
setupapi
shdocvw
shell32
sqldumper
sqlps
sqltoolsps
squirrel
ssh
stordiag
syncappvpublishingserver
syssetup
te@
tracker
ttdinject
tttracer
unregmp2
update
url
utilityfunctions
vbc
verclsid
visualuiaverifynative
vsiisexelauncher
vsjitdebugger
wab
wfc
winget
winrm
winword
wlrmdr
wmic
workfolders
wscript
wsl
wsreset
wt@
wuauclt
xwizard
zipfldr
##!<
##!<

View file

@ -0,0 +1,23 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Word list for rule 932380 (RCE Windows command injection part 2/2)
##!
##!+ i
##! extension/switches suffix
##! cmd.com, cmd.exe, etc.
##!$ (?:\.[\"\^]*\w+)?
##! cmd/h
##!$ \b
##! starting tokens prefix
##!> assemble
##!> include windows-commands-prefix
##!> cmdline windows
##!> include-except windows-commands windows-commands-fps
##!<
##!<

View file

@ -1,3 +1,6 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
AUTH_TYPE
HTTP_ACCEPT
HTTP_ACCEPT_CHARSET

View file

@ -0,0 +1,54 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##! optional opening parenthesis before command
##!^ \b\(?
##! optional quotes
##!^ ['\"]*
##! match comments: `/*...*/`, `//...`, `#...`
##!$ (?:/\*.*\*/|//.*|#.*
##! match white space and quotes
##!$ |\s|\")*
##! optional quotes
##!$ ['\"]*
##! optional closing parenthesis after command
##!$ \)?\s*
##! mandatory parentheses containing optional parameters
##!$ \(.*\)
assert
assert_options
chr
create_function
eval
exec
file
filegroup
glob
imagegif
imagejpeg
imagepng
imagewbmp
imagexbm
is_a
md5
opendir
passthru
popen
readfile
tmpfile
unpack
##! English words, or potential snippets of them, are added here to perform a regex match.
##! Compared to the parallel match performed by 933150, fewer false positives will be generated.
exp
ord
prev
stat
substr
system
unlink

View file

@ -0,0 +1,104 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! File autogenerated by util/php-dictionary-gen with: -a 30 -F 90000 -s ../fp-finder/spell.sh
##!+ i
##!^ \b
##!$ (?:\s|/\*.*\*/|#.*|//.*)*\(.*\)
abs
asin
assert
assert_options
basename
checkdate
chr
chroot
compact
constant
copy
cos
cosh
count
create_function
crypt
current
date
decoct
define
defined
dir
end
eval
exec
exp
explode
extract
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
flock
floor
flush
glob
hash
header
idate
imagegif
imagejpeg
imagepng
imagewbmp
imagexbm
implode
is_a
key
link
log
mail
max
md5
min
name
next
opendir
ord
pack
pass
passthru
pi
popen
pow
prev
rand
range
readfile
rename
reset
round
serialize
shuffle
sin
sleep
sort
stat
substr
symlink
syslog
system
tan
time
tmpfile
touch
trim
ucfirst
unlink
unpack
virtual

View file

@ -0,0 +1,32 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! PHP Wrappers
##!
##! PHP comes with many built-in wrappers for various URL-style protocols for
##! use with the filesystem functions such as fopen(), copy(), file_exists() and
##! filesize(). Abusing of PHP wrappers like phar:// could lead to RCE as
##! describled by Sam Thomas at BlackHat USA 2018 (https://bit.ly/2yaKV5X), even
##! wrappers like zlib://, glob://, rar://, zip://, etc... could lead to LFI and
##! expect:// to RCE.
##!
##! Valid PHP wrappers can be found in the PHP documentation here:
##! https://www.php.net/manual/en/wrappers.php
##! Suffix marker: all options end with ://
##!$ ://
bzip2
expect
glob
ogg
phar
rar
ssh2
ssh2.shell
ssh2.exec
ssh2.tunnel
ssh2.sftp
ssh2.scp
zip
zlib

View file

@ -0,0 +1,31 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Helpers
##!> define single_or_double_quotes ['"]
##!> define string_in_round_brackets \(.+\)
##!$ ;
##!> assemble
##! example payload: (system)(ls);
{{string_in_round_brackets}}{{string_in_round_brackets}}
##! example payload: (sys)"tem"(ls);
{{string_in_round_brackets}}{{single_or_double_quotes}}[a-zA-Z-_0-9]+{{single_or_double_quotes}}{{string_in_round_brackets}}
##! example payload: a=system&b=$_GET[0](ls);
\[\d+\]{{string_in_round_brackets}}
##! example payload: {0}("ls")
\{\d+\}{{string_in_round_brackets}}
##! example payload: $a("ls")
\$[^(\),.;\x5c/]+{{string_in_round_brackets}}
##! example payload: "system"("ls")
{{single_or_double_quotes}}[a-zA-Z0-9-_\x5c]+{{single_or_double_quotes}}{{string_in_round_brackets}}
##! example payload: (string)system("ls")
\([^\)]*string[^\)]*\)[a-zA-Z-_0-9\"'.{}\[\]\s]+\([^\)]*\)
##!<

View file

@ -0,0 +1,30 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Helpers
##!> define single_or_double_quotes ['"]
##!> define string_in_round_brackets \(.+\)
##!$ (?:;|$)?
##!> assemble
##! example payload: (system)(ls)
{{string_in_round_brackets}}{{string_in_round_brackets}}
##! example payload: (sys)"tem"(ls)
{{string_in_round_brackets}}{{single_or_double_quotes}}[a-zA-Z-_0-9]+{{single_or_double_quotes}}{{string_in_round_brackets}}
##! example payload: $_GET[0]("ls")
\[\d+\]{{string_in_round_brackets}}
##! example payload: {0}("ls")
\{\d+\}{{string_in_round_brackets}}
##! example payload: $a("ls")
\$[^(\),.;\x5c/]+{{string_in_round_brackets}}
##! example payload: "system"("ls")
{{single_or_double_quotes}}[a-zA-Z0-9-_\x5c]+{{single_or_double_quotes}}{{string_in_round_brackets}}
##! example payload: (string)system("ls")
\([^\)]*string[^\)]*\)[a-zA-Z-_0-9\"'.{}\[\]\s]+\([^\)]*\)
##!<

View file

@ -0,0 +1,230 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Note that the rule uses `multiMatch` and `removeWhitespace.
##! The explicit white space matches will be matched before
##! `removeWhitespace` is applied, everything else will be matched
##! after white space removal.
##!> define js-prop-start \[['\"`]
##!> define js-prop-start-dynamic \[
##!> define js-prop-finish ['\"`]\]
##! node-serialize serialized function flag
_\$\$ND_FUNC\$\$_
__js_function
\beval\(
String\.fromCharCode
function\(\){
new\s+Function\s*\(
this\.constructor
module\.exports=
\(\s*\Wchild_process\W\s*\)
##!> assemble
\(
\.call\(
##!=< js-call
##!<
##! All "process" method names
##! Note that `sync` will be appended optionally to all, as many
##! of the names have a twin with the `sync` suffix.
##!> assemble
access
appendfile
argv
availability
caveats
chmod
chown
close
copyfile
cp
createreadstream
createwritestream
exec
execfile
exists
fchmod
fchown
fdata
##! yes, fdatasyncsync
fdatasync
fstat
##! yes, fsyncsync
fsync
futimes
inodes
lchmod
link
lstat
lutimes
mkdir
mkdtemp
open
opendir
read
readdir
readfile
readlink
readv
rename
rm
spawn
spawnfile
stat
symlink
truncate
unlink
unwatchfile
utimes
watchfile
writefile
write
writev
##!=>
(?:sync)?
##!=< process-funcs
##!<
##! All "process" prop names
##!> assemble
binding
constructor
env
global
main
mainModule
process
require
##!=< process-props
##!<
##! All "console" method names
##!> assemble
debug
error
info
trace
warn
##!=< console-funcs
##!<
##! All "require" method names
##!> assemble
resolve
##!=< require-funcs
##!<
##! All "require" property names
##!> assemble
main
extensions
cache
##!=< require-props
##!<
##! "process" payloads
##!> assemble
process
##!=>
##! Match method calls via their usual syntax: foo.bar()
##!> assemble
\.
##!=>
##!=> process-funcs
##!=> js-call
##!<
##! Match properties via their usual syntax: foo.bar
##!> assemble
\.
##!=>
##!=> process-props
##!<
##! Match properties functions via: foo["bar"]
##!> assemble
{{js-prop-start}}
##!=>
##!> assemble
##!=> process-funcs
##!<
##!> assemble
##!=> process-props
##!<
##!=>
{{js-prop-finish}}
##!<
##!<
##! Match dynamic property access: process[req.query.a]
##! Note that we don't require `process` as a prefix here
##!> assemble
##!=> process-props
{{js-prop-start-dynamic}}
##!<
##! "console" payloads
##!> assemble
console
##!=>
##! Match method calls via their usual syntax: foo.bar()
##!> assemble
\.
##!=>
##!=> console-funcs
##!=> js-call
##!<
##! Match properties and functions via: foo["bar"]
##!> assemble
{{js-prop-start}}
##!=>
##!=> console-funcs
##!=>
{{js-prop-finish}}
##!<
##!<
##! "require" payloads
##!> assemble
require
##!=>
##! Match method calls via their usual syntax: foo.bar()
##!> assemble
\.
##!=>
##!=> require-funcs
##!=> js-call
##!<
##! Match properties via their usual syntax: foo.bar
##!> assemble
\.
##!=>
##!=> require-props
##!<
##! Match properties and functions via: foo["bar"]
##!> assemble
{{js-prop-start}}
##!=>
##!> assemble
##!=> require-funcs
##!<
##!> assemble
##!=> require-props
##!<
##!=>
{{js-prop-finish}}
##!<
##!<

View file

@ -0,0 +1,14 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!$ \s*\(
close
exists
fork
open
read
spawn
watch
write
require

View file

@ -0,0 +1,187 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Bypasses and techniques here come from:
##! - https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
##! - https://github.com/cujanovic/SSRF-Testing
##!+ i
##! add capture group
##!^ (
##!$ )
##! This regex starts with a list of all the schemes that can be used to make a request
##!> assemble
##!> include url-schemes
##!=>
://
##!=>
##! http://425.510.425.510/ Dotted decimal with overflow (already covered by RFI rule 931100)
##! http://2852039166/ Dotless decimal
##! http://7147006462/ Dotless decimal with overflow
\d{10}
##! http://0xA9.0xFE.0xA9.0xFE/ Dotted hexadecimal
(?:0x[a-f0-9]{2}\.){3}0x[a-f0-9]{2}
##! http://0xA9FEA9FE/ Dotless hexadecimal
0x[a-f0-9]{8}
##! http://0x41414141A9FEA9FE/ Dotless hexadecimal with overflow
0x[a-f0-9]{16}
##! http://0251.0376.0251.0376/ Dotted octal
##! http://0251.00376.000251.0000376/ Dotted octal with padding
(?:0{1,4}\d{1,3}\.){3}0{1,4}\d{1,3}
##! http://169.254.43518/
\d{1,3}\.\d{1,3}\.\d{5}
##! http://169.16689662/
\d{1,3}\.\d{8}
##! glibc Name Service Switch abuse
##! http://\\l\\o\\c\\a\\l\\h\\o\\s\\t (while underscore is not valid RFC syntax, it is allowed and might be used)
(?:\x5c\x5c[a-z\d-]\.?_?)+
##! http://[::ffff:a9fe:a9fe] IPV6 Compressed - IPv6 (base regex from https://ihateregex.io/expr/ipv6/, with [0-9] converted to \d and with non-capturing groups (below))
##! http://[0:0:0:0:0:ffff:a9fe:a9fe] IPV6 Expanded
##! http://[fe80::%zone1] link-local unicast with zone ID
##! http://[0:0:0:0:0:ffff:169.254.169.254] IPV6/IPV4
##! http://[::] the unspecified address
##! Something that looks like IPv6 in a URL.
##! Matches full and compressed IPv6, link-local IPv6 with
##! zone ID, and embedded IPv4.
##! We could match the IPv6 specification here but that would
##! decrease performance of the regular expression and would
##! actually increase the possibility for bypasses.
\[[a-f\d:]+(?:[\d.]+|%\w+)?\]
##! These come from https://github.com/cujanovic/SSRF-Testing
##! These bypasses work by confusing URL parsers in different languages (e.g., PHP, Python, Ruby, Perl)
##! and libraries (e.g. cURL). The bypasses are parser specific but will often be combined to break
##! multiple parsers with one try. The goal is often to get the application to call another library
##! with the malicious URL, e.g. libcurl or glibc (name resolution via gethostbyname(), see also
##! Name Service Switch abuse above).
##! http://127.88.23.245:22/+&@google.com:80#+@google.com:80/ (already covered by RFI rule 931100)
##! http://127.88.23.245:22/?@google.com:80/ (already covered by RFI rule 931100)
##! http://127.88.23.245:22/#@www.google.com:80/ (already covered by RFI rule 931100)
##! http://google.com:80\\@127.88.23.245:22/ (already covered by RFI rule 931100)
##! http://google.com:80+&@127.88.23.245:22/#+@google.com:80/
##! http://google.com:80+&@google.com:80#+@127.88.23.245:22/
##! create ip-or-domain for later use
##!> assemble
(?:\d{1,3}\.){3,3}\d{1,3}
[a-z][\w\-\.]{1,255}
##!=>
:\d{1,5}
##!=< ip-or-domain
##!<
##!> assemble
##! domain + port
[a-z][\w\-\.]{1,255}:\d{1,5}
##!=>
##! at least one of the evasion techniques
##!> assemble
##! technique 1
##!> assemble
##! possible white spaces to fool safety checks in URL parsers
\s*
##!=>
##! &@ to confuse URL parsers (& can indicate query parameter, @ indicates user info)
&?@
##!=>
##! IPv4 + port or domain + port
##!=> ip-or-domain
##! optional forward slash
\/?
##!=>
##!<
##! technique 2
##!> assemble
##! fragment to confuse URL parsers
#
##!=>
##! possible white spaces to fool safety checks in URL parsers
\s*
##!=>
##! &@ to confuse URL parsers (& can indicate query parameter, @ indicates user info)
&?@
##!=>
##! IPv4 + port or domain + port
##!=> ip-or-domain
##! optional forward slash
/?
##!=>
##!<
##!<
##!=>
+
##!=>
##!<
##! Enclosed alphanumerics are used for evasion (https://en.wikipedia.org/wiki/Enclosed_Alphanumerics).
##! See also https://github.com/cujanovic/SSRF-Testing.
##! These will normally sound many alarms, but having them flagged as ssrf attempt makes sense
##!> assemble
##! ⓪,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,⑪,⑫,⑬,⑭,⑮,⑯,⑰,⑱,⑲,⑳
\xe2\x91[\xaa\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3]
##! ⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿
\xe2\x91[\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf]
##! ⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇
\xe2\x92[\x80\x81\x82\x83\x84\x85\x86\x87]
##! ⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛
\xe2\x92[\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b]
##! ⒜,⒝,⒞,⒟,⒠,⒡,⒢,⒣,⒤,⒥,⒦,⒧,⒨,⒩,⒪,⒫,⒬,⒭,⒮,⒯,⒰,⒱,⒲,⒳,⒴,⒵
\xe2\x92[\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5]
##! Ⓐ,Ⓑ,Ⓒ,Ⓓ,Ⓔ,Ⓕ,Ⓖ,Ⓗ,Ⓘ,Ⓙ
\xe2\x92[\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf]
##! Ⓚ,Ⓛ,Ⓜ,Ⓝ,Ⓞ,Ⓟ,Ⓠ,Ⓡ,Ⓢ,Ⓣ,Ⓤ,Ⓥ,Ⓦ,Ⓧ,Ⓨ,Ⓩ
\xe2\x93[\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f]
##! ⓐ,ⓑ,ⓒ,ⓓ,ⓔ,ⓕ,ⓖ,ⓗ,ⓘ,ⓙ,ⓚ,ⓛ
\xe2\x93[\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b]
##! ⓜ,ⓝ,ⓞ,ⓟ,ⓠ,ⓡ,ⓢ,ⓣ,ⓤ,ⓥ,ⓦ,ⓧ,ⓨ,ⓩ
\xe2\x93[\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9]
##! ⓫,⓬,⓭,⓮,⓯,⓰,⓱,⓲,⓳,⓴
\xe2\x93[\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4]
##! ⓿,⓵,⓶,⓷,⓸,⓹,⓺,⓻,⓼,⓽,⓾
\xe2\x93[\xbf\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe]
##! ideographic full stop: 。
\xe3\x80\x82
##!=< enclosed-alnums
##!<
##! an IP could start with digits and dots
##!> assemble
[\d.]{0,11}
##!=>
##!> assemble
##!=> enclosed-alnums
##!<
##!=>
##! match all for capture
+
##!=>
##!<
##!<

View file

@ -0,0 +1,4 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
\@\{.*\}

View file

@ -0,0 +1,4 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
Process\s*\.\s*spawn\s*\(

View file

@ -0,0 +1,9 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! Match while(true) like loops
##!> assemble
##!^ while\s*\([\s(]*
##!$ .*\)
##!> include js-truthy-values
##!<

View file

@ -0,0 +1,10 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!^ ^
##!> assemble
data:
##!=>
##!> include charset-specification-no-anchors
##!<

View file

@ -0,0 +1,17 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!^ .
##!$ \b
\bxlink:href
\bxhtml
\bxmlns
!ENTITY\s+(?:\S+|%\s+\S+)\s+SYSTEM
!ENTITY\s+(?:\S+|%\s+\S+)\s+PUBLIC
\bdata:text/html
\bformaction
@import
;base64
\bpattern\b.*?=

View file

@ -0,0 +1,371 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!> assemble
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?
##!=< js-prop-prefix
##!<
##!> assemble
s\W*?c\W*?r\W*?i\W*?p\W*?t
f\W*?o\W*?r\W*?m
d\W*?i\W*?a\W*?l\W*?o\W*?g
s\W*?t\W*?y\W*?l\W*?e
s\W*?v\W*?g
m\W*?a\W*?r\W*?q\W*?u\W*?e\W*?e
l\W*?i\W*?n\W*?k[^>\w]
o\W*?b\W*?j\W*?e\W*?c\W*?t[^>\w]
e\W*?m\W*?b\W*?e\W*?d[^>\w]
a\W*?p\W*?p\W*?l\W*?e\W*?t[^>\w]
p\W*?a\W*?r\W*?a\W*?m[^>\w]
i?\W*?f\W*?r\W*?a\W*?m\W*?e[^>\w]
b\W*?a\W*?s\W*?e[^>\w]
b\W*?o\W*?d\W*?y[^>\w]
m\W*?e\W*?t\W*?a[^>\w]
i\W*?m\W*?a?\W*?g\W*?e?[^>\w]
v\W*?i\W*?d\W*?e\W*?o[^>\w]
a\W*?u\W*?d\W*?i\W*?o[^>\w]
b\W*?i\W*?n\W*?d\W*?i\W*?n\W*?g\W*?s[^>\w]
s\W*?e\W*?t[^>\w]
a\W*?n\W*?i\W*?m\W*?a\W*?t\W*?e[^>\w]
##!=< js-payloads
##!<
##!> assemble
(?:<\w.*[\s/]|['\"](?:.*[\s/])?)
##!=< html-properties-prefix
##!<
##!> assemble
background
formaction
lowsrc
onabort
onactivate
onadapteradded
onaddtrack
onafterprint
onafterscriptexecute
onafterupdate
onalerting
onanimationcancel
onanimationend
onanimationiteration
onanimationstart
onantennastatechange
onappcommand
onaudioend
onaudioprocess
onaudiostart
onauxclick
onbeforeactivate
onbeforecopy
onbeforecut
onbeforedeactivate
onbeforeeditfocus
onbeforeinput
onbeforepaste
onbeforeprint
onbeforescriptexecute
onbeforetoggle
onbeforeunload
onbeforeupdate
onbegin
onbeginEvent
onblocked
onblur
onbounce
onboundary
onbroadcast
onbusy
oncached
oncallschanged
oncanplay
oncanplaythrough
oncardstatechange
oncellchange
oncfstatechange
onchange
onchargingchange
onchargingtimechange
onchecking
onclick
onclose
oncommand
oncommandupdate
oncomplete
oncompositionend
oncompositionstart
oncompositionupdate
onconnected
onconnecting
oncontextmenu
oncontrolselect
oncopy
oncuechange
oncut
ondataavailable
ondatachange
ondataerror
ondatasetchanged
ondatasetcomplete
ondblclick
ondeactivate
ondeliveryerror
ondeliverysuccess
ondevicefound
ondevicelight
ondevicemotion
ondeviceorientation
ondeviceproximity
ondialing
ondisabled
ondischargingtimechange
ondisconnected
ondisconnecting
ondomactivate
ondomattrmodified
ondomcharacterdatamodified
ondomfocusin
ondomfocusout
ondommousescroll
ondomnodeinserted
ondomnodeinsertedintodocument
ondomnoderemoved
ondomnoderemovedfromdocument
ondomsubtreemodified
ondownloading
ondragdrop
ondragend
ondragenter
ondragexit
ondraggesture
ondragleave
ondragover
ondragstart
ondrop
ondurationchange
onemptied
onenabled
onend
onended
onendEvent
onenter
onerror
onerrorupdate
onexit
onfailed
onfilterchange
onfinish
onfocus
onfocusin
onfocusout
onformchange
onforminput
onfullscreenchange
ongamepadaxismove
ongamepadbuttondown
ongamepadbuttonup
ongamepadconnected
ongamepaddisconnected
onget
onhashchange
onheadphoneschange
onheld
onhelp
onholding
onicccardlockerror
oniccinfochange
onincoming
oninput
oninvalid
onkeydown
onkeypress
onkeyup
onlevelchange
onload
onloadeddata
onloadedmetadata
onloadend
onloadstart
onlosecapture
only
onmark
onmessage
onmousedown
onmouseenter
onmouseleave
onmousemove
onmouseout
onmouseover
onmouseup
onmousewheel
onmove
onmoveend
onmovestart
onmozafterpaint
onmozaudioavailable
onmozbeforeresize
onmozedgeuicanceled
onmozedgeuicompleted
onmozedgeuistarted
onmozfullscreenchange
onmozfullscreenerror
onmozmagnifygesture
onmozmagnifygesturestart
onmozmagnifygestureupdate
onmozmousehittest
onmozmousepixelscroll
onmoznetworkdownload
onmoznetworkupload
onmozorientationchange
onmozpointerlockchange
onmozpointerlockerror
onmozpresstapgesture
onmozrotategesture
onmozrotategesturestart
onmozrotategestureupdate
onmozscrolledareachanged
onmozswipegesture
onmozswipegestureend
onmozswipegesturestart
onmozswipegestureupdate
onmoztapgesture
onmoztimechange
onnomatch
onnoupdate
onobsolete
onoffline
ononline
onopen
onoverflow
onoverflowchanged
onpagehide
onpageshow
onpaint
onpaste
onpause
onplay
onplaying
onpointerdown
onpointerenter
onpointerleave
onpointermove
onpointerout
onpointerover
onpointerrawupdate
onpointerup
onpopstate
onpopuphidden
onpopuphiding
onpopupshowing
onpopupshown
onprogress
onpropertychange
onratechange
onreadystatechange
onreceived
onremovetrack
onrepeat
onrepeatEvent
onrequest
onreset
onresize
onresult
onresume
onresuming
onretrieving
onrowenter
onrowexit
onrowsdelete
onrowsinserted
onscroll
onscrollend
onsearch
onseekcomplete
onseeked
onseeking
onselect
onselectionchange
onselectstart
onsending
onsent
onset
onshow
onsoundend
onsoundstart
onspeechend
onspeechstart
onstalled
onstart
onstatechange
onstatuschanged
onstkcommand
onstksessionend
onstop
onsubmit
onsuccess
onsuspend
onsvgabort
onsvgerror
onsvgload
onsvgresize
onsvgscroll
onsvgunload
onsvgzoom
ontext
ontimeout
ontimeupdate
ontoggle
ontouchcancel
ontouchend
ontouchenter
ontouchleave
ontouchmove
ontouchstart
ontransitioncancel
ontransitionend
ontransitionrun
ontransitionstart
onunderflow
onunhandledrejection
onunload
onupdateready
onupgradeneeded
onuserproximity
onussdreceived
onversionchange
onvoicechange
onvolumechange
onwaiting
onwarning
onwebkitanimationend
onwebkitanimationiteration
onwebkitanimationstart
onwebkittransitionend
onwheel
onzoom
ping
src
style
##!=< html-properties
##!<
##!> assemble
[\s\x08]*?=
##!=< html-properties-end
##!<
##!> assemble
##!=> js-prop-prefix
##!=> js-payloads
##!<
##!> assemble
##!=> html-properties-prefix
##!=> html-properties
##!=> html-properties-end
##!<

View file

@ -0,0 +1,231 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! This rule tries to match all the possible ways to write 'javascript' using
##! html entities, and javascript escape sequences.
##! See https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references for examples.
##! And https://www.w3schools.com/charsets/ref_html_ascii.asp for the list of
##! all the possible html entities.
##!+ i
##! Matched order is sequential: we first match 'j', then 'a', then 'v', etc.
##!> define html_entity_hex_prefix &#x0*
##!> define html_entity_dec_prefix &#0*
##!> define whitespaces [\t\n\r]
##! html_encoded_whitespace is a list of all the possible ways to write an encoded whitespace
##!> assemble
##! canonical form
{{whitespaces}}
##! alternative forms
##!> assemble
##! 09 horizontal tab
##! 10 line feed
##! 13 carriage return
##! 0A line feed (hex)
##! 0D carriage return (hex)
{{html_entity_dec_prefix}}9;?
{{html_entity_dec_prefix}}10;?
{{html_entity_dec_prefix}}13;?
{{html_entity_hex_prefix}}A;?
{{html_entity_hex_prefix}}D;?
&tab;
&newline;
##!=>
##!<
##!=>
*
##!=< html_encoded_whitespace
##!<
##! all the possible ways to end the word 'javascript', plus whitespaces
##!> assemble
##! canonical form
:
##! alternative forms
##!> assemble
##! 58 : colon
##! 3A : colon (hex)
{{html_entity_dec_prefix}}58;?
{{html_entity_hex_prefix}}3A;?
&colon;
##!<
##!=>
.
##!=< end_javascript
##!<
##! all the possible ways to write 'j', plus whitespaces
##! canonical form
j
##! alternative forms
##!> assemble
##! J 74 uppercase J
##! j 106 lowercase j
##! J 4A uppercase J (hex)
##! j 6A lowercase j (hex)
{{html_entity_dec_prefix}}74;
{{html_entity_dec_prefix}}106;
{{html_entity_hex_prefix}}4A;
{{html_entity_hex_prefix}}6A;
##!<
##!=>
##!=> html_encoded_whitespace
##! all the possible ways to write 'a', plus whitespaces
##!> assemble
##! canonical form
a
##! alternative forms
##!> assemble
##! A 65 uppercase A
##! a 97 lowercase a
##! A 41 uppercase A (hex)
##! a 61 lowercase a (hex)
{{html_entity_dec_prefix}}65;
{{html_entity_dec_prefix}}97;
{{html_entity_hex_prefix}}41;
{{html_entity_hex_prefix}}61;
##!<
##!=>
##!=> html_encoded_whitespace
##!=< all_possible_ways_to_write_a
##!<
##!=> all_possible_ways_to_write_a
##! all the possible ways to write 'v', plus whitespaces
##! canonical form
v
##! alternative forms
##!> assemble
##! V 86 uppercase V
##! V 56 uppercase V (hex)
##! v 118 lowercase v
##! v 76 lowercase v (hex)
{{html_entity_dec_prefix}}86;
{{html_entity_hex_prefix}}56;
{{html_entity_dec_prefix}}118;
{{html_entity_hex_prefix}}76;
##!<
##!=>
##!=> html_encoded_whitespace
##!=> all_possible_ways_to_write_a
##! all the possible ways to write 's', plus whitespaces
##! canonical form
s
##! alternative forms
##!> assemble
##! s 115 lowercase s
##! s 73 lowercase s (hex)
##! S 83 uppercase S
##! S 53 uppercase S (hex)
{{html_entity_dec_prefix}}115;
{{html_entity_hex_prefix}}73;
{{html_entity_dec_prefix}}83;
{{html_entity_hex_prefix}}53;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'c', plus whitespaces
##! canonical form
c
##! alternative forms
##!> assemble
##! c 63 lowercase C (hex)
##! c 99 lowercase c
##! C 43 uppercase c (hex)
##! C 67 uppercase C
{{html_entity_hex_prefix}}63;
{{html_entity_dec_prefix}}99;
{{html_entity_hex_prefix}}43;
{{html_entity_dec_prefix}}67;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'r', plus whitespaces
##! canonical form
r
##! alternative forms
##!> assemble
##! r 72 lowercase R (hex)
##! r 114 lowercase r
##! r 52 uppercase r (hex)
##! R 82 uppercase R
{{html_entity_hex_prefix}}72;
{{html_entity_dec_prefix}}114;
{{html_entity_hex_prefix}}52;
{{html_entity_dec_prefix}}82;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'i', plus whitespaces
##! canonical form
i
##! alternative forms
##!> assemble
##! i 69 lowercase i (hex)
##! i 105 lowercase i
##! I 49 uppercase i (hex)
##! I 73 uppercase I
{{html_entity_hex_prefix}}69;
{{html_entity_dec_prefix}}105;
{{html_entity_hex_prefix}}49;
{{html_entity_dec_prefix}}73;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'p', plus whitespaces
##! canonical form
p
##! alternative forms
##!> assemble
##! p 70 lowercase p (hex)
##! p 112 lowercase p
##! P 50 uppercase p (hex)
##! P 80 uppercase P
{{html_entity_hex_prefix}}70;
{{html_entity_dec_prefix}}112;
{{html_entity_hex_prefix}}50;
{{html_entity_dec_prefix}}80;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 't', plus whitespaces
##! canonical form
t
##! alternative forms
##!> assemble
##! t 74 lowercase t (hex)
##! t 116 lowercase t
##! T 54 uppercase t (hex)
##! T 84 uppercase T
{{html_entity_hex_prefix}}74;
{{html_entity_dec_prefix}}116;
{{html_entity_hex_prefix}}54;
{{html_entity_dec_prefix}}84;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##!=> end_javascript

View file

@ -0,0 +1,212 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##! This rule tries to match all the possible ways to write 'vbscript' using
##! html entities, and javascript escape sequences.
##! See https://html.spec.whatwg.org/multipage/named-characters.html#named-character-references for examples.
##! And https://www.w3schools.com/charsets/ref_html_ascii.asp for the list of
##! all the possible html entities.
##!+ i
##! Matched order is sequential: we first match 'v', then 'b', then 's', etc.
##!> define html_entity_hex_prefix &#x0*
##!> define html_entity_dec_prefix &#0*
##!> define whitespaces [\t\n\r]
##! html_encoded_whitespace is a list of all the possible ways to write an encoded whitespace
##!> assemble
##! canonical form
{{whitespaces}}
##! alternative forms
##!> assemble
##! 09 horizontal tab
##! 10 line feed
##! 13 carriage return
##! 0A line feed (hex)
##! 0D carriage return (hex)
{{html_entity_dec_prefix}}9;?
{{html_entity_dec_prefix}}10;?
{{html_entity_dec_prefix}}13;?
{{html_entity_hex_prefix}}A;?
{{html_entity_hex_prefix}}D;?
&tab;
&newline;
##!=>
##!<
##!=>
*
##!=< html_encoded_whitespace
##!<
##! all the possible ways to end the word 'vbscript', plus whitespaces
##!> assemble
##! canonical form
:
##! alternative forms
##!> assemble
##! 58 : colon
##! 3A : colon (hex)
{{html_entity_dec_prefix}}58;?
{{html_entity_hex_prefix}}3A;?
&colon;
##!<
##!=>
.
##!=< end_vbscript
##!<
##!=>
##! all the possible ways to write 'v', plus whitespaces
##! canonical form
v
##! alternative forms
##!> assemble
##! v 118 lowercase v
##! v 76 lowercase v (hex)
##! V 86 uppercase V
##! V 56 uppercase V (hex)
{{html_entity_dec_prefix}}118;
{{html_entity_hex_prefix}}76;
{{html_entity_dec_prefix}}86;
{{html_entity_hex_prefix}}56;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'b', plus whitespaces
##! canonical form
b
##! alternative forms
##!> assemble
##! b 98 lowercase b
##! b 62 lowercase b (hex)
##! B 66 uppercase B
##! B 42 uppercase B (hex)
{{html_entity_dec_prefix}}98;
{{html_entity_hex_prefix}}62;
{{html_entity_dec_prefix}}66;
{{html_entity_hex_prefix}}42;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 's', plus whitespaces
##! canonical form
s
##! alternative forms
##!> assemble
##! s 115 lowercase s
##! s 73 lowercase s (hex)
##! S 83 uppercase S
##! S 53 uppercase S (hex)
{{html_entity_dec_prefix}}115;
{{html_entity_hex_prefix}}73;
{{html_entity_dec_prefix}}83;
{{html_entity_hex_prefix}}53;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'c', plus whitespaces
##! canonical form
c
##! alternative forms
##!> assemble
##! c 63 lowercase C (hex)
##! c 99 lowercase c
##! C 43 uppercase c (hex)
##! C 67 uppercase C
{{html_entity_hex_prefix}}63;
{{html_entity_dec_prefix}}99;
{{html_entity_hex_prefix}}43;
{{html_entity_dec_prefix}}67;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'r', plus whitespaces
##! canonical form
r
##! alternative forms
##!> assemble
##! r 72 lowercase R (hex)
##! r 114 lowercase r
##! r 52 uppercase r (hex)
##! R 82 uppercase R
{{html_entity_hex_prefix}}72;
{{html_entity_dec_prefix}}114;
{{html_entity_hex_prefix}}52;
{{html_entity_dec_prefix}}82;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'i', plus whitespaces
##! canonical form
i
##! alternative forms
##!> assemble
##! i 69 lowercase i (hex)
##! i 105 lowercase i
##! I 49 uppercase i (hex)
##! I 73 uppercase I
{{html_entity_hex_prefix}}69;
{{html_entity_dec_prefix}}105;
{{html_entity_hex_prefix}}49;
{{html_entity_dec_prefix}}73;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 'p', plus whitespaces
##! canonical form
p
##! alternative forms
##!> assemble
##! p 70 lowercase p (hex)
##! p 112 lowercase p
##! P 50 uppercase p (hex)
##! P 80 uppercase P
{{html_entity_hex_prefix}}70;
{{html_entity_dec_prefix}}112;
{{html_entity_hex_prefix}}50;
{{html_entity_dec_prefix}}80;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##! all the possible ways to write 't', plus whitespaces
##! canonical form
t
##! alternative forms
##!> assemble
##! t 74 lowercase t (hex)
##! t 116 lowercase t
##! T 54 uppercase t (hex)
##! T 84 uppercase T
{{html_entity_hex_prefix}}74;
{{html_entity_dec_prefix}}116;
{{html_entity_hex_prefix}}54;
{{html_entity_dec_prefix}}84;
##!<
##!=>
##!=> html_encoded_whitespace
##!=>
##!=> end_vbscript

View file

@ -0,0 +1,16 @@
##! Please refer to the documentation at
##! https://coreruleset.org/docs/development/regex_assembly/.
##!+ i
##!^ \b
##!$ \s*\(
eval
settimeout
setinterval
new\s+Function
alert
atob
btoa
prompt
confirm

Some files were not shown because too many files have changed in this diff Show more