Core Rule Set: gitea's ordinary requests pass by default (closes #198)
check / check (push) Failing after 2m27s
check / check (push) Failing after 2m27s
The eighth change, internal/waf/gitea.conf, has some fields skip the rules that refused ordinary gitea requests there, on gitea's paths only: searches, file names and branch names. Referer skips 944130 too. A registry's layer reuse skips 932260 on from, the seventh change. The new setting SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE loads an operator's own exclusions before the Core Rule Set's rules. The start stops, in every mode, on a set file that cannot be read or does not parse, names smallwebwaf's own ids, or holds a directive such as SecRuleRemoveById. A test sends the recorded gitea requests at the defaults, none refused, and three attacks, all refused. Model: opus-5-5
This commit is contained in:
1 parent
7fed6b6d36
commit
56aa8fb7b1
13 files changed
+1265
-67
No files matched your search
@@ -36,7 +36,8 @@ to them.
|
||||
- the state files;
|
||||
- a lookup database;
|
||||
- a `SWWAF_` setting given as a file;
|
||||
- the file `SWWAF_LOG_REMOTE_TLS_CA_FILE` names.
|
||||
- the file `SWWAF_LOG_REMOTE_TLS_CA_FILE` names;
|
||||
- the file `SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE` names.
|
||||
|
||||
## Non-goals
|
||||
|
||||
@@ -81,7 +82,7 @@ to them.
|
||||
of bans is full.
|
||||
- `internal/rules`: reads the rule files at start and again when they
|
||||
change, and tells which rules a request matches.
|
||||
- `internal/waf`: the Core Rule Set, with the six changes listed under
|
||||
- `internal/waf`: the Core Rule Set, with the eight changes listed under
|
||||
"Attack detection", as Coraza directives.
|
||||
- `internal/lookup`: looks clients up through GeoJS or in the lookup
|
||||
database.
|
||||
@@ -325,9 +326,10 @@ Conventions:
|
||||
lists: `SWWAF_ADMIN_TOKEN_FILE` names the file that holds `SWWAF_ADMIN_TOKEN`.
|
||||
The file's contents are the value, less one newline at the end, and are
|
||||
checked as the value itself would be. Setting both forms stops the start, and
|
||||
so does naming a file that cannot be read. `SWWAF_LOG_REMOTE_TLS_CA_FILE`
|
||||
already holds a file name, so it has no `_FILE` form. No `SWRP_` setting has
|
||||
one, since `rproxy` never touches disk.
|
||||
so does naming a file that cannot be read. `SWWAF_LOG_REMOTE_TLS_CA_FILE` and
|
||||
`SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE` already hold a file name, so they have
|
||||
no `_FILE` form. No `SWRP_` setting has one, since `rproxy` never touches
|
||||
disk.
|
||||
- Settings, files included, are read once at start. Changing one means
|
||||
restarting the container. The files `servewaf` watches while it runs are its
|
||||
state files, its rule files and the lookup database.
|
||||
@@ -582,6 +584,27 @@ files, the limits and the bans still apply to the client that sends it.
|
||||
probes these rules caught (see "Rule files"). A list you give replaces the
|
||||
default, so name these six ids in it to keep them off.
|
||||
|
||||
- `SWWAF_CORE_RULE_SET_EXCLUSIONS_FILE` names a file of exclusions, written as
|
||||
Coraza directives. An exclusion switches one rule off for some fields or paths
|
||||
only, where `SWWAF_WAF_DISABLED_RULES` switches it off everywhere. The file
|
||||
holds an app's own exclusions; the eighth change below holds gitea's.
|
||||
- `servewaf` loads the file after `smallwebwaf`'s own setup rules and before
|
||||
the Core Rule Set's rules. The Core Rule Set loads its own
|
||||
`REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf` at the same point.
|
||||
- So the file holds only `SecAction` and `SecRule` lines that exclude with
|
||||
`ctl:ruleRemoveTargetById` or `ctl:ruleRemoveById`. These run with each
|
||||
request, before the rules they exclude, those of phase 1 included.
|
||||
- A rule that `SWWAF_WAF_DISABLED_RULES` switches off and the file names is
|
||||
simply off.
|
||||
- The start stops on a file that cannot be read or does not parse, whatever
|
||||
`SWWAF_WAF_MODE` is.
|
||||
- It stops too on a file that names a number from 900000 to 900999, the ids
|
||||
of `smallwebwaf`'s own rules, alone or in a range. Comment lines are not
|
||||
checked.
|
||||
- It stops too on a directive that removes or changes rules as the file
|
||||
loads, such as `SecRuleRemoveById`, since none of the Core Rule Set's
|
||||
rules is loaded yet.
|
||||
|
||||
- `SWWAF_WAF_BODY_LIMIT` switches body inspection on, up to that size. It takes
|
||||
at most `64K`, since `servewaf` gets no more of a body than that (see "The
|
||||
answer"). Form data and multipart bodies are read up to the size. JSON and XML
|
||||
@@ -610,7 +633,7 @@ files, the limits and the bans still apply to the client that sends it.
|
||||
scanner from an ordinary client. In front of a code forge, registry and git
|
||||
clients get `404` and `401` by design, hundreds of times a minute.
|
||||
|
||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in six ways, since in front of
|
||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in eight ways, since in front of
|
||||
gitea it would otherwise refuse ordinary requests. The changes hold in front of
|
||||
every app, and no setting undoes them:
|
||||
|
||||
@@ -642,9 +665,10 @@ every app, and no setting undoes them:
|
||||
or `docker-build`. In these parameters, what only these three rules would
|
||||
catch reaches the app, such as the command `|cat /etc/passwd`. Path
|
||||
traversal, SQL and script injection, and PHP, Java and Node.js code are
|
||||
still refused there. Every other parameter keeps all three rules. An app
|
||||
that uses one of these parameters as a file on the server, or passes it to a
|
||||
shell, must check the value itself. A rule file can refuse it instead.
|
||||
still refused there. Other parameters keep all three rules, except on the
|
||||
gitea paths the eighth change names. An app that uses one of these
|
||||
parameters as a file on the server, or passes it to a shell, must check the
|
||||
value itself. A rule file can refuse it instead.
|
||||
|
||||
5. Two cookies are left out, and `Referer` keeps fewer rules:
|
||||
- The Core Rule Set reads the request without the `gitea_flash` and
|
||||
@@ -658,15 +682,79 @@ every app, and no setting undoes them:
|
||||
only to its own pages. Every other cookie is read in full. An app that
|
||||
reads a cookie of either name must check it itself.
|
||||
- `Referer` is not checked for a Unix command given without arguments
|
||||
(932340) or for Java starting a process (944110). `Referer` names the page
|
||||
a request comes from, on everything that page loads and on every link
|
||||
followed from it. The Core Rule Set takes some page addresses for attacks,
|
||||
such as a search for `env`, or OpenJDK's `Runtime.java`, whose path holds
|
||||
both `runtime` and `java.`. All of those requests would be refused.
|
||||
`Referer` keeps the other rules. An app that passes `Referer` to a shell
|
||||
must check it itself.
|
||||
(932340), for Java starting a process (944110) or for a Java class name
|
||||
(944130). `Referer` names the page a request comes from, on everything
|
||||
that page loads and on every link followed from it. The Core Rule Set
|
||||
takes some page addresses for attacks:
|
||||
- a search for `env`;
|
||||
- OpenJDK's `Runtime.java`, whose path holds both `runtime` and `java.`;
|
||||
- a file named `java.lang.String.md`.
|
||||
|
||||
Every request from such a page would be refused. `Referer` keeps the
|
||||
other rules, except after some gitea searches (the eighth change). An
|
||||
app that passes `Referer` to a shell must check it itself.
|
||||
|
||||
6. Responses are not inspected. A raw file from a repository, such as a shell
|
||||
script, looks to the response rules like source code leaking from the server.
|
||||
7. The `from` parameter of a container registry's upload path,
|
||||
`/v2/<image>/blobs/uploads/`, is not checked for command names (932260). When
|
||||
a push reuses a layer, `from` names the image the layer comes from. An image
|
||||
such as `owner/python3-app` would have that push refused.
|
||||
8. On gitea's paths, some fields skip the rules that refused ordinary gitea
|
||||
requests there. They are the fields where gitea sends a search, a file name
|
||||
or a branch name. `internal/waf/gitea.conf` lists each rule and the request
|
||||
it refused. The fields are:
|
||||
- `q` on gitea's searches of code, of issues and pull requests, and of
|
||||
commits. A code search holds code, such as `<script>`,
|
||||
`SELECT * FROM users WHERE` or `../`.
|
||||
- `Referer` of a page opened from such a search, for script and SQL
|
||||
injection and Java code (941110, 941120, 941160, 942100, 944100).
|
||||
- `q` on gitea's searches for a name, for the names of system files and
|
||||
commands (930120, 932120, 932260). Names such as `.profile` and
|
||||
`python3-app` were refused. gitea searches for the names of:
|
||||
- repositories;
|
||||
- users and organisations;
|
||||
- branches and tags;
|
||||
- packages.
|
||||
|
||||
Some of these searches also skip the rule for Java class names (944130),
|
||||
which refused `org.apache.commons.logging`.
|
||||
|
||||
- The path of these requests, which names a file:
|
||||
- a file's page;
|
||||
- its raw file;
|
||||
- its download;
|
||||
- its blame page;
|
||||
- its history;
|
||||
- its edit page;
|
||||
- its preview in the editor;
|
||||
- its delete page;
|
||||
- the API's call for its contents;
|
||||
- a release attachment's download.
|
||||
|
||||
Names such as `notes.txt~`, `process.env.d.ts` and `java.lang.String.md`
|
||||
were refused.
|
||||
|
||||
- A file name in a query parameter:
|
||||
- `file` of a commit graph;
|
||||
- `path` of the API's list of commits;
|
||||
- `path` of a diff's hidden lines;
|
||||
- `body` of the API's call for several files;
|
||||
- `template` of a new issue;
|
||||
- `redirect_to` of the sign-in page;
|
||||
- `name` of an attachment uploaded through the API.
|
||||
- A branch or tag name in a query parameter, for command names (932260).
|
||||
gitea sends one:
|
||||
- to delete or restore a branch;
|
||||
- to start a release from a tag;
|
||||
- to edit a branch protection rule;
|
||||
- to list a directory's last commits.
|
||||
- The `Content-Range` header of an artifact upload from
|
||||
`actions/upload-artifact@v3` (920450).
|
||||
|
||||
Elsewhere these fields keep every rule. The paths are those of gitea at the
|
||||
site root. An app other than gitea that serves one of them must check these
|
||||
fields itself.
|
||||
|
||||
The parameter and cookie names in these changes are matched without regard to
|
||||
case, as Coraza matches them.
|
||||
|
||||
Reference in new issue
Block a user