SWW_APPS: an app's Core Rule Set fixes apply only to the hostnames that serve it (closes #220)
check / check (push) Failing after 25m20s
check / check (push) Failing after 25m20s
Each app's fixes are one .conf file and one entry in apps. They apply only while Inspect has set the app's transaction variable, such as tx.app_gitea. SWW_APPS names each hostname's apps. A hostname gets only its apps' fixes; while SWW_APPS is unset, every hostname gets every app's fixes. A hostname in SWW_APPS that is not a DNS name, such as *.example.com, stops the start. Unset, SWW_APPS is logged at start as null; set empty, as "". Model: opus-5-5
This commit is contained in:
1 parent
56d6a12cc2
commit
348b881818
15 files changed
+963
-375
No files matched your search
@@ -81,8 +81,8 @@ 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/coreruleset`: the Core Rule Set, with the eleven changes listed
|
||||
under "Attack detection", as Coraza directives.
|
||||
- `internal/coreruleset`: the Core Rule Set, with the six changes and the
|
||||
apps' fixes listed under "Attack detection", as Coraza directives.
|
||||
- `internal/lookup`: looks clients up through GeoJS or in the lookup
|
||||
database.
|
||||
- `internal/reputation`: fetches the lists, asks the DNS blocklists and
|
||||
@@ -676,8 +676,8 @@ files, the limits and the bans still apply to the client that sends it.
|
||||
- `SWW_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 `SWW_WAF_DISABLED_RULES` switches it off everywhere. The file
|
||||
holds an app's own exclusions; the eighth to eleventh changes below hold
|
||||
gitea's, WordPress's, Drupal's and MediaWiki's.
|
||||
holds an app's own exclusions; the apps' fixes below hold gitea's,
|
||||
WordPress's, Drupal's and MediaWiki's.
|
||||
- `discriminator` 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.
|
||||
@@ -723,9 +723,9 @@ 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 eleven ways, since in front of
|
||||
gitea, WordPress, Drupal and MediaWiki it would otherwise refuse ordinary
|
||||
requests. The changes hold in front of every app, and no setting undoes them:
|
||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in six 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:
|
||||
|
||||
1. `PUT`, `PATCH` and `DELETE` are allowed methods besides `GET`, `HEAD`, `POST`
|
||||
and `OPTIONS`. APIs, container image pushes and package uploads use them.
|
||||
@@ -742,8 +742,52 @@ requests. The changes hold in front of every app, and no setting undoes them:
|
||||
and tea, which gitea registers for OAuth sign-in, ask to be sent back to
|
||||
`http://127.0.0.1` on the user's own machine. The server never fetches that
|
||||
address.
|
||||
4. Ten query parameters are not checked against the Core Rule Set's lists of
|
||||
system files (930120), shell paths (932160) and command names (932260):
|
||||
4. `Referer` is not checked for a Unix command given without arguments (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 (gitea's fixes). An app that passes
|
||||
`Referer` to a shell must check it itself.
|
||||
|
||||
5. 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.
|
||||
6. 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.
|
||||
|
||||
Each supported app also has its own fixes, which let its ordinary requests
|
||||
through. `SWW_APPS` says which hostnames get which app's fixes:
|
||||
|
||||
- `SWW_APPS` holds entries separated by semicolons. Each is a hostname, a colon,
|
||||
then one or more apps separated by commas, for example
|
||||
`git.example.com:gitea;blog.example.com:wordpress`.
|
||||
- The request's `Host` is matched by exact name, without its port and without
|
||||
regard to case. There are no wildcards.
|
||||
- A hostname not listed gets no app's fixes, so every rule checks it in full.
|
||||
Set empty, `SWW_APPS` lists no hostname.
|
||||
- Unset, every app's fixes hold for every hostname. An app's fixes then weaken
|
||||
the check of any other app that serves the same paths or fields.
|
||||
- Any of these mistakes stops the start:
|
||||
- an unknown app;
|
||||
- a hostname that is not a DNS name, such as `*.example.com`;
|
||||
- a hostname listed twice;
|
||||
- an app listed twice for one hostname;
|
||||
- an entry without a colon.
|
||||
|
||||
The apps supported are `drupal`, `gitea`, `mediawiki` and `wordpress`. Each
|
||||
app's fixes are in one file, such as `internal/coreruleset/gitea.conf`, and one
|
||||
entry of `apps` in `internal/coreruleset/coreruleset.go`. gitea's fixes are:
|
||||
|
||||
1. Ten query parameters are not checked against the Core Rule Set's lists of
|
||||
system files (930120), shell paths (932160) and command names (932260), on
|
||||
any path:
|
||||
- `path`, `files`, `skip-to` and `sub_path`;
|
||||
- `ref`, `sha`, `branch` and `workflow`;
|
||||
- `artifactName` and `redirect_to`.
|
||||
@@ -756,42 +800,19 @@ requests. The changes hold in front of every app, and no setting undoes them:
|
||||
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. Other parameters keep all three rules, except on the
|
||||
gitea, WordPress, Drupal and MediaWiki paths the eighth to eleventh changes
|
||||
name. 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.
|
||||
paths named in gitea's third fix, in WordPress's fixes, in Drupal's fixes
|
||||
and in MediaWiki's fixes.
|
||||
|
||||
5. Two cookies are left out, and `Referer` keeps fewer rules:
|
||||
- The Core Rule Set reads the request without the `gitea_flash` and
|
||||
`redirect_to` cookies. gitea puts a message naming what was just done into
|
||||
`gitea_flash`. It puts into `redirect_to` the page to return to after
|
||||
signing in. The Core Rule Set takes file names in them, such as
|
||||
`package.json`, for attacks. A browser sends such a cookie with every
|
||||
request until gitea replaces it. gitea cannot replace it while those
|
||||
requests are refused, so one refusal would keep the browser out of the
|
||||
whole site. gitea shows the message with any script removed and returns
|
||||
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), 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
|
||||
2. The Core Rule Set reads the request without the `gitea_flash` and
|
||||
`redirect_to` cookies. gitea puts a message naming what was just done into
|
||||
`gitea_flash`. It puts into `redirect_to` the page to return to after signing
|
||||
in. The Core Rule Set takes file names in them, such as `package.json`, for
|
||||
attacks. A browser sends such a cookie with every request until gitea
|
||||
replaces it. gitea cannot replace it while those requests are refused, so one
|
||||
refusal would keep the browser out of the whole site. gitea shows the message
|
||||
with any script removed and returns only to its own pages. Every other cookie
|
||||
is read in full.
|
||||
3. 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/coreruleset/gitea.conf` lists each rule and the
|
||||
request it refused. The fields are:
|
||||
@@ -809,8 +830,7 @@ requests. The changes hold in front of every app, and no setting undoes them:
|
||||
- packages.
|
||||
|
||||
A user's or an organisation's page is any path of one segment, so on
|
||||
every such path, on any app, `q` skips these three rules, for example on
|
||||
`/search`.
|
||||
every such path `q` skips these three rules, for example on `/search`.
|
||||
|
||||
Some of these searches also skip the rule for Java class names (944130),
|
||||
which refused `org.apache.commons.logging`.
|
||||
@@ -848,231 +868,230 @@ requests. The changes hold in front of every app, and no setting undoes them:
|
||||
`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.
|
||||
site root.
|
||||
|
||||
9. On WordPress's paths, some fields skip the rules that refused ordinary
|
||||
WordPress requests there. `internal/coreruleset/wordpress.conf` lists each
|
||||
rule and the request it refused. The REST API has four addresses:
|
||||
- `/wp-json/...`
|
||||
- `/index.php/wp-json/...`
|
||||
- `/index.php?rest_route=/...`
|
||||
- `/?rest_route=/...`
|
||||
WordPress's fixes: on WordPress's paths, some fields skip the rules that refused
|
||||
ordinary WordPress requests there. `internal/coreruleset/wordpress.conf` lists
|
||||
each rule and the request it refused. The REST API has four addresses:
|
||||
|
||||
The fields are:
|
||||
- The header `X-HTTP-Method-Override` on any address of the REST API
|
||||
(920450). The block editor saves a post with `POST` and names `PUT` in
|
||||
this header.
|
||||
- Three groups of fields skip the rules on system files and commands
|
||||
(930120, 932120, 932250, 932260). The fields hold searches, names and
|
||||
addresses of WordPress's own pages, and any of them can hold any word. The
|
||||
groups are:
|
||||
- On all of `/wp-admin/` and on `/wp-login.php`:
|
||||
- the searches `s`, `search`, `q` and `term`;
|
||||
- the names `tag`, `category_name`, `plugin`, `checked[]`, `theme`
|
||||
and `stylesheet`;
|
||||
- the name of a plugin's settings page in `page`;
|
||||
- the addresses `url`, `return`, `redirect_to`, `wp_http_referer`
|
||||
and `_wp_http_referer`.
|
||||
- On every REST API route under `/wp/v2/` and on the route
|
||||
`/oembed/1.0/embed`: `search`, `term`, `slug` and `url`.
|
||||
- On `/`, `/index.php`, `/page/N/` and `/index.php/page/N/`: `s` and
|
||||
`tag`.
|
||||
- `/wp-json/...`
|
||||
- `/index.php/wp-json/...`
|
||||
- `/index.php?rest_route=/...`
|
||||
- `/?rest_route=/...`
|
||||
|
||||
The addresses of the first group also skip the rule on Unix commands
|
||||
(932235), because an address repeats the search it came from. The other
|
||||
fields of the groups keep that rule.
|
||||
The fields are:
|
||||
|
||||
- On all of `/wp-admin/` and on `/wp-login.php`, these names skip the lists
|
||||
of PowerShell commands and command names (932120, 932260):
|
||||
- the name of a template in `p` and `postId` of the site editor;
|
||||
- the name of a plugin to install in `slug`.
|
||||
- The header `X-HTTP-Method-Override` on any address of the REST API (920450).
|
||||
The block editor saves a post with `POST` and names `PUT` in this header.
|
||||
- Three groups of fields skip the rules on system files and commands (930120,
|
||||
932120, 932250, 932260). The fields hold searches, names and addresses of
|
||||
WordPress's own pages, and any of them can hold any word. The groups are:
|
||||
- On all of `/wp-admin/` and on `/wp-login.php`:
|
||||
- the searches `s`, `search`, `q` and `term`;
|
||||
- the names `tag`, `category_name`, `plugin`, `checked[]`, `theme` and
|
||||
`stylesheet`;
|
||||
- the name of a plugin's settings page in `page`;
|
||||
- the addresses `url`, `return`, `redirect_to`, `wp_http_referer` and
|
||||
`_wp_http_referer`.
|
||||
- On every REST API route under `/wp/v2/` and on the route
|
||||
`/oembed/1.0/embed`: `search`, `term`, `slug` and `url`.
|
||||
- On `/`, `/index.php`, `/page/N/` and `/index.php/page/N/`: `s` and `tag`.
|
||||
|
||||
WordPress writes these names as slugs, such as `htaccess` and `ls-la`.
|
||||
The addresses of the first group also skip the rule on Unix commands
|
||||
(932235), because an address repeats the search it came from. The other
|
||||
fields of the groups keep that rule.
|
||||
|
||||
- `url` on the REST API routes `/wp-block-editor/v1/url-details` and
|
||||
`/oembed/1.0/proxy`, for the lists of system files and PowerShell commands
|
||||
(930120, 932120). The block editor's link previews and embeds send an
|
||||
address in this field.
|
||||
- On all of `/wp-admin/` and on `/wp-login.php`, these names skip the lists of
|
||||
PowerShell commands and command names (932120, 932260):
|
||||
- the name of a template in `p` and `postId` of the site editor;
|
||||
- the name of a plugin to install in `slug`.
|
||||
|
||||
- `_wp_http_referer` on `/wp-admin/upload.php`, for a Unix command given
|
||||
without arguments (932340). The media list's own address ends in `&ps`.
|
||||
- `file` on `/wp-admin/plugin-editor.php` and `/wp-admin/theme-editor.php`,
|
||||
for the lists of system files, shell paths, command names and JavaScript
|
||||
names (930120, 932120, 932160, 932260, 941180).
|
||||
- These fields of a body. Each applies only when the query has no parameter
|
||||
of that name, so it matters only while `SWW_WAF_BODY_LIMIT` is set:
|
||||
- `content` of a post, a page, a template or a template part saved
|
||||
through the REST API. It holds HTML and any code it shows.
|
||||
- `content` of a reply to a comment sent to `admin-ajax.php`.
|
||||
- `newcontent` of a plugin's or a theme's file saved from its editor,
|
||||
which is PHP.
|
||||
- `pwd` when signing in, for the list of system files (930120).
|
||||
- `title`, `excerpt` and `name` in a JSON body sent to any REST API
|
||||
route under `/wp/v2/`, for the rules on system files and commands
|
||||
(930120, 932120, 932250, 932260).
|
||||
- `slug` in a JSON body sent to any REST API route under `/wp/v2/`, for
|
||||
the lists of PowerShell commands and command names (932120, 932260).
|
||||
- `url` on `/wp-comments-post.php`, the address of a commenter's site,
|
||||
for the lists of system files and PowerShell commands (930120,
|
||||
932120).
|
||||
WordPress writes these names as slugs, such as `htaccess` and `ls-la`.
|
||||
|
||||
Elsewhere this change does not apply. The paths are those of WordPress at
|
||||
the site root. An app other than WordPress that serves one of them must
|
||||
check these fields itself.
|
||||
- `url` on the REST API routes `/wp-block-editor/v1/url-details` and
|
||||
`/oembed/1.0/proxy`, for the lists of system files and PowerShell commands
|
||||
(930120, 932120). The block editor's link previews and embeds send an address
|
||||
in this field.
|
||||
|
||||
10. On Drupal's paths, some fields skip the rules that refused ordinary Drupal
|
||||
requests there. `internal/coreruleset/drupal.conf` lists each rule and the
|
||||
request it refused. These query fields skip the lists of system files and
|
||||
command names (930120, 932120, 932250, 932260):
|
||||
- On every page under `/admin`: `title`, `name`, `user`, `filename`,
|
||||
`filemime`, `info`, `subject`, `author_name`, `search`, `q` and
|
||||
`destination`.
|
||||
- `destination` on the pages Drupal links to with one, such as these:
|
||||
- `/node/1/edit`;
|
||||
- `/user/login`;
|
||||
- `/node/1/revisions/2/revert`;
|
||||
- `/block/add/basic`;
|
||||
- `/big_pipe/no-js`.
|
||||
- `keys` on `/search` and the pages under it.
|
||||
- `q` on these autocompletes:
|
||||
- `/entity_reference_autocomplete/`;
|
||||
- `/ckeditor5/{editor}/entity-link-suggestions`;
|
||||
- `/block-category/autocomplete`.
|
||||
- Every `filter[...]` field on `/jsonapi/`.
|
||||
- `name` on `/user/password`, `/media-library` and `/views/ajax`, in the
|
||||
query or a body.
|
||||
- `_wp_http_referer` on `/wp-admin/upload.php`, for a Unix command given without
|
||||
arguments (932340). The media list's own address ends in `&ps`.
|
||||
- `file` on `/wp-admin/plugin-editor.php` and `/wp-admin/theme-editor.php`, for
|
||||
the lists of system files, shell paths, command names and JavaScript names
|
||||
(930120, 932120, 932160, 932260, 941180).
|
||||
- These fields of a body. Each applies only when the query has no parameter of
|
||||
that name, so it matters only while `SWW_WAF_BODY_LIMIT` is set:
|
||||
- `content` of a post, a page, a template or a template part saved through
|
||||
the REST API. It holds HTML and any code it shows.
|
||||
- `content` of a reply to a comment sent to `admin-ajax.php`.
|
||||
- `newcontent` of a plugin's or a theme's file saved from its editor, which
|
||||
is PHP.
|
||||
- `pwd` when signing in, for the list of system files (930120).
|
||||
- `title`, `excerpt` and `name` in a JSON body sent to any REST API route
|
||||
under `/wp/v2/`, for the rules on system files and commands (930120,
|
||||
932120, 932250, 932260).
|
||||
- `slug` in a JSON body sent to any REST API route under `/wp/v2/`, for the
|
||||
lists of PowerShell commands and command names (932120, 932260).
|
||||
- `url` on `/wp-comments-post.php`, the address of a commenter's site, for
|
||||
the lists of system files and PowerShell commands (930120, 932120).
|
||||
|
||||
`destination` also skips 932230 and 932235, because it holds the address of
|
||||
a page of results. `url` on `/media/oembed`, the address of a video, skips
|
||||
only 930120 and 932120.
|
||||
Elsewhere WordPress's fixes do not apply. The paths are those of WordPress at
|
||||
the site root.
|
||||
|
||||
These fields of a body skip the rules that refused them:
|
||||
- On the node, comment and media forms, for 930120, 932120, 932250 and
|
||||
932260:
|
||||
- the title;
|
||||
- the summary;
|
||||
- the tags;
|
||||
- the address;
|
||||
- the revision note;
|
||||
- the comment subject;
|
||||
- the media name;
|
||||
- the image text.
|
||||
- On the tag, custom block and contact forms, for the same four rules:
|
||||
- the tag's name and description;
|
||||
- the block description and body;
|
||||
- the subject and message of a contact message.
|
||||
- These fields through JSON:API, for the same four rules:
|
||||
- `title`;
|
||||
- `subject`;
|
||||
- `body.summary`;
|
||||
- `name`;
|
||||
- `revision_log`;
|
||||
- `info`;
|
||||
- `description.value`.
|
||||
- The title saved through Drupal's JSON format on `/node/{id}`, for the same
|
||||
four rules.
|
||||
- The body and comment body on the node and comment forms and through
|
||||
JSON:API, which hold HTML and any code it shows.
|
||||
- `name` and `pass` when signing in (930120, 932120, 932250, 932260).
|
||||
- `name` when resetting a password through Drupal's JSON format on
|
||||
`/user/password`, for the same four rules.
|
||||
- `mail` in that same reset, for 932120 and 932260 only.
|
||||
- `name` when signing up, editing an account and commenting without an
|
||||
account, for the same four rules.
|
||||
- `mail` on those forms, for 930120, 932120 and 932260 only.
|
||||
Drupal's fixes: on Drupal's paths, some fields skip the rules that refused
|
||||
ordinary Drupal requests there. `internal/coreruleset/drupal.conf` lists each
|
||||
rule and the request it refused. These query fields skip the lists of system
|
||||
files and command names (930120, 932120, 932250, 932260):
|
||||
|
||||
These exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None applies
|
||||
when the query has a parameter of the same name.
|
||||
- On every page under `/admin`: `title`, `name`, `user`, `filename`, `filemime`,
|
||||
`info`, `subject`, `author_name`, `search`, `q` and `destination`.
|
||||
- `destination` on the pages Drupal links to with one, such as these:
|
||||
- `/node/1/edit`;
|
||||
- `/user/login`;
|
||||
- `/node/1/revisions/2/revert`;
|
||||
- `/block/add/basic`;
|
||||
- `/big_pipe/no-js`.
|
||||
- `keys` on `/search` and the pages under it.
|
||||
- `q` on these autocompletes:
|
||||
- `/entity_reference_autocomplete/`;
|
||||
- `/ckeditor5/{editor}/entity-link-suggestions`;
|
||||
- `/block-category/autocomplete`.
|
||||
- Every `filter[...]` field on `/jsonapi/`.
|
||||
- `name` on `/user/password`, `/media-library` and `/views/ajax`, in the query
|
||||
or a body.
|
||||
|
||||
Elsewhere these fields keep every rule. The paths are those of Drupal at the
|
||||
site root, with or without a language prefix such as `/fr`. Such a prefix is
|
||||
any first path segment of two or three lowercase letters, optionally
|
||||
followed by a hyphen and more letters, so `/api` counts too. An app other
|
||||
than Drupal that serves one of them must check these fields itself.
|
||||
`destination` also skips 932230 and 932235, because it holds the address of a
|
||||
page of results. `url` on `/media/oembed`, the address of a video, skips only
|
||||
930120 and 932120.
|
||||
|
||||
11. On MediaWiki's paths, some fields skip the rules that refused ordinary
|
||||
MediaWiki requests there. `internal/coreruleset/mediawiki.conf` lists each
|
||||
rule and the request it refused. These fields skip the lists of system files
|
||||
and command names (930120, 932120, 932250, 932260), in the query or the
|
||||
body:
|
||||
- On MediaWiki's pages, which are `/index.php` and the paths under
|
||||
`/index.php/` and `/wiki/`:
|
||||
- the searches `search` and `ilsearch`;
|
||||
- the titles `title`, `page` and `target`;
|
||||
- `from`, `to` and `prefix`, which limit a list of pages;
|
||||
- the user names `user`, `username` and `wpTarget`;
|
||||
- the file names `filename` and `wpDestFile`;
|
||||
- `returnto` and `returntoquery`, the page and query to go back to after
|
||||
signing in.
|
||||
- On `/api.php`:
|
||||
- the searches `search`, `srsearch` and `pssearch`;
|
||||
- the titles `titles`, `title`, `page` and `bltitle`;
|
||||
- `from` and `to`, the titles of a page being moved;
|
||||
- the starts of lists `apfrom`, `apto`, `apprefix`, `aifrom`,
|
||||
`aiprefix`, `aufrom` and `auprefix`;
|
||||
- `letitle`, the page whose log is listed;
|
||||
- `euquery`, an address;
|
||||
- the fields a generator sends in place of the fields above, each with a
|
||||
`g` in front:
|
||||
- `gsrsearch` and `gpssearch`;
|
||||
- `gapfrom`, `gapto` and `gapprefix`;
|
||||
- `gaifrom` and `gaiprefix`;
|
||||
- `gbltitle`;
|
||||
- `geuquery`;
|
||||
- the user names `ucuser`, `bkusers` and `user`;
|
||||
- `summary`, `sectiontitle`, `filename`, `comment` and `reason`;
|
||||
- `lgname`, `lgpassword`, `username` and `password`, for signing in.
|
||||
- `q` on `/rest.php/` and the paths under it.
|
||||
These fields of a body skip the rules that refused them:
|
||||
|
||||
`modules` on `/load.php` skips 930120 alone, because it lists the scripts
|
||||
and styles a page loads.
|
||||
- On the node, comment and media forms, for 930120, 932120, 932250 and 932260:
|
||||
- the title;
|
||||
- the summary;
|
||||
- the tags;
|
||||
- the address;
|
||||
- the revision note;
|
||||
- the comment subject;
|
||||
- the media name;
|
||||
- the image text.
|
||||
- On the tag, custom block and contact forms, for the same four rules:
|
||||
- the tag's name and description;
|
||||
- the block description and body;
|
||||
- the subject and message of a contact message.
|
||||
- These fields through JSON:API, for the same four rules:
|
||||
- `title`;
|
||||
- `subject`;
|
||||
- `body.summary`;
|
||||
- `name`;
|
||||
- `revision_log`;
|
||||
- `info`;
|
||||
- `description.value`.
|
||||
- The title saved through Drupal's JSON format on `/node/{id}`, for the same
|
||||
four rules.
|
||||
- The body and comment body on the node and comment forms and through JSON:API,
|
||||
which hold HTML and any code it shows.
|
||||
- `name` and `pass` when signing in (930120, 932120, 932250, 932260).
|
||||
- `name` when resetting a password through Drupal's JSON format on
|
||||
`/user/password`, for the same four rules.
|
||||
- `mail` in that same reset, for 932120 and 932260 only.
|
||||
- `name` when signing up, editing an account and commenting without an account,
|
||||
for the same four rules.
|
||||
- `mail` on those forms, for 930120, 932120 and 932260 only.
|
||||
|
||||
These fields of a body skip the rules that refused them:
|
||||
- On MediaWiki's pages, for the same four rules:
|
||||
- `wpSummary`, the summary of an edit;
|
||||
- `wpUploadDescription`, the description of an uploaded file;
|
||||
- `wpName` and `wpPassword`, for signing in;
|
||||
- `wpOldTitle`, `wpNewTitleMain` and `wpReason`, for moving a page.
|
||||
- `comment` in the JSON body of `/rest.php/`, for the same four rules.
|
||||
- On MediaWiki's pages, for 930120 and 932120 alone, the reasons on the
|
||||
admin pages:
|
||||
- `wpReason-other`, for blocking a user;
|
||||
- `user-reason`, for changing a user's groups;
|
||||
- `mwProtect-reason`, for protecting a page.
|
||||
- On MediaWiki's pages, `wpTitles`, the list of watched pages that
|
||||
`Special:EditWatchlist/raw` sends, one title per line. It always skips
|
||||
930120, 932120 and 932250. It skips 932125, 932230, 932235, 932260 and
|
||||
932380 only when it holds no `;`, `|`, `&`, backtick or `{`. A title
|
||||
starting with a command name, such as `Python3 notes`, passes. So does a
|
||||
command alone on a line, such as `wget http://example.com/x.sh`. A command
|
||||
such as `; wget http://example.com/x.sh` is still refused. So is a list
|
||||
that mixes a title holding one of these characters with a title starting
|
||||
with a command name.
|
||||
- The wikitext of a page, which holds templates, tables and any code it
|
||||
shows:
|
||||
- `wpTextbox1` on MediaWiki's pages;
|
||||
- `text`, `appendtext` and `prependtext` on `/api.php`;
|
||||
- `source` in the JSON body of `/rest.php/`.
|
||||
These exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None applies
|
||||
when the query has a parameter of the same name.
|
||||
|
||||
These body exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None
|
||||
applies when the query has a parameter of the same name.
|
||||
Elsewhere these fields keep every rule. The paths are those of Drupal at the
|
||||
site root, with or without a language prefix such as `/fr`. Such a prefix is any
|
||||
first path segment of two or three lowercase letters, optionally followed by a
|
||||
hyphen and more letters, so `/api` counts too.
|
||||
|
||||
The names of uploaded files skip 932180 on MediaWiki's pages and on
|
||||
`/api.php`, so a picture named `Notes on .htaccess.png` can be uploaded.
|
||||
MediaWiki refuses a file whose extension it does not allow.
|
||||
MediaWiki's fixes: on MediaWiki's paths, some fields skip the rules that refused
|
||||
ordinary MediaWiki requests there. `internal/coreruleset/mediawiki.conf` lists
|
||||
each rule and the request it refused. These fields skip the lists of system
|
||||
files and command names (930120, 932120, 932250, 932260), in the query or the
|
||||
body:
|
||||
|
||||
`/index.php` itself counts as MediaWiki's only when its query has a `title`,
|
||||
as in `/index.php?title=Main_Page`. WordPress serves `/index.php` too. A
|
||||
wiki without short URLs serves its pages under `/index.php/`, as in
|
||||
`/index.php/Main_Page`, and its sign-in and upload forms post there.
|
||||
- On MediaWiki's pages, which are `/index.php` and the paths under `/index.php/`
|
||||
and `/wiki/`:
|
||||
- the searches `search` and `ilsearch`;
|
||||
- the titles `title`, `page` and `target`;
|
||||
- `from`, `to` and `prefix`, which limit a list of pages;
|
||||
- the user names `user`, `username` and `wpTarget`;
|
||||
- the file names `filename` and `wpDestFile`;
|
||||
- `returnto` and `returntoquery`, the page and query to go back to after
|
||||
signing in.
|
||||
- On `/api.php`:
|
||||
- the searches `search`, `srsearch` and `pssearch`;
|
||||
- the titles `titles`, `title`, `page` and `bltitle`;
|
||||
- `from` and `to`, the titles of a page being moved;
|
||||
- the starts of lists `apfrom`, `apto`, `apprefix`, `aifrom`, `aiprefix`,
|
||||
`aufrom` and `auprefix`;
|
||||
- `letitle`, the page whose log is listed;
|
||||
- `euquery`, an address;
|
||||
- the fields a generator sends in place of the fields above, each with a `g`
|
||||
in front:
|
||||
- `gsrsearch` and `gpssearch`;
|
||||
- `gapfrom`, `gapto` and `gapprefix`;
|
||||
- `gaifrom` and `gaiprefix`;
|
||||
- `gbltitle`;
|
||||
- `geuquery`;
|
||||
- the user names `ucuser`, `bkusers` and `user`;
|
||||
- `summary`, `sectiontitle`, `filename`, `comment` and `reason`;
|
||||
- `lgname`, `lgpassword`, `username` and `password`, for signing in.
|
||||
- `q` on `/rest.php/` and the paths under it.
|
||||
|
||||
Elsewhere these fields keep every rule. The paths are those of MediaWiki at
|
||||
the site root or under `/w/`. An app other than MediaWiki that serves one of
|
||||
them must check these fields itself.
|
||||
`modules` on `/load.php` skips 930120 alone, because it lists the scripts and
|
||||
styles a page loads.
|
||||
|
||||
The parameter and cookie names in these changes are matched without regard to
|
||||
case, as Coraza matches them.
|
||||
These fields of a body skip the rules that refused them:
|
||||
|
||||
- On MediaWiki's pages, for the same four rules:
|
||||
- `wpSummary`, the summary of an edit;
|
||||
- `wpUploadDescription`, the description of an uploaded file;
|
||||
- `wpName` and `wpPassword`, for signing in;
|
||||
- `wpOldTitle`, `wpNewTitleMain` and `wpReason`, for moving a page.
|
||||
- `comment` in the JSON body of `/rest.php/`, for the same four rules.
|
||||
- On MediaWiki's pages, for 930120 and 932120 alone, the reasons on the admin
|
||||
pages:
|
||||
- `wpReason-other`, for blocking a user;
|
||||
- `user-reason`, for changing a user's groups;
|
||||
- `mwProtect-reason`, for protecting a page.
|
||||
- On MediaWiki's pages, `wpTitles`, the list of watched pages that
|
||||
`Special:EditWatchlist/raw` sends, one title per line. It always skips 930120,
|
||||
932120 and 932250. It skips 932125, 932230, 932235, 932260 and 932380 only
|
||||
when it holds no `;`, `|`, `&`, backtick or `{`. A title starting with a
|
||||
command name, such as `Python3 notes`, passes. So does a command alone on a
|
||||
line, such as `wget http://example.com/x.sh`. A command such as
|
||||
`; wget http://example.com/x.sh` is still refused. So is a list that mixes a
|
||||
title holding one of these characters with a title starting with a command
|
||||
name.
|
||||
- The wikitext of a page, which holds templates, tables and any code it shows:
|
||||
- `wpTextbox1` on MediaWiki's pages;
|
||||
- `text`, `appendtext` and `prependtext` on `/api.php`;
|
||||
- `source` in the JSON body of `/rest.php/`.
|
||||
|
||||
These body exclusions matter only while `SWW_WAF_BODY_LIMIT` is set. None
|
||||
applies when the query has a parameter of the same name.
|
||||
|
||||
The names of uploaded files skip 932180 on MediaWiki's pages and on `/api.php`,
|
||||
so a picture named `Notes on .htaccess.png` can be uploaded. MediaWiki refuses a
|
||||
file whose extension it does not allow.
|
||||
|
||||
`/index.php` itself counts as MediaWiki's only when its query has a `title`, as
|
||||
in `/index.php?title=Main_Page`. WordPress serves `/index.php` too. A wiki
|
||||
without short URLs serves its pages under `/index.php/`, as in
|
||||
`/index.php/Main_Page`, and its sign-in and upload forms post there.
|
||||
|
||||
Elsewhere these fields keep every rule. The paths are those of MediaWiki at the
|
||||
site root or under `/w/`.
|
||||
|
||||
Each app's fixes switch rules off for some of its fields and cookies. Any other
|
||||
app on a hostname that gets those fixes must check those fields and cookies
|
||||
itself.
|
||||
|
||||
The parameter names in these changes and fixes are matched without regard to
|
||||
case, and the cookie names exactly.
|
||||
|
||||
### Ban lengths, response and scope
|
||||
|
||||
|
||||
Reference in new issue
Block a user