Core Rule Set: Ghost's ordinary requests pass by default (closes #357)
check / check (push) Waiting to run
check / check (push) Waiting to run
Ghost 6.76.0's ordinary traffic, recorded in `testdata/ghost-requests.txt`, passes at the default settings and while bodies are read. It covers public pages, members' sign-up and sign-in, the admin, the editor saving and publishing posts and pages with code blocks and HTML cards, tags, settings, staff invitations, uploads, newsletter settings, and both APIs. The new `ghost.conf`, the sixteenth change, lets through `filter`, the member `search` and the embed `url` in the query, and plain text, addresses, articles, code injection and passwords in JSON bodies. A `<script>` element and a `javascript:` link stay refused in articles and code injection. `README.md` lists Ghost; `SPEC.md` lists the change. Model: opus-5-5
This commit is contained in:
1 parent
b6aa2cbc4b
commit
7c9e29113c
8 files changed
+1410
-13
No files matched your search
@@ -84,7 +84,7 @@ never as a time.
|
||||
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 fifteen changes listed
|
||||
- `internal/coreruleset`: the Core Rule Set, with the sixteen changes listed
|
||||
under "Attack detection", as Coraza directives.
|
||||
- `internal/lookup`: looks clients up through GeoJS or in the lookup
|
||||
database.
|
||||
@@ -681,7 +681,7 @@ 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 fifteenth changes below hold
|
||||
holds an app's own exclusions. The eighth to sixteenth changes below hold
|
||||
those of the apps they name.
|
||||
- `waf` loads the file after `smallwebwaf`'s own setup rules and before the
|
||||
Core Rule Set's rules. The Core Rule Set loads its own
|
||||
@@ -728,7 +728,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 fifteen ways. Without them, it
|
||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in sixteen ways. Without them, it
|
||||
would refuse ordinary requests to these apps:
|
||||
|
||||
- gitea;
|
||||
@@ -738,7 +738,8 @@ would refuse ordinary requests to these apps:
|
||||
- MediaWiki;
|
||||
- Mastodon;
|
||||
- Vaultwarden;
|
||||
- Nextcloud.
|
||||
- Nextcloud;
|
||||
- Ghost.
|
||||
|
||||
The changes hold in front of every app, and no setting undoes them:
|
||||
|
||||
@@ -774,7 +775,7 @@ 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. The eighth to
|
||||
fifteenth changes switch some of them off for some fields on the paths of
|
||||
sixteenth changes switch some of them off for some fields on the paths of
|
||||
the apps they 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.
|
||||
@@ -1586,6 +1587,69 @@ The changes hold in front of every app, and no setting undoes them:
|
||||
at the site root. An app other than Forgejo that serves such a path must
|
||||
check `q` itself.
|
||||
|
||||
16. On Ghost's paths, some fields skip the rules that refused ordinary Ghost
|
||||
requests there. `internal/coreruleset/ghost.conf` lists each rule and the
|
||||
request it refused. Ghost's admin and integrations call the Admin API under
|
||||
`/ghost/api/admin/`. Themes and Ghost's scripts call the Content API under
|
||||
`/ghost/api/content/`, and members call `/members/api/`.
|
||||
|
||||
Three query fields skip some rules:
|
||||
- `filter`, a query in Ghost's own filter language, skips 932120 on the
|
||||
Admin API and the Content API, so `tag:powershell` passes;
|
||||
- `search`, a search for a member, skips 930120, 932120, 932250 and 932260
|
||||
on the Admin API;
|
||||
- `url`, the address the editor looks up for an embed or a bookmark, skips
|
||||
930120 and 932120.
|
||||
|
||||
The fields of JSON bodies where a person types plain text skip 930120,
|
||||
932120, 932125, 932230, 932250, 932260 and 932380. They are these fields of
|
||||
posts, pages, tags, labels, members, newsletters and snippets, on the Admin
|
||||
API:
|
||||
- `title`, `name` and `slug`;
|
||||
- a post's `tags` and a member's `labels`, by name or slug;
|
||||
- `custom_excerpt`, `description`, `note` and `sender_name`;
|
||||
- the `meta_`, `og_` and `twitter_` titles and descriptions.
|
||||
|
||||
A member's `name` at `/members/api/` skips them too. A member's `email`
|
||||
skips 930120, 932120 and 932260, at `/members/api/` and when the admin adds
|
||||
a member.
|
||||
|
||||
The articles carry HTML on purpose. These fields skip the rules the articles
|
||||
set off, such as the lists of commands for a code block, and the rules for
|
||||
HTML elements, event handlers and JavaScript for an HTML card:
|
||||
- `lexical`, which the editor saves, and `mobiledoc` and `html`, which
|
||||
integrations send, for posts and pages;
|
||||
- `lexical` and `mobiledoc` of snippets;
|
||||
- `footer_content` of newsletters.
|
||||
|
||||
Code injection, `codeinjection_head` and `codeinjection_foot` of posts and
|
||||
pages, skips the rules of plain text and four rules for HTML in a page's
|
||||
head. So does `value` at `/ghost/api/admin/settings/`, since the site's
|
||||
settings hold its code injection.
|
||||
|
||||
`<script>alert(1)</script>` and `javascript:alert(1)` are still refused in
|
||||
the articles and code injection (941110, 941170 and 941210). Path traversal
|
||||
and SQL and script injection are still refused in every field above.
|
||||
`; wget http://example.com/x.sh` is still refused in the query fields, the
|
||||
plain text and the addresses.
|
||||
|
||||
Coraza names a staff user's `profile_image` field
|
||||
`json.users.0.profile_image`. That name holds `.profile`, a file on the list
|
||||
of system files, so the name skips 930120 when a profile is saved.
|
||||
|
||||
The passwords skip each rule that random passwords set off. The numbers are
|
||||
in `internal/coreruleset/ghost.conf`. They are `password` when signing in,
|
||||
and the passwords sent when creating the first staff user, accepting an
|
||||
invitation, and resetting or changing a password. `' OR '1'='1`,
|
||||
`../../etc/passwd`, `; cat /etc/passwd` and `<img src=x onerror=x()>` sent
|
||||
as a password reach Ghost; `<script>alert(1)</script>` and
|
||||
`javascript:alert(1)` are still refused.
|
||||
|
||||
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 Ghost at the site root. An
|
||||
app other than Ghost 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