fix: keel-overlay-coraza: an audit log that names the rule, and Anubis's challenge by IP #27

Merged
marcos-mendez merged 3 commits from fix/web-waf-anubis-audit into 19.x 2026-10-02 02:34:13 -03:00
marcos-mendez commented 2026-10-02 00:35:03 -03:00 (Migrated from github.com)

Two Keel Web bugs from the maintainer's test screenshots, both in keel-overlay-coraza (0.1.2).

098: the WAF log did not name the rule

Nginx's error log only says Coraza: Access denied with code 403, unique_id "...". keel-rules.conf now has Coraza write /var/log/coraza/audit.log:

  • one JSON object per line (SecAuditLogFormat JSON, RelevantOnly), for each blocked request and for each 4xx or 5xx answer except 404;
  • parts A, B, H and Z only: the request line, the headers and the matches, never a body;
  • each matched rule appears in messages[].error_message in ModSecurity's format ([id "941100"] [msg "..."] [data "..."] [severity "..."]), so CrowdSec can parse it later;
  • transaction.id is the error log's unique_id.

The workers create the WAF and write the file as www-data. A worker that cannot open the file dies with its WAF, so the directory (www-data:adm 0750) comes from a tmpfiles.d entry and is made at every boot. Coraza keeps the file open, so logrotate copies and truncates it daily. A purge deletes it. A request served normally writes nothing, even when a rule only warned.

113: the WAF blocked Anubis's pass-challenge when the site is opened by IP

On a site opened by IP, Anubis's challenge page sends the browser to /.within.website/x/cmd/anubis/api/pass-challenge?...&redir=<the URL with the IP>. That reached the blocking score of 5 in two ways:

  • by IPv4, CRS 931100 ("Possible Remote File Inclusion (RFI) Attack: URL Parameter using IP Address", tag attack-rfi);
  • by IPv6, CRS 932130 ("Remote Command Execution: Unix Shell Expression Found"), which reads the brackets of https://[2001:db8::1]/ as a shell glob.

920350 ("Host header is a numeric IP") is not the cause: it only warns, with a score of 3, and the page by IP was served. The new keel-exclusions.conf is read before the rule set. On paths under /.within.website/ only, rule 10001 removes ARGS:redir from the attack-rfi rules and from 932130. No rule is turned off globally. Every other rule still reads redir, and every other argument and path keeps all the rules.

Evidence (LXC container of the step7b Web image, cloud_simple, these packages installed)

  • Before the fix, the audit log of a pass-challenge by IPv4 named 920350, then 931100, then 949110 (score 8). By IPv6 it named 920350, then 932130, then 949110.
  • After the fix, Chromium (playwright-core) passes the challenge over HTTPS by name, by IPv6 and by IPv4. pass-challenge answers 302 each time.
  • An XSS or SQLi URL gets 403, and the audit line names 941100/941110/941160/941390/949110, or 942100/942190/942270/942360/949110.
  • redir with an IP on /, another argument on Anubis's path, and <script> or ;cat /etc/passwd in redir all still get 403.
  • On the container, overlay-web.bats with these tests plus the Coraza on/off and gzip tests: 8/8 passed (with keel-web's front unlinked, as on the CI machine).

Test plan

  • packages / web (overlay-web.bats in the trixie LXC container) green
  • lintian clean in packages / build
  • Keel-Linux/keel-web PR (depends on keel-overlay-coraza 0.1.2) and Keel-Linux/anubis PR (1.27.0-0+keel2) reviewed together
Two Keel Web bugs from the maintainer's test screenshots, both in `keel-overlay-coraza` (0.1.2). ## 098: the WAF log did not name the rule Nginx's error log only says `Coraza: Access denied with code 403, unique_id "..."`. `keel-rules.conf` now has Coraza write `/var/log/coraza/audit.log`: - one JSON object per line (`SecAuditLogFormat JSON`, `RelevantOnly`), for each blocked request and for each 4xx or 5xx answer except 404; - parts A, B, H and Z only: the request line, the headers and the matches, never a body; - each matched rule appears in `messages[].error_message` in ModSecurity's format (`[id "941100"] [msg "..."] [data "..."] [severity "..."]`), so CrowdSec can parse it later; - `transaction.id` is the error log's `unique_id`. The workers create the WAF and write the file as `www-data`. A worker that cannot open the file dies with its WAF, so the directory (`www-data:adm 0750`) comes from a tmpfiles.d entry and is made at every boot. Coraza keeps the file open, so logrotate copies and truncates it daily. A purge deletes it. A request served normally writes nothing, even when a rule only warned. ## 113: the WAF blocked Anubis's pass-challenge when the site is opened by IP On a site opened by IP, Anubis's challenge page sends the browser to `/.within.website/x/cmd/anubis/api/pass-challenge?...&redir=<the URL with the IP>`. That reached the blocking score of 5 in two ways: - by IPv4, CRS **931100** ("Possible Remote File Inclusion (RFI) Attack: URL Parameter using IP Address", tag `attack-rfi`); - by IPv6, CRS **932130** ("Remote Command Execution: Unix Shell Expression Found"), which reads the brackets of `https://[2001:db8::1]/` as a shell glob. 920350 ("Host header is a numeric IP") is not the cause: it only warns, with a score of 3, and the page by IP was served. The new `keel-exclusions.conf` is read before the rule set. On paths under `/.within.website/` only, rule 10001 removes `ARGS:redir` from the `attack-rfi` rules and from 932130. No rule is turned off globally. Every other rule still reads `redir`, and every other argument and path keeps all the rules. ## Evidence (LXC container of the step7b Web image, cloud_simple, these packages installed) - Before the fix, the audit log of a pass-challenge by IPv4 named 920350, then 931100, then 949110 (score 8). By IPv6 it named 920350, then 932130, then 949110. - After the fix, Chromium (playwright-core) passes the challenge over HTTPS by name, by IPv6 and by IPv4. `pass-challenge` answers 302 each time. - An XSS or SQLi URL gets 403, and the audit line names 941100/941110/941160/941390/949110, or 942100/942190/942270/942360/949110. - `redir` with an IP on `/`, another argument on Anubis's path, and `<script>` or `;cat /etc/passwd` in `redir` all still get 403. - On the container, `overlay-web.bats` with these tests plus the Coraza on/off and gzip tests: 8/8 passed (with keel-web's front unlinked, as on the CI machine). ## Test plan - [ ] `packages / web` (overlay-web.bats in the trixie LXC container) green - [ ] lintian clean in `packages / build` - [ ] Keel-Linux/keel-web PR (depends on keel-overlay-coraza 0.1.2) and Keel-Linux/anubis PR (1.27.0-0+keel2) reviewed together
Sign in to join this conversation.
No description provided.