check / check (push) Successful in 3m15s
Delete the Gitea compose setup, its document, its two scripts and their make targets. Documents and tests no longer use Gitea as the example deployment. The Core Rule Set exclusions for Gitea's false positives in internal/waf stay, with their comments and tests. Model: opus-5-5
73 lines
2.9 KiB
Markdown
73 lines
2.9 KiB
Markdown
# Rule files
|
|
|
|
The format of a rule file, and the default file the image ships. "Rule files" in
|
|
[`SPEC.md`](../SPEC.md) says how the files are read, watched and mounted, and
|
|
what each action leads to.
|
|
|
|
## The format
|
|
|
|
A rule is a line of four fields separated by spaces or tabs: an id, a target, an
|
|
action and a regex. The regex runs to the end of the line. Blank lines and lines
|
|
starting with `#` are ignored.
|
|
|
|
```
|
|
# id target action regex
|
|
env-file path ban (?i)^/\.env(\.[a-z]+)?$
|
|
scanner-agent user_agent ban (?i)\b(sqlmap|nikto|nuclei|wpscan)\b
|
|
```
|
|
|
|
- The id is letters, digits, `-` and `_`, unique across all files. The log line,
|
|
the metrics, the alerts and a ban's notes name the rule by it.
|
|
- The target is what the regex is matched against:
|
|
- `path`: the path without the query;
|
|
- `uri`: the path and the query together;
|
|
- `query`: the query as sent;
|
|
- `method`, `host`, `user_agent` and `referer`;
|
|
- `header:<Name>`: any one request header but `Host` and
|
|
`Transfer-Encoding`.
|
|
- The action is `log`, `block` or `ban`.
|
|
- The regex is in Go's syntax, RE2. It matches anywhere in the target unless
|
|
anchored with `^` and `$`. `(?i)` at its front makes it ignore case.
|
|
|
|
## The default file
|
|
|
|
The image ships one file, `share/rules.d/00-default.rules`, installed as
|
|
`/etc/smallwebwaf/rules.d/00-default.rules`:
|
|
|
|
```
|
|
# 00-default.rules: probes no real visitor sends, anchored at the site root
|
|
|
|
# id target action regex
|
|
env-file path ban (?i)^/\.env(\.[a-z]+)?$
|
|
vcs-dir path ban (?i)^/\.(git|svn|hg|bzr)(/|$)
|
|
secrets-dir path ban (?i)^/\.(aws|ssh|docker|kube)/
|
|
secret-file path ban (?i)^/\.(htpasswd|htaccess|npmrc|netrc|pgpass|git-credentials|bash_history|DS_Store)$
|
|
editor-dir path ban (?i)^/\.(vscode|idea)/
|
|
backup-file path ban (?i)^/[^/]+\.(php(\.[a-z0-9]+|~)|sql(\.[a-z0-9]+)?)$
|
|
log-file path ban (?i)^/(debug|error|access)\.log$
|
|
compose-file path ban (?i)^/(docker-)?compose\.ya?ml$
|
|
php-shell path ban (?i)^/(shell|c99|r57|wso|alfa)\.php$
|
|
scanner-agent user_agent ban (?i)\b(sqlmap|nikto|nuclei|masscan|zgrab|wpscan)\b
|
|
path-traversal uri block (\.\./){2,}
|
|
empty-agent user_agent log ^$
|
|
```
|
|
|
|
## A file of your own
|
|
|
|
`servewaf` reads the rule files in its own container. Rules of your own go in a
|
|
file named to sort after the default, such as `50-site.rules`:
|
|
|
|
```
|
|
# 50-site.rules: WordPress probes, which this site never serves
|
|
wp-probe path ban (?i)^/(wp-login\.php|xmlrpc\.php|wp-admin/)
|
|
```
|
|
|
|
A `Dockerfile` built on the `smallwebwaf` image, for `servewaf` to run from,
|
|
adds it:
|
|
|
|
```dockerfile
|
|
COPY 50-site.rules /etc/smallwebwaf/rules.d/50-site.rules
|
|
```
|
|
|
|
Or mount it there. A `path` rule applies on every site behind that `servewaf`.
|