Path rules and trap paths match the path decoded once too (closes #85)
check / check (push) Waiting to run
check / check (push) Waiting to run
A path rule matched only the path as the client sent it, so /%2eenv got past the default env-file rule while an app that decodes the path serves /.env. A path rule now matches the path as sent or decoded once, as a uri rule already did, and so does a path in SWWAF_TRAP_PATHS: /%77p-login.php matches /wp-login.php. The query is cut off before the path is decoded, and the path is decoded only once, so /%252eenv is not /.env. A ban's notes keep the path as sent. SPEC.md and README.md say so. Model: opus-5-5
This commit was merged in pull request #125.
This commit is contained in:
@@ -197,11 +197,12 @@ in `bin/state` unless `SWWAF_STATE_DIR` is set, and the default rule file of
|
||||
rate limits and before the rule files, which it does not need. A request for
|
||||
one is refused with `SWWAF_BAN_RESPONSE` and bans the client's netblock for a
|
||||
clear sign of attack, as a `ban` rule's match does. A trap path is matched
|
||||
against the path a `path` rule sees: as the client sent it, before any
|
||||
decoding and without the query, the whole of it, character for character.
|
||||
`/wp-login.php` matches `/wp-login.php?redirect_to=x`, but not
|
||||
`/wp-login.php/`, `/WP-LOGIN.PHP`, `/blog/wp-login.php` or `/%77p-login.php`.
|
||||
A client in `SWWAF_ALLOW_NETS` is not checked.
|
||||
against the path a `path` rule sees: without the query, as the client sent it
|
||||
and once percent-decoded, the whole of it, character for character.
|
||||
`/wp-login.php` matches `/wp-login.php?redirect_to=x` and `/%77p-login.php`,
|
||||
but not `/wp-login.php/`, `/WP-LOGIN.PHP`, `/blog/wp-login.php` or
|
||||
`/%2577p-login.php`. The ban's notes give the path as the client sent it. A
|
||||
client in `SWWAF_ALLOW_NETS` is not checked.
|
||||
- Inspects each request with the OWASP Core Rule Set 4.25.0, run by Coraza,
|
||||
after the rule files, unless `SWWAF_WAF_MODE` is `off`: its method, its URL
|
||||
with the query, and its headers, and, once `SWWAF_WAF_BODY_LIMIT` is set, its
|
||||
@@ -741,8 +742,8 @@ effective settings are logged at start, unless `SWWAF_LOG_LEVEL` is `warn` or
|
||||
scanners ask for, such as `/wp-login.php,/xmlrpc.php` in front of gitea; a
|
||||
request for one bans its client for a clear sign of attack, as a `ban` rule
|
||||
does, with or without rule files (see "What it does so far" above). A path
|
||||
that does not start with `/`, or holds a `?`, which no path a `path` rule sees
|
||||
holds, stops the start.
|
||||
that does not start with `/`, or holds a `?`, as one written with a query
|
||||
does, stops the start.
|
||||
- `SWWAF_ERROR_BURST_THRESHOLD` (default `30`): the most requests of a client in
|
||||
a minute that `smallwebwaf` may refuse after a rule file match, a trap path or
|
||||
a Core Rule Set match, or for a missing or wrong token; one more breaks the
|
||||
@@ -1522,14 +1523,15 @@ scanner-agent user_agent ban (?i)\b(sqlmap|nikto|nuclei|wpscan)\b
|
||||
|
||||
- The id is letters, digits, `-` and `_`, and no two rules share one. The
|
||||
request log, the metrics and a ban's notes name the rule by it.
|
||||
- The target is what the regex is matched against: `path` or `query`, as the
|
||||
client sent it, before any decoding; `uri`, the path and the query together,
|
||||
both as sent and once percent-decoded, so that an encoded probe does not slip
|
||||
past; `method`; `host`; `user_agent`; `referer`; or `header:<Name>`, any one
|
||||
request header but `Host` and `Transfer-Encoding`, which Go's HTTP server
|
||||
takes out of every request; the request's host is the target `host`. A header
|
||||
sent more than once is matched with its values joined by `, `, and one not
|
||||
sent as empty text. No body is read.
|
||||
- The target is what the regex is matched against: `path`, the path without the
|
||||
query, and `uri`, the path and the query together, each both as sent and once
|
||||
percent-decoded, so that an encoded probe does not slip past; `query`, as the
|
||||
client sent it, before any decoding; `method`; `host`; `user_agent`;
|
||||
`referer`; or `header:<Name>`, any one request header but `Host` and
|
||||
`Transfer-Encoding`, which Go's HTTP server takes out of every request; the
|
||||
request's host is the target `host`. A header sent more than once is matched
|
||||
with its values joined by `, `, and one not sent as empty text. No body is
|
||||
read.
|
||||
- The action is `log`, `block` or `ban` (see "What it does so far" above). Keep
|
||||
`ban` for requests no real visitor sends, and anchor a path at the site root
|
||||
with `^/`: a file of the same name deeper in a site can be ordinary content,
|
||||
|
||||
Reference in New Issue
Block a user