Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95b5c447ee |
No files matched your search
@@ -220,123 +220,123 @@ account, a key, a token or an alert destination stays off until you give one.
|
|||||||
|
|
||||||
Every setting the code reads, with its default:
|
Every setting the code reads, with its default:
|
||||||
|
|
||||||
| Variable | Default | What it does |
|
| Variable | Default | What it does |
|
||||||
| ---------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ---------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `SWW_COMMAND` | `rproxy` | Which command the image runs, and its health check checks: `rproxy` or `discriminator`. |
|
| `SWW_COMMAND` | `rproxy` | Which command the image runs, and its health check checks: `rproxy` or `discriminator`. |
|
||||||
| `SWRP_WAF_BACKEND` | required | `discriminator`'s URL, such as `http://discriminator:8080`. |
|
| `SWRP_WAF_BACKEND` | required | `discriminator`'s URL, such as `http://discriminator:8080`. |
|
||||||
| `SWRP_UPSTREAM_URL` | `http://127.0.0.1:8081` | The app's URL: a scheme, a host and an optional port, nothing more. |
|
| `SWRP_UPSTREAM_URL` | `http://127.0.0.1:8081` | The app's URL: a scheme, a host and an optional port, nothing more. |
|
||||||
| `SWRP_LISTEN_ADDR` | `:8080` | Where `rproxy` listens; leave the host part empty. |
|
| `SWRP_LISTEN_ADDR` | `:8080` | Where `rproxy` listens; leave the host part empty. |
|
||||||
| `SWRP_TRUSTED_PROXIES` | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` | The netblocks whose `X-Forwarded-For` `rproxy` believes; set but empty, it believes none. |
|
| `SWRP_TRUSTED_PROXIES` | `10.0.0.0/8,172.16.0.0/12,192.168.0.0/16` | The netblocks whose `X-Forwarded-For` `rproxy` believes; set but empty, it believes none. |
|
||||||
| `SWRP_TIMEOUT_MS` | `2000` | How long `rproxy` waits for `discriminator`'s answer to a question and to a report, in milliseconds. |
|
| `SWRP_TIMEOUT_MS` | `2000` | How long `rproxy` waits for `discriminator`'s answer to a question and to a report, in milliseconds. |
|
||||||
| `SWRP_DEFAULT_DISPOSITION` | `allow` | What `rproxy` does with a request when `discriminator` cannot be reached or does not answer in time: `allow` passes it to the app, `deny` answers `503`. |
|
| `SWRP_DEFAULT_DISPOSITION` | `allow` | What `rproxy` does with a request when `discriminator` cannot be reached or does not answer in time: `allow` passes it to the app, `deny` answers `503`. |
|
||||||
| `SWRP_MAX_REQUEST_SIZE` | `100M` | The largest request body, a size or `off`; a larger one is answered `413`. |
|
| `SWRP_MAX_REQUEST_SIZE` | `100M` | The largest request body, a size or `off`; a larger one is answered `413`. |
|
||||||
| `SWRP_MAX_RESPONSE_SIZE` | `1G` | The largest response body, a size or `off`. The visitor gets `502` in place of a larger one, or it is cut off if it has already started. |
|
| `SWRP_MAX_RESPONSE_SIZE` | `1G` | The largest response body, a size or `off`. The visitor gets `502` in place of a larger one, or it is cut off if it has already started. |
|
||||||
| `SWRP_MAX_REQUEST_TIME_MS` | `60000` | Two time limits, each this long, in milliseconds or `off`: one for the visitor to send its request line and headers, then one for the whole request to reach the app. |
|
| `SWRP_MAX_REQUEST_TIME_MS` | `60000` | Two time limits, each this long, in milliseconds or `off`: one for the visitor to send its request line and headers, then one for the whole request to reach the app. |
|
||||||
| `SWRP_MAX_RESPONSE_TIME_MS` | `1800000` | How long the answer may take, from the end of the request to its last byte reaching the visitor, in milliseconds or `off`. |
|
| `SWRP_MAX_RESPONSE_TIME_MS` | `1800000` | How long the answer may take, from the end of the request to its last byte reaching the visitor, in milliseconds or `off`. |
|
||||||
| `SWW_LISTEN_ADDR` | `:8080` | Where `discriminator` listens; leave the host part empty. |
|
| `SWW_LISTEN_ADDR` | `:8080` | Where `discriminator` listens; leave the host part empty. |
|
||||||
| `SWW_INSTANCE_NAME` | the container's host name | The name in every line `discriminator` logs, and in every alert and metric, such as `fsn1/discriminator`. |
|
| `SWW_INSTANCE_NAME` | the container's host name | The name in every line `discriminator` logs, and in every alert and metric, such as `fsn1/discriminator`. |
|
||||||
| `SWW_MODE` | `enforce` | `observe` refuses nothing and makes no ban; each log line says what `enforce` would have done. |
|
| `SWW_MODE` | `enforce` | `observe` refuses nothing and makes no ban; each log line says what `enforce` would have done. |
|
||||||
| `SWW_IPV6_GROUP_PREFIX` | `64` | The prefix length of the IPv6 netblock that counts as one client, from 32 to 128. |
|
| `SWW_IPV6_GROUP_PREFIX` | `64` | The prefix length of the IPv6 netblock that counts as one client, from 32 to 128. |
|
||||||
| `SWW_MAX_TRACKED_CLIENTS` | `20000` | The most clients kept, in memory and in `clients.json`; the least recently seen is dropped first. |
|
| `SWW_MAX_TRACKED_CLIENTS` | `20000` | The most clients kept, in memory and in `clients.json`; the least recently seen is dropped first. |
|
||||||
| `SWW_MAX_BANS` | `5000` | The most bans `discriminator` keeps of its own; bans an admin made do not count. |
|
| `SWW_MAX_BANS` | `5000` | The most bans `discriminator` keeps of its own; bans an admin made do not count. |
|
||||||
| `SWW_ALLOW_NETS` | empty | Netblocks whose clients skip every check, such as your monitoring. |
|
| `SWW_ALLOW_NETS` | empty | Netblocks whose clients skip every check, such as your monitoring. |
|
||||||
| `SWW_RATE_LIMIT_EXEMPT_NETS` | empty | Netblocks whose clients are exempt from rate limiting and the byte limits. |
|
| `SWW_RATE_LIMIT_EXEMPT_NETS` | empty | Netblocks whose clients are exempt from rate limiting and the byte limits. |
|
||||||
| `SWW_DENY_NETS` | empty | Netblocks whose clients are refused. |
|
| `SWW_DENY_NETS` | empty | Netblocks whose clients are refused. |
|
||||||
| `SWW_RATE_LIMIT_PER_MINUTE` | `120` | The most requests a client may make in a minute, a count or `off`; the next request is refused and bans the client. |
|
| `SWW_RATE_LIMIT_PER_MINUTE` | `120` | The most requests a client may make in a minute, a count or `off`; the next request is refused and bans the client. |
|
||||||
| `SWW_RATE_LIMIT_PER_HOUR` | `1500` | The most requests a client may make in an hour, a count or `off`; the next request is refused and bans the client. |
|
| `SWW_RATE_LIMIT_PER_HOUR` | `1500` | The most requests a client may make in an hour, a count or `off`; the next request is refused and bans the client. |
|
||||||
| `SWW_RATE_LIMIT_PER_DAY` | `6000` | The most requests a client may make in a day, a count or `off`; the next request is refused and bans the client. |
|
| `SWW_RATE_LIMIT_PER_DAY` | `6000` | The most requests a client may make in a day, a count or `off`; the next request is refused and bans the client. |
|
||||||
| `SWW_RATE_LIMIT_EXEMPT_PATHS` | empty | Path prefixes exempt from rate limiting and the byte limits, such as `/assets/`. |
|
| `SWW_RATE_LIMIT_EXEMPT_PATHS` | empty | Path prefixes exempt from rate limiting and the byte limits, such as `/assets/`. |
|
||||||
| `SWW_BYTES_LIMIT_PER_MINUTE` | `off` | The most bytes counted for a client in a minute, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
| `SWW_BYTES_LIMIT_PER_MINUTE` | `off` | The most bytes counted for a client in a minute, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
||||||
| `SWW_BYTES_LIMIT_PER_HOUR` | `50G` | The most bytes counted for a client in an hour, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
| `SWW_BYTES_LIMIT_PER_HOUR` | `50G` | The most bytes counted for a client in an hour, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
||||||
| `SWW_BYTES_LIMIT_PER_DAY` | `100G` | The most bytes counted for a client in a day, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
| `SWW_BYTES_LIMIT_PER_DAY` | `100G` | The most bytes counted for a client in a day, a size or `off`. `SWW_BYTES_COUNT` says which bytes count: response bodies, request bodies or both. The request that passes the limit is not cut off, and the client is banned when its response ends. |
|
||||||
| `SWW_BYTES_COUNT` | `both` | What the byte limits and the byte anomaly thresholds count: `response`, the app's response bodies; `request`, the visitors' request bodies; or `both`. What the visitor sent over a WebSocket counts as request bytes, and what the app sent as response bytes. |
|
| `SWW_BYTES_COUNT` | `both` | What the byte limits and the byte anomaly thresholds count: `response`, the app's response bodies; `request`, the visitors' request bodies; or `both`. What the visitor sent over a WebSocket counts as request bytes, and what the app sent as response bytes. |
|
||||||
| `SWW_ERROR_BURST_THRESHOLD` | `30` | The most refusals a client may get in a minute from a rule file, a trap path or the Core Rule Set, a count or `off`. The next one bans the client. |
|
| `SWW_ERROR_BURST_THRESHOLD` | `30` | The most refusals a client may get in a minute from a rule file, a trap path or the Core Rule Set, a count or `off`. The next one bans the client. |
|
||||||
| `SWW_BAN_RESPONSE` | `403` | How a refused client is answered: `403`, `429` or `close`, which drops the connection. |
|
| `SWW_BAN_RESPONSE` | `403` | How a refused client is answered: `403`, `429` or `close`, which drops the connection. |
|
||||||
| `SWW_LIMIT_BAN_DURATION` | `1h` | The ban for a first broken limit. |
|
| `SWW_LIMIT_BAN_DURATION` | `1h` | The ban for a first broken limit. |
|
||||||
| `SWW_LIMIT_BAN_REPEAT_WINDOW` | `24h` | A client that breaks a limit again within this time after its last such ban ended gets a ban three times as long. |
|
| `SWW_LIMIT_BAN_REPEAT_WINDOW` | `24h` | A client that breaks a limit again within this time after its last such ban ended gets a ban three times as long. |
|
||||||
| `SWW_MAX_BAN_DURATION` | `7d` | A ban for a broken limit that would be longer than this is permanent instead. |
|
| `SWW_MAX_BAN_DURATION` | `7d` | A ban for a broken limit that would be longer than this is permanent instead. |
|
||||||
| `SWW_ATTACK_BAN_DURATION` | `7d` | The ban for a first clear sign of attack: a `ban` rule or a trap path. |
|
| `SWW_ATTACK_BAN_DURATION` | `7d` | The ban for a first clear sign of attack: a `ban` rule or a trap path. |
|
||||||
| `SWW_BAN_SCOPE_V4_PREFIX` | `32` | The prefix length of the netblock a ban on an IPv4 client covers, from 0 to 32. |
|
| `SWW_BAN_SCOPE_V4_PREFIX` | `32` | The prefix length of the netblock a ban on an IPv4 client covers, from 0 to 32. |
|
||||||
| `SWW_LOOKUP_SOURCE` | `geojs` | Where each client's AS number and country come from: `geojs` (a web service), `file` (a local database) or `off`. |
|
| `SWW_LOOKUP_SOURCE` | `geojs` | Where each client's AS number and country come from: `geojs` (a web service), `file` (a local database) or `off`. |
|
||||||
| `SWW_LOOKUP_DB_PATH` | empty | The IPinfo Lite database file, in its `.mmdb` form, read while the source is `file`. |
|
| `SWW_LOOKUP_DB_PATH` | empty | The IPinfo Lite database file, in its `.mmdb` form, read while the source is `file`. |
|
||||||
| `SWW_LOOKUP_TIMEOUT` | `800ms` | How long a request waits for its client's first GeoJS answer when a setting needs it, and how long a request to GeoJS may take. |
|
| `SWW_LOOKUP_TIMEOUT` | `800ms` | How long a request waits for its client's first GeoJS answer when a setting needs it, and how long a request to GeoJS may take. |
|
||||||
| `SWW_ADD_LOOKUP_HEADERS` | `false` | `true` passes the app the client's AS number and country in `X-Client-ASN` and `X-Client-Country`. |
|
| `SWW_ADD_LOOKUP_HEADERS` | `false` | `true` passes the app the client's AS number and country in `X-Client-ASN` and `X-Client-Country`. |
|
||||||
| `SWW_EXCLUSIVELY_ALLOWED_COUNTRIES` | empty | When set, the only countries whose clients get through; a client the lookup cannot place is refused too. |
|
| `SWW_EXCLUSIVELY_ALLOWED_COUNTRIES` | empty | When set, the only countries whose clients get through; a client the lookup cannot place is refused too. |
|
||||||
| `SWW_TAG_LISTS` | empty | Address lists that each add a tag to their clients' requests, as `name=URL` pairs, such as `torexit=https://example.com/tor.txt`. |
|
| `SWW_TAG_LISTS` | empty | Address lists that each add a tag to their clients' requests, as `name=URL` pairs, such as `torexit=https://example.com/tor.txt`. |
|
||||||
| `SWW_TAG_DENY` | empty | Tags whose requests are refused, such as `torexit,country=CN`. |
|
| `SWW_TAG_DENY` | empty | Tags whose requests are refused, such as `torexit,country=CN`. |
|
||||||
| `SWW_TAG_LIMIT_PERCENT` | empty | Tags whose clients get a percentage, from 1 to 99, of every request and byte limit, such as `vpn:50,asn=14061:25`; the lowest applies. |
|
| `SWW_TAG_LIMIT_PERCENT` | empty | Tags whose clients get a percentage, from 1 to 99, of every request and byte limit, such as `vpn:50,asn=14061:25`; the lowest applies. |
|
||||||
| `SWW_ROUTEWATCH_URL` | unset | The URL of a routewatch instance, which gives each client's `asn=` and `prefix=` tags. Unset, nothing asks routewatch. |
|
| `SWW_ROUTEWATCH_URL` | unset | The URL of a routewatch instance, which gives each client's `asn=` and `prefix=` tags. Unset, nothing asks routewatch. |
|
||||||
| `SWW_ASN_BYTES_PERCENT` | empty | A percentage of the byte limits alone for the AS numbers listed, in place of their `asn=` tag's percentage. |
|
| `SWW_ASN_BYTES_PERCENT` | empty | A percentage of the byte limits alone for the AS numbers listed, in place of their `asn=` tag's percentage. |
|
||||||
| `SWW_COUNTRY_BYTES_PERCENT` | empty | A percentage of the byte limits alone for the countries listed, in place of their `country=` tag's percentage. |
|
| `SWW_COUNTRY_BYTES_PERCENT` | empty | A percentage of the byte limits alone for the countries listed, in place of their `country=` tag's percentage. |
|
||||||
| `SWW_UNKNOWN_LIMIT_PERCENT` | `100` | The percentage of every limit a client without a country gets. |
|
| `SWW_UNKNOWN_LIMIT_PERCENT` | `100` | The percentage of every limit a client without a country gets. |
|
||||||
| `SWW_ASN_LIMIT_PERCENT_URL` | unset | The URL of a text file of `AS<number>:<percent>` lines, fetched like a blocklist; each line counts as an `asn=` tag in `SWW_TAG_LIMIT_PERCENT` (the lowest wins). |
|
| `SWW_ASN_LIMIT_PERCENT_URL` | unset | The URL of a text file of `AS<number>:<percent>` lines, fetched like a blocklist; each line counts as an `asn=` tag in `SWW_TAG_LIMIT_PERCENT` (the lowest wins). |
|
||||||
| `SWW_RULES_DIR` | `/etc/sww/rules.d` | The directory of the rule files, read at start and again when a file there changes. |
|
| `SWW_RULES_DIR` | `/etc/sww/rules.d` | The directory of the rule files, read at start and again when a file there changes. |
|
||||||
| `SWW_RULES_ENABLED` | `true` | `false` reads no rule file. |
|
| `SWW_RULES_ENABLED` | `true` | `false` reads no rule file. |
|
||||||
| `SWW_TRAP_PATHS` | empty | Paths only scanners ask for, such as `/wp-login.php,/xmlrpc.php`; a request for one bans the client. |
|
| `SWW_TRAP_PATHS` | empty | Paths only scanners ask for, such as `/wp-login.php,/xmlrpc.php`; a request for one bans the client. |
|
||||||
| `SWW_WAF_MODE` | `block` | What the Core Rule Set does with a match: `block` refuses it with `403`, `detect` only logs and alerts it, `off` runs no rule. |
|
| `SWW_WAF_MODE` | `block` | What the Core Rule Set does with a match: `block` refuses it with `403`, `detect` only logs and alerts it, `off` runs no rule. |
|
||||||
| `SWW_WAF_PARANOIA_LEVEL` | `1` | The Core Rule Set's paranoia level, from 1 to 4; each level up finds more attacks and takes more ordinary requests for attacks. |
|
| `SWW_WAF_PARANOIA_LEVEL` | `1` | The Core Rule Set's paranoia level, from 1 to 4; each level up finds more attacks and takes more ordinary requests for attacks. |
|
||||||
| `SWW_WAF_ANOMALY_THRESHOLD` | `5` | The Core Rule Set score at which a request is a match, a whole number or `off`; one critical rule scores 5. |
|
| `SWW_WAF_ANOMALY_THRESHOLD` | `5` | The Core Rule Set score at which a request is a match, a whole number or `off`; one critical rule scores 5. |
|
||||||
| `SWW_WAF_DISABLED_RULES` | `920340,920420,920440,920640,930130,930140` | Core Rule Set rule ids switched off; a list you give replaces the default, so repeat these six to keep them off. |
|
| `SWW_WAF_DISABLED_RULES` | `920340,920420,920440,920640,930130,930140` | Core Rule Set rule ids switched off; a list you give replaces the default, so repeat these six to keep them off. |
|
||||||
| `SWW_WAF_EXEMPT_PATHS` | empty | Path prefixes the Core Rule Set does not inspect. |
|
| `SWW_WAF_EXEMPT_PATHS` | empty | Path prefixes the Core Rule Set does not inspect. |
|
||||||
| `SWW_WAF_BODY_LIMIT` | `off` | How much of a request body the Core Rule Set reads, a size up to `64K`; `off` reads none. |
|
| `SWW_WAF_BODY_LIMIT` | `off` | How much of a request body the Core Rule Set reads, a size up to `64K`; `off` reads none. |
|
||||||
| `SWW_CORE_RULE_SET_EXCLUSIONS_FILE` | unset | A file of Core Rule Set exclusions, as Coraza directives, that switch rules off for some fields or paths only. |
|
| `SWW_CORE_RULE_SET_EXCLUSIONS_FILE` | unset | A file of Core Rule Set exclusions, as Coraza directives, that switch rules off for some fields or paths only. |
|
||||||
| `SWW_BLOCKLIST_URLS` | empty | Blocklists to fetch, text files of addresses and netblocks one to a line, such as `https://www.spamhaus.org/drop/drop.txt`. |
|
| `SWW_BLOCKLIST_URLS` | empty | Blocklists to fetch, text files of addresses and netblocks one to a line, such as `https://www.spamhaus.org/drop/drop.txt`. |
|
||||||
| `SWW_BLOCKLIST_REFRESH` | `24h` | How long after a list was last tried it is fetched again, `1h` or more. |
|
| `SWW_BLOCKLIST_REFRESH` | `24h` | How long after a list was last tried it is fetched again, `1h` or more. |
|
||||||
| `SWW_BLOCKLIST_ACTION` | `deny` | What a client on a blocklist gets: `deny`, `limit:<percent>` of every limit, or `log`. |
|
| `SWW_BLOCKLIST_ACTION` | `deny` | What a client on a blocklist gets: `deny`, `limit:<percent>` of every limit, or `log`. |
|
||||||
| `SWW_DNSBL_ZONES` | empty | DNS blocklists asked about each new client in the background, such as `dnsbl.dronebl.org`. |
|
| `SWW_DNSBL_ZONES` | empty | DNS blocklists asked about each new client in the background, such as `dnsbl.dronebl.org`. |
|
||||||
| `SWW_DNSBL_RESOLVER` | unset | The resolver the zones are asked through, an IP address with an optional port; unset, the host's resolver is used. |
|
| `SWW_DNSBL_RESOLVER` | unset | The resolver the zones are asked through, an IP address with an optional port; unset, the host's resolver is used. |
|
||||||
| `SWW_ABUSEIPDB_KEY` | unset | The key of your AbuseIPDB account; set, a client that has committed an offence is checked in the background. |
|
| `SWW_ABUSEIPDB_KEY` | unset | The key of your AbuseIPDB account; set, a client that has committed an offence is checked in the background. |
|
||||||
| `SWW_ABUSEIPDB_MIN_SCORE` | `75` | The least AbuseIPDB abuse confidence score, from 0 to 100, that is a hit. |
|
| `SWW_ABUSEIPDB_MIN_SCORE` | `75` | The least AbuseIPDB abuse confidence score, from 0 to 100, that is a hit. |
|
||||||
| `SWW_ABUSEIPDB_DAILY_BUDGET` | `900` | The most AbuseIPDB checks made in a day. |
|
| `SWW_ABUSEIPDB_DAILY_BUDGET` | `900` | The most AbuseIPDB checks made in a day. |
|
||||||
| `SWW_CROWDSEC_LAPI_URL` | unset | The local API of a CrowdSec engine you run, such as `http://172.17.0.1:8080`; its decision list is fetched every minute, and a listed client is banned. |
|
| `SWW_CROWDSEC_LAPI_URL` | unset | The local API of a CrowdSec engine you run, such as `http://172.17.0.1:8080`; its decision list is fetched every minute, and a listed client is banned. |
|
||||||
| `SWW_CROWDSEC_LAPI_KEY` | unset | The key the engine gave for `smallwebwaf`, as `cscli bouncers add smallwebwaf` prints it; set with the URL, never alone. |
|
| `SWW_CROWDSEC_LAPI_KEY` | unset | The key the engine gave for `smallwebwaf`, as `cscli bouncers add smallwebwaf` prints it; set with the URL, never alone. |
|
||||||
| `SWW_REPUTATION_ACTION` | `limit:25` | What a client listed by a DNS blocklist, or scored a hit by AbuseIPDB, gets: `deny`, `limit:<percent>` or `log`. |
|
| `SWW_REPUTATION_ACTION` | `limit:25` | What a client listed by a DNS blocklist, or scored a hit by AbuseIPDB, gets: `deny`, `limit:<percent>` or `log`. |
|
||||||
| `SWW_REPUTATION_CACHE_TTL` | `24h` | How long a DNS blocklist verdict or an AbuseIPDB score is used. |
|
| `SWW_REPUTATION_CACHE_TTL` | `24h` | How long a DNS blocklist verdict or an AbuseIPDB score is used. |
|
||||||
| `SWW_REPUTATION_TIMEOUT` | `2s` | How long a DNS blocklist query or an AbuseIPDB check may take. |
|
| `SWW_REPUTATION_TIMEOUT` | `2s` | How long a DNS blocklist query or an AbuseIPDB check may take. |
|
||||||
| `SWW_STATE_DIR` | `/var/lib/sww` | The directory of the state files, an absolute path. |
|
| `SWW_STATE_DIR` | `/var/lib/sww` | The directory of the state files, an absolute path. |
|
||||||
| `SWW_STATE_WRITE_DELAY` | `10s` | How long `bans.json` waits to be written after a ban is made, lifted or made permanent. |
|
| `SWW_STATE_WRITE_DELAY` | `10s` | How long `bans.json` waits to be written after a ban is made, lifted or made permanent. |
|
||||||
| `SWW_STATE_COUNTER_INTERVAL` | `15m` | How often every state file is written. |
|
| `SWW_STATE_COUNTER_INTERVAL` | `15m` | How often every state file is written. |
|
||||||
| `SWW_LOG_LEVEL` | `info` | The least severe of `discriminator`'s own messages that are written: `debug`, `info`, `warn` or `error`; request lines are always written. |
|
| `SWW_LOG_LEVEL` | `info` | The least severe of `discriminator`'s own messages that are written: `debug`, `info`, `warn` or `error`; request lines are always written. |
|
||||||
| `SWW_LOG_REQUEST_HEADERS` | `accept,accept-language,accept-encoding,content-type,origin,range` | The request headers whose values the request log records; `Authorization` and `Cookie` are never recorded. |
|
| `SWW_LOG_REQUEST_HEADERS` | `accept,accept-language,accept-encoding,content-type,origin,range` | The request headers whose values the request log records; `Authorization` and `Cookie` are never recorded. |
|
||||||
| `SWW_LOG_REMOTE_URL` | unset | A syslog server that also gets every line `discriminator` writes: `syslog+udp://`, `syslog+tcp://` or `syslog+tls://` with a host and a port. |
|
| `SWW_LOG_REMOTE_URL` | unset | A syslog server that also gets every line `discriminator` writes: `syslog+udp://`, `syslog+tcp://` or `syslog+tls://` with a host and a port. |
|
||||||
| `SWW_LOG_REMOTE_TLS_CA_FILE` | unset | A file of PEM certificates a `syslog+tls` server's certificate must chain to, instead of the host's own. |
|
| `SWW_LOG_REMOTE_TLS_CA_FILE` | unset | A file of PEM certificates a `syslog+tls` server's certificate must chain to, instead of the host's own. |
|
||||||
| `SWW_LOG_REMOTE_BUFFER` | `10000` | The most lines held while they wait to be sent; past it, the oldest is dropped. |
|
| `SWW_LOG_REMOTE_BUFFER` | `10000` | The most lines held while they wait to be sent; past it, the oldest is dropped. |
|
||||||
| `SWW_LOG_REMOTE_FACILITY` | `local0` | The syslog facility of each record sent. |
|
| `SWW_LOG_REMOTE_FACILITY` | `local0` | The syslog facility of each record sent. |
|
||||||
| `SWW_LOG_REMOTE_APP_NAME` | `SWW_INSTANCE_NAME` | The app name in each syslog record, 1 to 48 printable ASCII characters without a space. |
|
| `SWW_LOG_REMOTE_APP_NAME` | `SWW_INSTANCE_NAME` | The app name in each syslog record, 1 to 48 printable ASCII characters without a space. |
|
||||||
| `SWW_ADMIN_TOKEN` | unset | The bearer token for the ban and client endpoints, at least 32 characters; unset, they answer `404`. |
|
| `SWW_ADMIN_TOKEN` | unset | The bearer token for the ban and client endpoints, at least 32 characters; unset, they answer `404`. |
|
||||||
| `SWW_METRICS_TOKEN` | unset | The bearer token for `/_sww/metrics`, at least 32 characters; unset, the metrics are off. |
|
| `SWW_METRICS_TOKEN` | unset | The bearer token for `/_sww/metrics`, at least 32 characters; unset, the metrics are off. |
|
||||||
| `SWW_METRICS_TOP_N` | `50` | How many AS numbers and how many countries get metric series of their own; the rest are summed as `other`. |
|
| `SWW_METRICS_TOP_N` | `50` | How many AS numbers and how many countries get metric series of their own; the rest are summed as `other`. |
|
||||||
| `SWW_ALERT_WEBHOOK_URL` | unset | A webhook each alert is posted to as a JSON object. |
|
| `SWW_ALERT_WEBHOOK_URL` | unset | A webhook each alert is posted to as a JSON object. |
|
||||||
| `SWW_ALERT_WEBHOOK_HEADERS` | empty | Headers sent with each post, a list of `Name:value`, such as `Authorization:Bearer <token>`. |
|
| `SWW_ALERT_WEBHOOK_HEADERS` | empty | Headers sent with each post, a list of `Name:value`, such as `Authorization:Bearer <token>`. |
|
||||||
| `SWW_ALERT_SLACK_WEBHOOK_URL` | unset | A Slack incoming webhook each alert is posted to as a message. |
|
| `SWW_ALERT_SLACK_WEBHOOK_URL` | unset | A Slack incoming webhook each alert is posted to as a message. |
|
||||||
| `SWW_ALERT_NTFY_URL` | unset | An ntfy topic each alert is published to, as its full URL, such as `https://ntfy.sh/my-alerts`. |
|
| `SWW_ALERT_NTFY_URL` | unset | An ntfy topic each alert is published to, as its full URL, such as `https://ntfy.sh/my-alerts`. |
|
||||||
| `SWW_ALERT_NTFY_TOKEN` | unset | An ntfy access token sent with each alert. |
|
| `SWW_ALERT_NTFY_TOKEN` | unset | An ntfy access token sent with each alert. |
|
||||||
| `SWW_ALERT_EVENTS` | `ban,permanent_ban,core_rule_set_match,anomaly,reputation_hit,source_failure,file_error` | The events alerts are sent for; the hourly `summary` is sent whatever it says. |
|
| `SWW_ALERT_EVENTS` | `ban,permanent_ban,waf_block,anomaly,reputation_hit,source_failure,file_error` | The events alerts are sent for; the hourly `summary` is sent whatever it says. |
|
||||||
| `SWW_ALERT_COOLDOWN` | `15m` | How long after an alert its repeats are held back and counted, a duration or `off`. |
|
| `SWW_ALERT_COOLDOWN` | `15m` | How long after an alert its repeats are held back and counted, a duration or `off`. |
|
||||||
| `SWW_ALERT_MAX_PER_HOUR` | `60` | The most alerts sent in an hour, a number or `off`; the rest are counted in the hour's `summary`. |
|
| `SWW_ALERT_MAX_PER_HOUR` | `60` | The most alerts sent in an hour, a number or `off`; the rest are counted in the hour's `summary`. |
|
||||||
| `SWW_ANOMALY_CLIENT_REQUESTS_PER_MINUTE` | `off` | Alert when one client makes more requests than this in a minute, a count. |
|
| `SWW_ANOMALY_CLIENT_REQUESTS_PER_MINUTE` | `off` | Alert when one client makes more requests than this in a minute, a count. |
|
||||||
| `SWW_ANOMALY_CLIENT_REQUESTS_PER_HOUR` | `off` | Alert when one client makes more requests than this in an hour, a count. |
|
| `SWW_ANOMALY_CLIENT_REQUESTS_PER_HOUR` | `off` | Alert when one client makes more requests than this in an hour, a count. |
|
||||||
| `SWW_ANOMALY_CLIENT_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one client in a minute, a size. |
|
| `SWW_ANOMALY_CLIENT_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one client in a minute, a size. |
|
||||||
| `SWW_ANOMALY_CLIENT_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one client in an hour, a size. |
|
| `SWW_ANOMALY_CLIENT_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one client in an hour, a size. |
|
||||||
| `SWW_ANOMALY_NET_REQUESTS_PER_MINUTE` | `off` | Alert when the netblock around a client makes more requests than this in a minute, a count. |
|
| `SWW_ANOMALY_NET_REQUESTS_PER_MINUTE` | `off` | Alert when the netblock around a client makes more requests than this in a minute, a count. |
|
||||||
| `SWW_ANOMALY_NET_REQUESTS_PER_HOUR` | `off` | Alert when the netblock around a client makes more requests than this in an hour, a count. |
|
| `SWW_ANOMALY_NET_REQUESTS_PER_HOUR` | `off` | Alert when the netblock around a client makes more requests than this in an hour, a count. |
|
||||||
| `SWW_ANOMALY_NET_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the netblock around a client in a minute, a size. |
|
| `SWW_ANOMALY_NET_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the netblock around a client in a minute, a size. |
|
||||||
| `SWW_ANOMALY_NET_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the netblock around a client in an hour, a size. |
|
| `SWW_ANOMALY_NET_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the netblock around a client in an hour, a size. |
|
||||||
| `SWW_ANOMALY_NET_V4_PREFIX` | `24` | The prefix length of the netblock around an IPv4 client that the `SWW_ANOMALY_NET_` thresholds count, from 0 to 32. |
|
| `SWW_ANOMALY_NET_V4_PREFIX` | `24` | The prefix length of the netblock around an IPv4 client that the `SWW_ANOMALY_NET_` thresholds count, from 0 to 32. |
|
||||||
| `SWW_ANOMALY_NET_V6_PREFIX` | `48` | The prefix length of the netblock around an IPv6 client that the `SWW_ANOMALY_NET_` thresholds count, from 0 to 128. |
|
| `SWW_ANOMALY_NET_V6_PREFIX` | `48` | The prefix length of the netblock around an IPv6 client that the `SWW_ANOMALY_NET_` thresholds count, from 0 to 128. |
|
||||||
| `SWW_ANOMALY_ASN_REQUESTS_PER_MINUTE` | `off` | Alert when one AS number makes more requests than this in a minute, a count. |
|
| `SWW_ANOMALY_ASN_REQUESTS_PER_MINUTE` | `off` | Alert when one AS number makes more requests than this in a minute, a count. |
|
||||||
| `SWW_ANOMALY_ASN_REQUESTS_PER_HOUR` | `off` | Alert when one AS number makes more requests than this in an hour, a count. |
|
| `SWW_ANOMALY_ASN_REQUESTS_PER_HOUR` | `off` | Alert when one AS number makes more requests than this in an hour, a count. |
|
||||||
| `SWW_ANOMALY_ASN_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one AS number in a minute, a size. |
|
| `SWW_ANOMALY_ASN_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one AS number in a minute, a size. |
|
||||||
| `SWW_ANOMALY_ASN_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one AS number in an hour, a size. |
|
| `SWW_ANOMALY_ASN_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for one AS number in an hour, a size. |
|
||||||
| `SWW_ANOMALY_TOTAL_REQUESTS_PER_MINUTE` | `off` | Alert when the whole service gets more requests than this in a minute, a count. |
|
| `SWW_ANOMALY_TOTAL_REQUESTS_PER_MINUTE` | `off` | Alert when the whole service gets more requests than this in a minute, a count. |
|
||||||
| `SWW_ANOMALY_TOTAL_REQUESTS_PER_HOUR` | `off` | Alert when the whole service gets more requests than this in an hour, a count. |
|
| `SWW_ANOMALY_TOTAL_REQUESTS_PER_HOUR` | `off` | Alert when the whole service gets more requests than this in an hour, a count. |
|
||||||
| `SWW_ANOMALY_TOTAL_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the whole service in a minute, a size. |
|
| `SWW_ANOMALY_TOTAL_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the whole service in a minute, a size. |
|
||||||
| `SWW_ANOMALY_TOTAL_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the whole service in an hour, a size. |
|
| `SWW_ANOMALY_TOTAL_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for the whole service in an hour, a size. |
|
||||||
| `SWW_WATCH_NETS` | empty | Named netblocks the `SWW_WATCH_` thresholds count each as a whole, such as `office=203.0.113.0/24,scraper-x=198.51.100.0/22`. |
|
| `SWW_WATCH_NETS` | empty | Named netblocks the `SWW_WATCH_` thresholds count each as a whole, such as `office=203.0.113.0/24,scraper-x=198.51.100.0/22`. |
|
||||||
| `SWW_WATCH_REQUESTS_PER_MINUTE` | `off` | Alert when a watched netblock makes more requests than this in a minute, a count. |
|
| `SWW_WATCH_REQUESTS_PER_MINUTE` | `off` | Alert when a watched netblock makes more requests than this in a minute, a count. |
|
||||||
| `SWW_WATCH_REQUESTS_PER_HOUR` | `off` | Alert when a watched netblock makes more requests than this in an hour, a count. |
|
| `SWW_WATCH_REQUESTS_PER_HOUR` | `off` | Alert when a watched netblock makes more requests than this in an hour, a count. |
|
||||||
| `SWW_WATCH_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for a watched netblock in a minute, a size. |
|
| `SWW_WATCH_BYTES_PER_MINUTE` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for a watched netblock in a minute, a size. |
|
||||||
| `SWW_WATCH_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for a watched netblock in an hour, a size. |
|
| `SWW_WATCH_BYTES_PER_HOUR` | `off` | Alert when more than this many bytes, as `SWW_BYTES_COUNT` counts them, are counted for a watched netblock in an hour, a size. |
|
||||||
|
|
||||||
[`docs/settings.md`](docs/settings.md) gives the values each setting takes in
|
[`docs/settings.md`](docs/settings.md) gives the values each setting takes in
|
||||||
full, and the limits that are fixed rather than settings.
|
full, and the limits that are fixed rather than settings.
|
||||||
@@ -469,7 +469,7 @@ services:
|
|||||||
# Alerts to an ntfy topic, with its token read from a file.
|
# Alerts to an ntfy topic, with its token read from a file.
|
||||||
SWW_ALERT_NTFY_URL: https://ntfy.example/smallwebwaf
|
SWW_ALERT_NTFY_URL: https://ntfy.example/smallwebwaf
|
||||||
SWW_ALERT_NTFY_TOKEN_FILE: /etc/sww/tokens/ntfy
|
SWW_ALERT_NTFY_TOKEN_FILE: /etc/sww/tokens/ntfy
|
||||||
SWW_ALERT_EVENTS: ban,permanent_ban,core_rule_set_match,source_failure,file_error
|
SWW_ALERT_EVENTS: ban,permanent_ban,waf_block,source_failure,file_error
|
||||||
volumes:
|
volumes:
|
||||||
- discriminator-state:/var/lib/sww
|
- discriminator-state:/var/lib/sww
|
||||||
- /srv/ipinfo:/var/lib/ipinfo:ro
|
- /srv/ipinfo:/var/lib/ipinfo:ro
|
||||||
@@ -581,11 +581,16 @@ client's limits by tag. See "Request tags" in [`SPEC.md`](SPEC.md).
|
|||||||
headers of every request, and no body unless `SWW_WAF_BODY_LIMIT` is set. In
|
headers of every request, and no body unless `SWW_WAF_BODY_LIMIT` is set. In
|
||||||
front of a code forge, bodies carry what people write and publish, which the
|
front of a code forge, bodies carry what people write and publish, which the
|
||||||
rules take for attacks.
|
rules take for attacks.
|
||||||
- `smallwebwaf` changes the Core Rule Set in eight ways so that it lets ordinary
|
- `smallwebwaf` changes the Core Rule Set in nine ways so that it lets ordinary
|
||||||
requests to a code forge through, such as git over HTTP and sign-in through
|
requests to a code forge or to WordPress through, such as git over HTTP and
|
||||||
Git Credential Manager. On gitea's own paths, its searches, file names and
|
sign-in through Git Credential Manager. On gitea's own paths, its searches,
|
||||||
branch names get through too. No setting undoes the changes; "Attack
|
file names and branch names get through too. On WordPress's own paths, its
|
||||||
detection" in [`SPEC.md`](SPEC.md) lists them.
|
searches and file names do. No setting undoes the changes; "Attack detection"
|
||||||
|
in [`SPEC.md`](SPEC.md) lists them.
|
||||||
|
- These apps work out of the box at the default settings, and the Core Rule Set
|
||||||
|
refuses none of their ordinary requests:
|
||||||
|
- gitea;
|
||||||
|
- WordPress.
|
||||||
- `SWW_CORE_RULE_SET_EXCLUSIONS_FILE` switches single rules off for an app's own
|
- `SWW_CORE_RULE_SET_EXCLUSIONS_FILE` switches single rules off for an app's own
|
||||||
fields or paths.
|
fields or paths.
|
||||||
- Rule files are plain text, one rule to a line, edited by hand and read again
|
- Rule files are plain text, one rule to a line, edited by hand and read again
|
||||||
@@ -632,10 +637,9 @@ is set aside as `<name>.bad`, and never stops the running process (see
|
|||||||
- `internal/rproxy`: the reverse proxy in front of one app.
|
- `internal/rproxy`: the reverse proxy in front of one app.
|
||||||
- `internal/discriminator`: `discriminator`'s server, which runs the checks and
|
- `internal/discriminator`: `discriminator`'s server, which runs the checks and
|
||||||
answers its own endpoints.
|
answers its own endpoints.
|
||||||
- `internal/ratelimit`, `internal/bans`, `internal/rules`,
|
- `internal/ratelimit`, `internal/bans`, `internal/rules`, `internal/waf`,
|
||||||
`internal/coreruleset`, `internal/lookup`, `internal/reputation`,
|
`internal/lookup`, `internal/reputation`, `internal/routewatch`,
|
||||||
`internal/routewatch`, `internal/anomaly` and `internal/alerts`: one check or
|
`internal/anomaly` and `internal/alerts`: one check or source each.
|
||||||
source each.
|
|
||||||
- `internal/state`, `internal/requestlog`, `internal/remotelog` and
|
- `internal/state`, `internal/requestlog`, `internal/remotelog` and
|
||||||
`internal/metrics`: the state files, the log lines, the syslog sender and the
|
`internal/metrics`: the state files, the log lines, the syslog sender and the
|
||||||
metrics.
|
metrics.
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ to them.
|
|||||||
of bans is full.
|
of bans is full.
|
||||||
- `internal/rules`: reads the rule files at start and again when they
|
- `internal/rules`: reads the rule files at start and again when they
|
||||||
change, and tells which rules a request matches.
|
change, and tells which rules a request matches.
|
||||||
- `internal/coreruleset`: the Core Rule Set, with the eight changes listed
|
- `internal/waf`: the Core Rule Set, with the nine changes listed under
|
||||||
under "Attack detection", as Coraza directives.
|
"Attack detection", as Coraza directives.
|
||||||
- `internal/lookup`: looks clients up through GeoJS or in the lookup
|
- `internal/lookup`: looks clients up through GeoJS or in the lookup
|
||||||
database.
|
database.
|
||||||
- `internal/reputation`: fetches the lists, asks the DNS blocklists and
|
- `internal/reputation`: fetches the lists, asks the DNS blocklists and
|
||||||
@@ -655,7 +655,7 @@ files, the limits and the bans still apply to the client that sends it.
|
|||||||
match, and scores are still logged. A request with more than 1000 query
|
match, and scores are still logged. A request with more than 1000 query
|
||||||
parameters or body fields adds 5 to its score, since Coraza reads only the
|
parameters or body fields adds 5 to its score, since Coraza reads only the
|
||||||
first 1000. For a match, in `block` and `detect` mode alike, the log line
|
first 1000. For a match, in `block` and `detect` mode alike, the log line
|
||||||
gives the rule ids and the score, and a `core_rule_set_match` alert is sent.
|
gives the rule ids and the score, and a `waf_block` alert is sent.
|
||||||
- `SWW_WAF_DISABLED_RULES` switches off rule ids when an app trips a false
|
- `SWW_WAF_DISABLED_RULES` switches off rule ids when an app trips a false
|
||||||
positive. The default switches off six rules:
|
positive. The default switches off six rules:
|
||||||
- 920340, 920420 and 920640 refuse a request for the type of its body, when
|
- 920340, 920420 and 920640 refuse a request for the type of its body, when
|
||||||
@@ -674,7 +674,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
|
- `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
|
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
|
only, where `SWW_WAF_DISABLED_RULES` switches it off everywhere. The file
|
||||||
holds an app's own exclusions; the eighth change below holds gitea's.
|
holds an app's own exclusions; the eighth and ninth changes below hold gitea's
|
||||||
|
and WordPress's.
|
||||||
- `discriminator` loads the file after `smallwebwaf`'s own setup rules and
|
- `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
|
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.
|
`REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf` at the same point.
|
||||||
@@ -720,9 +721,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
|
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.
|
clients get `404` and `401` by design, hundreds of times a minute.
|
||||||
|
|
||||||
`smallwebwaf` changes the Core Rule Set 4.25.0 in eight ways, since in front of
|
`smallwebwaf` changes the Core Rule Set 4.25.0 in nine ways, since in front of
|
||||||
gitea it would otherwise refuse ordinary requests. The changes hold in front of
|
gitea and WordPress it would otherwise refuse ordinary requests. The changes
|
||||||
every app, and no setting undoes them:
|
hold in front of every app, and no setting undoes them:
|
||||||
|
|
||||||
1. `PUT`, `PATCH` and `DELETE` are allowed methods besides `GET`, `HEAD`, `POST`
|
1. `PUT`, `PATCH` and `DELETE` are allowed methods besides `GET`, `HEAD`, `POST`
|
||||||
and `OPTIONS`. APIs, container image pushes and package uploads use them.
|
and `OPTIONS`. APIs, container image pushes and package uploads use them.
|
||||||
@@ -789,8 +790,8 @@ every app, and no setting undoes them:
|
|||||||
such as `owner/python3-app` would have that push refused.
|
such as `owner/python3-app` would have that push refused.
|
||||||
8. On gitea's paths, some fields skip the rules that refused ordinary gitea
|
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
|
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
|
or a branch name. `internal/waf/gitea.conf` lists each rule and the request
|
||||||
request it refused. The fields are:
|
it refused. The fields are:
|
||||||
- `q` on gitea's searches of code, of issues and pull requests, and of
|
- `q` on gitea's searches of code, of issues and pull requests, and of
|
||||||
commits. A code search holds code, such as `<script>`,
|
commits. A code search holds code, such as `<script>`,
|
||||||
`SELECT * FROM users WHERE` or `../`.
|
`SELECT * FROM users WHERE` or `../`.
|
||||||
@@ -847,6 +848,41 @@ every app, and no setting undoes them:
|
|||||||
site root. An app other than gitea that serves one of them must check these
|
site root. An app other than gitea that serves one of them must check these
|
||||||
fields itself.
|
fields itself.
|
||||||
|
|
||||||
|
9. On WordPress's paths, some fields skip the rules that refused ordinary
|
||||||
|
WordPress requests there. `internal/waf/wordpress.conf` lists each rule and
|
||||||
|
the request it refused. The REST API has three addresses, by the permalink
|
||||||
|
setting:
|
||||||
|
- `/wp-json/...`
|
||||||
|
- `/index.php/wp-json/...`
|
||||||
|
- `/index.php?rest_route=/...`
|
||||||
|
|
||||||
|
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.
|
||||||
|
- `s` in WordPress's searches, for the lists of command names (932120,
|
||||||
|
932250, 932260). The pages are:
|
||||||
|
- `/` and `/index.php`;
|
||||||
|
- `/wp-admin/edit.php`;
|
||||||
|
- `/wp-admin/upload.php`;
|
||||||
|
- `/wp-admin/plugin-install.php`.
|
||||||
|
- `search` on the REST API's routes `/wp/v2/search` and `/wp/v2/posts`, for
|
||||||
|
the same rules.
|
||||||
|
- `file` on `/wp-admin/plugin-editor.php` and `/wp-admin/theme-editor.php`,
|
||||||
|
for the lists of system files, shell paths and command names (930120,
|
||||||
|
932160, 932260).
|
||||||
|
- 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).
|
||||||
|
|
||||||
|
Elsewhere these fields keep every rule. The paths are those of WordPress at
|
||||||
|
the site root.
|
||||||
|
|
||||||
The parameter and cookie names in these changes are matched without regard to
|
The parameter and cookie names in these changes are matched without regard to
|
||||||
case, as Coraza matches them.
|
case, as Coraza matches them.
|
||||||
|
|
||||||
@@ -1378,11 +1414,11 @@ these fields, named as the request log's fields of the same meaning:
|
|||||||
- `request_bytes` and `response_bytes`: the body bytes each way, with what a
|
- `request_bytes` and `response_bytes`: the body bytes each way, with what a
|
||||||
WebSocket carried each way, each a whole number from `0` to `1125899906842624`
|
WebSocket carried each way, each a whole number from `0` to `1125899906842624`
|
||||||
(1 PiB);
|
(1 PiB);
|
||||||
- `duration_total_ms`: milliseconds from the request's headers being read to the
|
- `duration_total`: milliseconds from the request's headers being read to the
|
||||||
end of the answer, from `0` to `1000000000000` (about 31 years);
|
end of the answer, from `0` to `1000000000000` (about 31 years);
|
||||||
- `duration_upstream_total_ms`: milliseconds from the hand-over to the app to
|
- `duration_upstream_total`: milliseconds from the hand-over to the app to the
|
||||||
the end of the answer, in the same range, and `0` for a request not passed to
|
end of the answer, in the same range, and `0` for a request not passed to the
|
||||||
the app.
|
app.
|
||||||
|
|
||||||
`discriminator` answers `400` and writes a process warning when the body:
|
`discriminator` answers `400` and writes a process warning when the body:
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -9,9 +9,9 @@ back or dropped.
|
|||||||
- `ban`: a ban `discriminator` made.
|
- `ban`: a ban `discriminator` made.
|
||||||
- `permanent_ban`: a permanent ban it made, or an existing ban made permanent by
|
- `permanent_ban`: a permanent ban it made, or an existing ban made permanent by
|
||||||
a request.
|
a request.
|
||||||
- `core_rule_set_match`: the Core Rule Set scored a request at or over the
|
- `waf_block`: the Core Rule Set scored a request at or over the threshold. The
|
||||||
threshold. The request was refused unless the alert's `detail` gives `mode`:
|
request was refused unless the alert's `detail` gives `mode`: `detect` or
|
||||||
`detect` or `observe`.
|
`observe`.
|
||||||
- `anomaly`: a count over an anomaly threshold.
|
- `anomaly`: a count over an anomaly threshold.
|
||||||
- `reputation_hit`: a request from a client on a blocklist, the CrowdSec
|
- `reputation_hit`: a request from a client on a blocklist, the CrowdSec
|
||||||
decision list or a DNS blocklist, or with an AbuseIPDB score that is a hit.
|
decision list or a DNS blocklist, or with an AbuseIPDB score that is a hit.
|
||||||
@@ -130,7 +130,7 @@ The priority and tag by event:
|
|||||||
|
|
||||||
- `ban`: priority `default`, tag `no_entry`.
|
- `ban`: priority `default`, tag `no_entry`.
|
||||||
- `permanent_ban`: priority `high`, tag `no_entry`.
|
- `permanent_ban`: priority `high`, tag `no_entry`.
|
||||||
- `core_rule_set_match`: priority `default`, tag `shield`.
|
- `waf_block`: priority `default`, tag `shield`.
|
||||||
- `anomaly`: priority `high`, tag `chart_with_upwards_trend`.
|
- `anomaly`: priority `high`, tag `chart_with_upwards_trend`.
|
||||||
- `reputation_hit`: priority `low`, tag `label`.
|
- `reputation_hit`: priority `low`, tag `label`.
|
||||||
- `source_failure` and `file_error`: priority `high`, tag `warning`.
|
- `source_failure` and `file_error`: priority `high`, tag `warning`.
|
||||||
|
|||||||
+5
-6
@@ -28,8 +28,7 @@ body bytes, never headers, whatever `SWW_BYTES_COUNT` says.
|
|||||||
## Attack detection
|
## Attack detection
|
||||||
|
|
||||||
- `sww_rule_matches_total`, by `rule_id` and `action`, and `sww_rules_loaded`;
|
- `sww_rule_matches_total`, by `rule_id` and `action`, and `sww_rules_loaded`;
|
||||||
- `sww_core_rule_set_matches_total`, by `mode` and `rule_id`, for the rules that
|
- `sww_waf_matches_total`, by `mode` and `rule_id`, for the rules that fired.
|
||||||
fired.
|
|
||||||
|
|
||||||
## Countries and AS numbers
|
## Countries and AS numbers
|
||||||
|
|
||||||
@@ -44,8 +43,8 @@ For the `SWW_METRICS_TOP_N` busiest of each, the rest as `other`:
|
|||||||
## Lookups
|
## Lookups
|
||||||
|
|
||||||
- `sww_geojs_requests_total` and `sww_geojs_failures_total`;
|
- `sww_geojs_requests_total` and `sww_geojs_failures_total`;
|
||||||
- `sww_requests_without_geojs_answer_total`: the requests that needed an answer
|
- `sww_geojs_unanswered_total`: the requests that needed an answer and went on
|
||||||
and went on without it;
|
without it;
|
||||||
- with the file source, `sww_lookup_database_last_read_timestamp_seconds` and
|
- with the file source, `sww_lookup_database_last_read_timestamp_seconds` and
|
||||||
`sww_lookup_database_read_failures_total`.
|
`sww_lookup_database_read_failures_total`.
|
||||||
|
|
||||||
@@ -71,8 +70,8 @@ By `file`:
|
|||||||
## Remote log, alerts and the process
|
## Remote log, alerts and the process
|
||||||
|
|
||||||
- while a syslog server is set, `sww_remote_log_lines_sent_total`,
|
- while a syslog server is set, `sww_remote_log_lines_sent_total`,
|
||||||
`sww_remote_log_lines_dropped_total` and `sww_remote_log_lines_waiting`;
|
`sww_remote_log_lines_dropped_total` and `sww_remote_log_buffer_depth`;
|
||||||
- by `destination`, `sww_alerts_sent_total`, `sww_alert_send_failures_total`,
|
- by `destination`, `sww_alerts_sent_total`, `sww_alerts_failed_total`,
|
||||||
`sww_alerts_suppressed_total` and `sww_alerts_dropped_total`;
|
`sww_alerts_suppressed_total` and `sww_alerts_dropped_total`;
|
||||||
- Go's own `go_` metrics and the process's `process_` metrics.
|
- Go's own `go_` metrics and the process's `process_` metrics.
|
||||||
|
|
||||||
|
|||||||
+22
-23
@@ -26,7 +26,7 @@ These questions write no line:
|
|||||||
A `report` line:
|
A `report` line:
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type":"request","discriminator_line":"report","time":"2026-10-03T12:00:00.123Z","instance":"fsn1/discriminator","client_ip":"203.0.113.9","method":"GET","scheme":"https","host":"app.example","path":"/","query":"","protocol":"HTTP/1.1","status":200,"request_bytes":0,"response_bytes":5120,"referer":"","user_agent":"curl/8.9.1","request_id":"7Q2NHZ4KJ3VXW5YB6R3MEFTD2A","peer_ip":"172.18.0.2","forwarded_for":"203.0.113.9","client_group":"203.0.113.9/32","asn":"AS64496","as_name":"Example Net","country":"DE","request_headers":{"accept":"*/*"},"action":"forward","counts":{"minute":1,"hour":12,"day":40,"minute_bytes":5120,"hour_bytes":61440,"day_bytes":204800},"core_rule_set_score":0,"duration_total_ms":3.217,"duration_checks_ms":0.041,"duration_core_rule_set_ms":0.029,"duration_upstream_total_ms":3.104}
|
{"type":"request","discriminator_line":"report","time":"2026-10-03T12:00:00.123Z","instance":"fsn1/discriminator","client_ip":"203.0.113.9","method":"GET","scheme":"https","host":"app.example","path":"/","query":"","protocol":"HTTP/1.1","status":200,"request_bytes":0,"response_bytes":5120,"referer":"","user_agent":"curl/8.9.1","request_id":"7Q2NHZ4KJ3VXW5YB6R3MEFTD2A","peer_ip":"172.18.0.2","forwarded_for":"203.0.113.9","client_group":"203.0.113.9/32","asn":"AS64496","as_name":"Example Net","country":"DE","request_headers":{"accept":"*/*"},"action":"forward","counts":{"minute":1,"hour":12,"day":40,"minute_bytes":5120,"hour_bytes":61440,"day_bytes":204800},"waf_score":0,"duration_total":3.217,"duration_checks":0.041,"duration_waf":0.029,"duration_upstream_total":3.104}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Every line
|
### Every line
|
||||||
@@ -37,7 +37,7 @@ Every one of these lines has:
|
|||||||
- the standard web log fields;
|
- the standard web log fields;
|
||||||
- `request_id`, `peer_ip` and `client_group`;
|
- `request_id`, `peer_ip` and `client_group`;
|
||||||
- `asn`, `as_name` and `country`;
|
- `asn`, `as_name` and `country`;
|
||||||
- `action` and `duration_total_ms`.
|
- `action` and `duration_total`.
|
||||||
|
|
||||||
### Standard web log fields
|
### Standard web log fields
|
||||||
|
|
||||||
@@ -103,10 +103,10 @@ Every one of these lines has:
|
|||||||
- `permanently_banned`: refused under a ban that never runs out, including a
|
- `permanently_banned`: refused under a ban that never runs out, including a
|
||||||
ban this request made or made permanent;
|
ban this request made or made permanent;
|
||||||
- `country_denied`, `client_is_rate_limited`, `blocked_by_block_rule` and
|
- `country_denied`, `client_is_rate_limited`, `blocked_by_block_rule` and
|
||||||
`blocked_by_core_rule_set`: refused by that check;
|
`waf_blocked`: refused by that check;
|
||||||
- `request_header_too_large`: over a header limit;
|
- `request_header_too_large`: over a header limit;
|
||||||
- `own_endpoint`: answered at one of `discriminator`'s own endpoints, or
|
- `admin`: answered at one of `discriminator`'s own endpoints, or `404` for
|
||||||
`404` for a path under `/_sww/`.
|
a path under `/_sww/`.
|
||||||
- `would_action`: in `observe` mode, what `enforce` mode would have done with a
|
- `would_action`: in `observe` mode, what `enforce` mode would have done with a
|
||||||
request it would have refused. `action` then names what was done, normally
|
request it would have refused. `action` then names what was done, normally
|
||||||
`forward`.
|
`forward`.
|
||||||
@@ -140,10 +140,9 @@ Every one of these lines has:
|
|||||||
`byte_limits` bans when the report comes, so only the `report` line names
|
`byte_limits` bans when the report comes, so only the `report` line names
|
||||||
it.
|
it.
|
||||||
|
|
||||||
- `rate_limit_percent` and `rate_limit_percent_setting`: the client's percentage
|
- `limit_percent` and `limit_percent_setting`: the client's percentage of the
|
||||||
of the rate limits and the setting that lowered it, when one did.
|
rate limits and the setting that lowered it, when one did. `bytes_percent` and
|
||||||
`bytes_limit_percent` and `bytes_limit_percent_setting` do the same for the
|
`bytes_percent_setting` do the same for the byte limits.
|
||||||
byte limits.
|
|
||||||
- `counts`: the client's totals as rate limiting counts them, this request
|
- `counts`: the client's totals as rate limiting counts them, this request
|
||||||
included. It is left out when rate limiting did not count the request. It
|
included. It is left out when rate limiting did not count the request. It
|
||||||
holds:
|
holds:
|
||||||
@@ -159,7 +158,7 @@ Every one of these lines has:
|
|||||||
- `limit_hit`: the limit broken:
|
- `limit_hit`: the limit broken:
|
||||||
- `minute`, `hour` or `day` for a rate limit;
|
- `minute`, `hour` or `day` for a rate limit;
|
||||||
- `minute_bytes`, `hour_bytes` or `day_bytes` for a byte limit;
|
- `minute_bytes`, `hour_bytes` or `day_bytes` for a byte limit;
|
||||||
- `minute_refusals` for the error burst (`SWW_ERROR_BURST_THRESHOLD`).
|
- `error_burst`.
|
||||||
|
|
||||||
When the bytes counted for a request and its response break a limit, the
|
When the bytes counted for a request and its response break a limit, the
|
||||||
request has been passed on whole, so its `action` stays `forward`. Only its
|
request has been passed on whole, so its `action` stays `forward`. Only its
|
||||||
@@ -167,8 +166,8 @@ Every one of these lines has:
|
|||||||
|
|
||||||
- `rule_ids`: the rule file rules that matched, in order, up to the one that
|
- `rule_ids`: the rule file rules that matched, in order, up to the one that
|
||||||
refused.
|
refused.
|
||||||
- `core_rule_set_score` and `core_rule_set_rule_ids`: the Core Rule Set's score
|
- `waf_score` and `waf_rule_ids`: the Core Rule Set's score and the rules that
|
||||||
and the rules that matched, for a request it inspected.
|
matched, for a request it inspected.
|
||||||
- `reputation`: the sources the client is on, in this order:
|
- `reputation`: the sources the client is on, in this order:
|
||||||
- blocklist URLs;
|
- blocklist URLs;
|
||||||
- the CrowdSec decision list's URL;
|
- the CrowdSec decision list's URL;
|
||||||
@@ -190,14 +189,14 @@ Every one of these lines has:
|
|||||||
|
|
||||||
All in milliseconds:
|
All in milliseconds:
|
||||||
|
|
||||||
- `duration_total_ms`:
|
- `duration_total`:
|
||||||
- on the `decision` line, from `discriminator` having read the question's
|
- on the `decision` line, from `discriminator` having read the question's
|
||||||
body to the line;
|
body to the line;
|
||||||
- on the `report` line, from `rproxy` having read the request's headers to
|
- on the `report` line, from `rproxy` having read the request's headers to
|
||||||
the end of the answer.
|
the end of the answer.
|
||||||
- `duration_checks_ms`: to the end of the checks;
|
- `duration_checks`: to the end of the checks;
|
||||||
- `duration_core_rule_set_ms`: the part of that the Core Rule Set took;
|
- `duration_waf`: the part of that the Core Rule Set took;
|
||||||
- `duration_upstream_total_ms`: on the `report` line of an allowed request, from
|
- `duration_upstream_total`: on the `report` line of an allowed request, from
|
||||||
the hand-over to the app to the end of the answer.
|
the hand-over to the app to the end of the answer.
|
||||||
|
|
||||||
### Requests to its own endpoints
|
### Requests to its own endpoints
|
||||||
@@ -210,8 +209,8 @@ these meanings where they differ:
|
|||||||
- `scheme`: `http`.
|
- `scheme`: `http`.
|
||||||
- `time`: when the request's headers had been read.
|
- `time`: when the request's headers had been read.
|
||||||
- `request_bytes`: the bytes read of a ban to add, and otherwise `0`.
|
- `request_bytes`: the bytes read of a ban to add, and otherwise `0`.
|
||||||
- `action`: `own_endpoint`.
|
- `action`: `admin`.
|
||||||
- `duration_total_ms`: from the request's headers being read to the line.
|
- `duration_total`: from the request's headers being read to the line.
|
||||||
|
|
||||||
## `rproxy`'s line
|
## `rproxy`'s line
|
||||||
|
|
||||||
@@ -229,10 +228,10 @@ these meanings where they differ:
|
|||||||
a WebSocket carried from the visitor.
|
a WebSocket carried from the visitor.
|
||||||
- `response_bytes`: the bytes of the answer's body, with what a WebSocket
|
- `response_bytes`: the bytes of the answer's body, with what a WebSocket
|
||||||
carried from the app.
|
carried from the app.
|
||||||
- `duration_request_ms`: milliseconds from the request's headers being read
|
- `duration_request`: milliseconds from the request's headers being read until
|
||||||
until the app had been sent the whole request, or the answer started if that
|
the app had been sent the whole request, or the answer started if that was
|
||||||
was sooner. It includes the wait for `discriminator`.
|
sooner. It includes the wait for `discriminator`.
|
||||||
- `duration_response_ms`: milliseconds from then until the end of the answer.
|
- `duration_response`: milliseconds from then until the end of the answer.
|
||||||
- `disposition`: what was done with the request: `allow`, `deny` or `close`. It
|
- `disposition`: what was done with the request: `allow`, `deny` or `close`. It
|
||||||
is `discriminator`'s answer, or the value of `SWRP_DEFAULT_DISPOSITION`. It is
|
is `discriminator`'s answer, or the value of `SWRP_DEFAULT_DISPOSITION`. It is
|
||||||
left out when:
|
left out when:
|
||||||
@@ -246,5 +245,5 @@ these meanings where they differ:
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
{"type":"request","time":"2026-10-03T12:00:00.123Z","request_id":"7Q2NHZ4KJ3VXW5YB6R3MEFTD2A","client_ip":"203.0.113.9","host":"app.example","method":"GET","path":"/","query":"","status":200,"request_bytes":0,"response_bytes":5120,"duration_request_ms":1.204,"duration_response_ms":3.104,"disposition":"allow"}
|
{"type":"request","time":"2026-10-03T12:00:00.123Z","request_id":"7Q2NHZ4KJ3VXW5YB6R3MEFTD2A","client_ip":"203.0.113.9","host":"app.example","method":"GET","path":"/","query":"","status":200,"request_bytes":0,"response_bytes":5120,"duration_request":1.204,"duration_response":3.104,"disposition":"allow"}
|
||||||
```
|
```
|
||||||
+1
-1
@@ -324,7 +324,7 @@ the request first.
|
|||||||
- `SWW_ALERT_NTFY_TOKEN` (default unset): an ntfy access token. A control
|
- `SWW_ALERT_NTFY_TOKEN` (default unset): an ntfy access token. A control
|
||||||
character in it is refused.
|
character in it is refused.
|
||||||
- `SWW_ALERT_EVENTS` (default
|
- `SWW_ALERT_EVENTS` (default
|
||||||
`ban,permanent_ban,core_rule_set_match,anomaly,reputation_hit,source_failure,file_error`):
|
`ban,permanent_ban,waf_block,anomaly,reputation_hit,source_failure,file_error`):
|
||||||
the event types alerts are sent for, from those in [`alerts.md`](alerts.md)
|
the event types alerts are sent for, from those in [`alerts.md`](alerts.md)
|
||||||
but `summary`. Any other name is refused.
|
but `summary`. Any other name is refused.
|
||||||
- `SWW_ALERT_COOLDOWN` (default `15m`): how long after an alert is sent its
|
- `SWW_ALERT_COOLDOWN` (default `15m`): how long after an alert is sent its
|
||||||
|
|||||||
+2
-2
@@ -64,8 +64,8 @@ since it was first seen:
|
|||||||
- body bytes of its requests, and of the responses it was sent;
|
- body bytes of its requests, and of the responses it was sent;
|
||||||
- responses by status class;
|
- responses by status class;
|
||||||
- offences by kind: `limit`, `attack`, `blocked_by_block_rule` and
|
- offences by kind: `limit`, `attack`, `blocked_by_block_rule` and
|
||||||
`blocked_by_core_rule_set`. A file may also hold `token_refused`, which is
|
`waf_blocked`. A file may also hold `token_refused`, which is kept, and which
|
||||||
kept, and which nothing adds to.
|
nothing adds to.
|
||||||
|
|
||||||
## `lookups.json`
|
## `lookups.json`
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ const (
|
|||||||
// EventAnomaly is a count of requests or bytes over an anomaly
|
// EventAnomaly is a count of requests or bytes over an anomaly
|
||||||
// threshold.
|
// threshold.
|
||||||
EventAnomaly = "anomaly"
|
EventAnomaly = "anomaly"
|
||||||
// EventCoreRuleSetMatch is a request the Core Rule Set scored at or over
|
// EventWAFBlock is a request the Core Rule Set scored at or over
|
||||||
// SWW_WAF_ANOMALY_THRESHOLD, refused in block mode, let through in
|
// SWW_WAF_ANOMALY_THRESHOLD, refused in block mode, let through in
|
||||||
// detect mode.
|
// detect mode.
|
||||||
EventCoreRuleSetMatch = "core_rule_set_match"
|
EventWAFBlock = "waf_block"
|
||||||
// EventReputationHit is a request whose client a blocklist, the
|
// EventReputationHit is a request whose client a blocklist, the
|
||||||
// CrowdSec decision list or a DNSBL zone lists, or whose AbuseIPDB score
|
// CrowdSec decision list or a DNSBL zone lists, or whose AbuseIPDB score
|
||||||
// is a hit.
|
// is a hit.
|
||||||
@@ -72,7 +72,7 @@ const (
|
|||||||
// default.
|
// default.
|
||||||
func Events() []string {
|
func Events() []string {
|
||||||
return []string{
|
return []string{
|
||||||
EventBan, EventPermanentBan, EventCoreRuleSetMatch, EventAnomaly,
|
EventBan, EventPermanentBan, EventWAFBlock, EventAnomaly,
|
||||||
EventReputationHit, EventSourceFailure, EventFileError,
|
EventReputationHit, EventSourceFailure, EventFileError,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,7 +871,7 @@ func ntfyPriority(event string) string {
|
|||||||
return "high"
|
return "high"
|
||||||
case EventReputationHit:
|
case EventReputationHit:
|
||||||
return "low"
|
return "low"
|
||||||
default: // ban, core_rule_set_match and summary
|
default: // ban, waf_block and summary
|
||||||
return "default"
|
return "default"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -882,7 +882,7 @@ func ntfyTag(event string) string {
|
|||||||
switch event {
|
switch event {
|
||||||
case EventBan, EventPermanentBan:
|
case EventBan, EventPermanentBan:
|
||||||
return "no_entry"
|
return "no_entry"
|
||||||
case EventCoreRuleSetMatch:
|
case EventWAFBlock:
|
||||||
return "shield"
|
return "shield"
|
||||||
case EventAnomaly:
|
case EventAnomaly:
|
||||||
return "chart_with_upwards_trend"
|
return "chart_with_upwards_trend"
|
||||||
|
|||||||
@@ -1281,12 +1281,12 @@ func anAlertForEachEvent() []eventMessage {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
alerts.Alert{
|
alerts.Alert{
|
||||||
Event: alerts.EventCoreRuleSetMatch, Client: netip.MustParseAddr("192.0.2.1"),
|
Event: alerts.EventWAFBlock, Client: netip.MustParseAddr("192.0.2.1"),
|
||||||
Netblock: netip.MustParsePrefix("192.0.2.1/32"),
|
Netblock: netip.MustParsePrefix("192.0.2.1/32"),
|
||||||
Reason: "refused by the Core Rule Set",
|
Reason: "refused by the Core Rule Set",
|
||||||
Host: "app.example",
|
Host: "app.example",
|
||||||
},
|
},
|
||||||
"fsn1app1/blog: core_rule_set_match", "default shield",
|
"fsn1app1/blog: waf_block", "default shield",
|
||||||
"refused by the Core Rule Set\nhost: app.example\nclient: 192.0.2.1\n" +
|
"refused by the Core Rule Set\nhost: app.example\nclient: 192.0.2.1\n" +
|
||||||
"netblock: 192.0.2.1/32",
|
"netblock: 192.0.2.1/32",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ const (
|
|||||||
ScopeASN = "asn"
|
ScopeASN = "asn"
|
||||||
// ScopeTotal is the whole service.
|
// ScopeTotal is the whole service.
|
||||||
ScopeTotal = "total"
|
ScopeTotal = "total"
|
||||||
// ScopeWatchedNet is a named netblock of SWW_WATCH_NETS.
|
// ScopeWatch is a named netblock of SWW_WATCH_NETS.
|
||||||
ScopeWatchedNet = "watched_net"
|
ScopeWatch = "watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scopes returns every scope.
|
// Scopes returns every scope.
|
||||||
func Scopes() []string {
|
func Scopes() []string {
|
||||||
return []string{ScopeClient, ScopeNet, ScopeASN, ScopeTotal, ScopeWatchedNet}
|
return []string{ScopeClient, ScopeNet, ScopeASN, ScopeTotal, ScopeWatch}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The windows a counter counts in, as the alerts name them.
|
// The windows a counter counts in, as the alerts name them.
|
||||||
@@ -257,7 +257,7 @@ func (c *Counters) scopesOf(r Request) []scope {
|
|||||||
for _, named := range p.NamedNetblocks {
|
for _, named := range p.NamedNetblocks {
|
||||||
if named.Netblock.Contains(client) {
|
if named.Netblock.Contains(client) {
|
||||||
all = append(all, scope{
|
all = append(all, scope{
|
||||||
key{scope: ScopeWatchedNet, netblock: named.Netblock, name: named.Name}, p.Watch,
|
key{scope: ScopeWatch, netblock: named.Netblock, name: named.Name}, p.Watch,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -13,7 +13,7 @@ func TestBanWithoutACauseIsAnAdmins(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{{Netblock: netblock, Start: midnight()}})
|
ledger.Load([]bans.Ban{{Netblock: netblock, Start: midnight()}})
|
||||||
|
|
||||||
if got := ledger.Bans(netblock)[0].Cause; got != bans.CauseAdmin {
|
if got := ledger.Bans(netblock)[0].Cause; got != bans.CauseAdmin {
|
||||||
@@ -24,9 +24,9 @@ func TestBanWithoutACauseIsAnAdmins(t *testing.T) {
|
|||||||
func TestAdminsBansAreNeverDroppedAndDoNotCountTowardMaxBans(t *testing.T) {
|
func TestAdminsBansAreNeverDroppedAndDoNotCountTowardMaxBans(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 1
|
rules.MaxBans = 1
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
adminsOnly := netip.MustParsePrefix("198.51.100.0/24")
|
adminsOnly := netip.MustParsePrefix("198.51.100.0/24")
|
||||||
both := netip.MustParsePrefix("203.0.113.1/32")
|
both := netip.MustParsePrefix("203.0.113.1/32")
|
||||||
second := netip.MustParsePrefix("203.0.113.2/32")
|
second := netip.MustParsePrefix("203.0.113.2/32")
|
||||||
@@ -64,9 +64,9 @@ func TestAdminsBansAreNeverDroppedAndDoNotCountTowardMaxBans(t *testing.T) {
|
|||||||
func TestEarlierBansCountABanDroppedAfterAnAdminsBan(t *testing.T) {
|
func TestEarlierBansCountABanDroppedAfterAnAdminsBan(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 2
|
rules.MaxBans = 2
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
netblock := netip.MustParsePrefix("203.0.113.1/32")
|
netblock := netip.MustParsePrefix("203.0.113.1/32")
|
||||||
other := netip.MustParsePrefix("203.0.113.2/32")
|
other := netip.MustParsePrefix("203.0.113.2/32")
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ func TestEarlierBansCountABanDroppedAfterAnAdminsBan(t *testing.T) {
|
|||||||
func TestEarlierBansCountABanAnAdminKeepsOnce(t *testing.T) {
|
func TestEarlierBansCountABanAnAdminKeepsOnce(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.1/32")
|
netblock := netip.MustParsePrefix("203.0.113.1/32")
|
||||||
|
|
||||||
// The netblock breaks a limit twice, the second time after its first
|
// The netblock breaks a limit twice, the second time after its first
|
||||||
@@ -117,7 +117,7 @@ func TestEarlierBansCountABanAnAdminKeepsOnce(t *testing.T) {
|
|||||||
func TestReasonOfTheBansSwwMakes(t *testing.T) {
|
func TestReasonOfTheBansSwwMakes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
|
|
||||||
limit, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.1/32"), midnight(),
|
limit, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.1/32"), midnight(),
|
||||||
bans.Notes{Kind: "requests", Limit: 1000, Window: "minute"})
|
bans.Notes{Kind: "requests", Limit: 1000, Window: "minute"})
|
||||||
@@ -150,7 +150,7 @@ func TestLiftedBanForALimitRefusesNothingAndMakesNoBanLonger(t *testing.T) {
|
|||||||
Lifted: midnight().Add(10 * time.Minute),
|
Lifted: midnight().Add(10 * time.Minute),
|
||||||
}
|
}
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{lifted})
|
ledger.Load([]bans.Ban{lifted})
|
||||||
|
|
||||||
// While it would still last, it refuses nothing, and a limit broken
|
// While it would still last, it refuses nothing, and a limit broken
|
||||||
@@ -181,7 +181,7 @@ func TestLiftedBanForAnAttackRefusesNothingAndMakesNoBanLonger(t *testing.T) {
|
|||||||
|
|
||||||
// A permanent ban for a clear sign of attack, lifted.
|
// A permanent ban for a clear sign of attack, lifted.
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{{
|
ledger.Load([]bans.Ban{{
|
||||||
Netblock: netblock,
|
Netblock: netblock,
|
||||||
Start: midnight(),
|
Start: midnight(),
|
||||||
@@ -211,7 +211,7 @@ func TestLiftedBanForAnAttackRefusesNothingAndMakesNoBanLonger(t *testing.T) {
|
|||||||
func TestLoadEditCountsTheBansAnAdminMade(t *testing.T) {
|
func TestLoadEditCountsTheBansAnAdminMade(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
made, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.1/32"), midnight(),
|
made, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.1/32"), midnight(),
|
||||||
bans.Notes{})
|
bans.Notes{})
|
||||||
atStart := bans.Ban{
|
atStart := bans.Ban{
|
||||||
@@ -246,7 +246,7 @@ func TestAdminsBanIsMadeWhileAnotherLasts(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
|
|
||||||
// An hour's ban for a broken limit.
|
// An hour's ban for a broken limit.
|
||||||
ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
||||||
@@ -292,7 +292,7 @@ func TestLiftLiftsEveryActiveBanCoveringTheClient(t *testing.T) {
|
|||||||
wide := netip.MustParsePrefix("203.0.113.0/24")
|
wide := netip.MustParsePrefix("203.0.113.0/24")
|
||||||
other := netip.MustParsePrefix("203.0.113.10/32")
|
other := netip.MustParsePrefix("203.0.113.10/32")
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{
|
ledger.Load([]bans.Ban{
|
||||||
// Ended an hour ago.
|
// Ended an hour ago.
|
||||||
{
|
{
|
||||||
@@ -346,7 +346,7 @@ func TestPermanentBanOnAWiderNetblockIsReturnedOverATemporaryBan(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
client := netip.MustParseAddr("203.0.113.9")
|
client := netip.MustParseAddr("203.0.113.9")
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
|
|
||||||
// The temporary ban is made first, so that its netblock is looked at first.
|
// The temporary ban is made first, so that its netblock is looked at first.
|
||||||
ledger.BanForLimit(netip.MustParsePrefix("203.0.113.9/32"), midnight(), bans.Notes{})
|
ledger.BanForLimit(netip.MustParsePrefix("203.0.113.9/32"), midnight(), bans.Notes{})
|
||||||
@@ -360,7 +360,7 @@ func TestOlderPermanentBanIsReturnedOverANewerTemporaryBan(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
|
|
||||||
ledger.BanForAdmin(netblock, midnight(), time.Time{}, "for good")
|
ledger.BanForAdmin(netblock, midnight(), time.Time{}, "for good")
|
||||||
ledger.BanForAdmin(netblock, midnight().Add(time.Minute), midnight().Add(time.Hour),
|
ledger.BanForAdmin(netblock, midnight().Add(time.Minute), midnight().Add(time.Hour),
|
||||||
|
|||||||
+12
-12
@@ -40,8 +40,8 @@ const repeatFactor = 3
|
|||||||
// maxTextBytes is how much of each text in a ban's notes is kept.
|
// maxTextBytes is how much of each text in a ban's notes is kept.
|
||||||
const maxTextBytes = 256
|
const maxTextBytes = 256
|
||||||
|
|
||||||
// Params are how long a ban lasts, and how many bans are held.
|
// Rules are how long a ban lasts, and how many bans are held.
|
||||||
type Params struct {
|
type Rules struct {
|
||||||
// LimitBanDuration is how long a first ban for a broken limit lasts.
|
// LimitBanDuration is how long a first ban for a broken limit lasts.
|
||||||
LimitBanDuration time.Duration
|
LimitBanDuration time.Duration
|
||||||
// LimitBanRepeatWindow is how soon after the end of the netblock's
|
// LimitBanRepeatWindow is how soon after the end of the netblock's
|
||||||
@@ -180,7 +180,7 @@ type Request struct {
|
|||||||
|
|
||||||
// Ledger holds the bans. It is safe for concurrent use.
|
// Ledger holds the bans. It is safe for concurrent use.
|
||||||
type Ledger struct {
|
type Ledger struct {
|
||||||
params Params
|
rules Rules
|
||||||
// changed receives a value when a ban is made, unless one is waiting
|
// changed receives a value when a ban is made, unless one is waiting
|
||||||
// already.
|
// already.
|
||||||
changed chan struct{}
|
changed chan struct{}
|
||||||
@@ -190,7 +190,7 @@ type Ledger struct {
|
|||||||
// Find make each netblock they find the most recently seen.
|
// Find make each netblock they find the most recently seen.
|
||||||
netblocks *simplelru.LRU[netip.Prefix, *[]Ban]
|
netblocks *simplelru.LRU[netip.Prefix, *[]Ban]
|
||||||
// held is how many bans netblocks holds whose cause is not CauseAdmin,
|
// held is how many bans netblocks holds whose cause is not CauseAdmin,
|
||||||
// at most params.MaxBans.
|
// at most rules.MaxBans.
|
||||||
held int
|
held int
|
||||||
// made is how many bans have been made since the start, by cause: by
|
// made is how many bans have been made since the start, by cause: by
|
||||||
// the ledger, and by an admin, through BanForAdmin or in an edit of
|
// the ledger, and by an admin, through BanForAdmin or in an edit of
|
||||||
@@ -205,7 +205,7 @@ type Ledger struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New returns a Ledger with no ban yet.
|
// New returns a Ledger with no ban yet.
|
||||||
func New(params Params) *Ledger {
|
func New(rules Rules) *Ledger {
|
||||||
// The ledger drops bans itself, and never those whose cause is
|
// The ledger drops bans itself, and never those whose cause is
|
||||||
// CauseAdmin, however many there are, so the LRU has no limit of its
|
// CauseAdmin, however many there are, so the LRU has no limit of its
|
||||||
// own: it keeps the netblocks in the order they were last seen.
|
// own: it keeps the netblocks in the order they were last seen.
|
||||||
@@ -215,7 +215,7 @@ func New(params Params) *Ledger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Ledger{
|
return &Ledger{
|
||||||
params: params,
|
rules: rules,
|
||||||
changed: make(chan struct{}, 1),
|
changed: make(chan struct{}, 1),
|
||||||
netblocks: netblocks,
|
netblocks: netblocks,
|
||||||
made: map[string]int{},
|
made: map[string]int{},
|
||||||
@@ -812,7 +812,7 @@ func (l *Ledger) covering(client netip.Addr) []*[]Ban {
|
|||||||
// unless ban's cause is CauseAdmin, which does not count toward MaxBans.
|
// unless ban's cause is CauseAdmin, which does not count toward MaxBans.
|
||||||
func (l *Ledger) add(ban Ban) {
|
func (l *Ledger) add(ban Ban) {
|
||||||
counted := ban.Cause != CauseAdmin
|
counted := ban.Cause != CauseAdmin
|
||||||
if counted && l.held == l.params.MaxBans {
|
if counted && l.held == l.rules.MaxBans {
|
||||||
l.dropOne()
|
l.dropOne()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -847,7 +847,7 @@ func (l *Ledger) add(ban Ban) {
|
|||||||
// new ban longer. A ban an admin adds to bans.json can start after
|
// new ban longer. A ban an admin adds to bans.json can start after
|
||||||
// another and end before it, so that one is looked for among them all.
|
// another and end before it, so that one is looked for among them all.
|
||||||
func (l *Ledger) limitExpiry(held []Ban, now time.Time) time.Time {
|
func (l *Ledger) limitExpiry(held []Ban, now time.Time) time.Time {
|
||||||
length := l.params.LimitBanDuration
|
length := l.rules.LimitBanDuration
|
||||||
|
|
||||||
var last *Ban
|
var last *Ban
|
||||||
|
|
||||||
@@ -858,18 +858,18 @@ func (l *Ledger) limitExpiry(held []Ban, now time.Time) time.Time {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if last != nil && now.Sub(last.Expires) <= l.params.LimitBanRepeatWindow {
|
if last != nil && now.Sub(last.Expires) <= l.rules.LimitBanRepeatWindow {
|
||||||
lastLength := last.Expires.Sub(last.Start)
|
lastLength := last.Expires.Sub(last.Start)
|
||||||
// This is repeatFactor * lastLength > MaxBanDuration, written so
|
// This is repeatFactor * lastLength > MaxBanDuration, written so
|
||||||
// that it cannot overflow.
|
// that it cannot overflow.
|
||||||
if lastLength > l.params.MaxBanDuration/repeatFactor {
|
if lastLength > l.rules.MaxBanDuration/repeatFactor {
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
length = repeatFactor * lastLength
|
length = repeatFactor * lastLength
|
||||||
}
|
}
|
||||||
|
|
||||||
if length > l.params.MaxBanDuration {
|
if length > l.rules.MaxBanDuration {
|
||||||
return time.Time{}
|
return time.Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,7 +887,7 @@ func (l *Ledger) attackExpiry(held []Ban, now time.Time) time.Time {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return now.Add(l.params.AttackBanDuration)
|
return now.Add(l.rules.AttackBanDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dropOne drops the earliest ban whose cause is not CauseAdmin of the
|
// dropOne drops the earliest ban whose cause is not CauseAdmin of the
|
||||||
|
|||||||
+27
-27
@@ -15,7 +15,7 @@ const day = 24 * time.Hour
|
|||||||
func TestRepeatsTripleUntilPermanent(t *testing.T) {
|
func TestRepeatsTripleUntilPermanent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
now := midnight()
|
now := midnight()
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ func TestRepeatWindowRunsOut(t *testing.T) {
|
|||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
||||||
@@ -80,9 +80,9 @@ func TestRepeatWindowRunsOut(t *testing.T) {
|
|||||||
func TestFirstBanLongerThanTheMaximumIsPermanent(t *testing.T) {
|
func TestFirstBanLongerThanTheMaximumIsPermanent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.LimitBanDuration = params.MaxBanDuration + time.Hour
|
rules.LimitBanDuration = rules.MaxBanDuration + time.Hour
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
|
|
||||||
ban, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.9/32"), midnight(),
|
ban, _ := ledger.BanForLimit(netip.MustParsePrefix("203.0.113.9/32"), midnight(),
|
||||||
bans.Notes{})
|
bans.Notes{})
|
||||||
@@ -97,9 +97,9 @@ func TestLongestBanSetFarOffDoesNotOverflow(t *testing.T) {
|
|||||||
// With bans of up to 100,000 days, the 14th ban in a row, of 3^13
|
// With bans of up to 100,000 days, the 14th ban in a row, of 3^13
|
||||||
// hours, is within the maximum, and three times as long would not fit
|
// hours, is within the maximum, and three times as long would not fit
|
||||||
// in a time.Duration. The 15th is permanent.
|
// in a time.Duration. The 15th is permanent.
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBanDuration = 100000 * day
|
rules.MaxBanDuration = 100000 * day
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
now := midnight()
|
now := midnight()
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ func TestLongestBanSetFarOffDoesNotOverflow(t *testing.T) {
|
|||||||
func TestBrokenLimitDuringABanMakesNoOther(t *testing.T) {
|
func TestBrokenLimitDuringABanMakesNoOther(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
first, made := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
first, made := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
||||||
@@ -146,7 +146,7 @@ func TestBrokenLimitDuringABanMakesNoOther(t *testing.T) {
|
|||||||
func TestCheckRefusesWhileTheBanLastsAndCountsTheRefusals(t *testing.T) {
|
func TestCheckRefusesWhileTheBanLastsAndCountsTheRefusals(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
ban, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{Requests: 5})
|
ban, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{Requests: 5})
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ func TestCheckRefusesWhileTheBanLastsAndCountsTheRefusals(t *testing.T) {
|
|||||||
func TestFindCountsNothing(t *testing.T) {
|
func TestFindCountsNothing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
ban, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{Requests: 5})
|
ban, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{Requests: 5})
|
||||||
|
|
||||||
@@ -200,9 +200,9 @@ func TestFindCountsNothing(t *testing.T) {
|
|||||||
func TestMaxBansDropsTheEarliestBanOfTheNetblockSeenLongestAgo(t *testing.T) {
|
func TestMaxBansDropsTheEarliestBanOfTheNetblockSeenLongestAgo(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 3
|
rules.MaxBans = 3
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
a := netip.MustParsePrefix("203.0.113.1/32")
|
a := netip.MustParsePrefix("203.0.113.1/32")
|
||||||
b := netip.MustParsePrefix("203.0.113.2/32")
|
b := netip.MustParsePrefix("203.0.113.2/32")
|
||||||
c := netip.MustParsePrefix("203.0.113.3/32")
|
c := netip.MustParsePrefix("203.0.113.3/32")
|
||||||
@@ -239,9 +239,9 @@ func TestFullLedgerDropsTheEarlierBanOfTheNetblockBannedAgain(t *testing.T) {
|
|||||||
|
|
||||||
// With room for one ban, the netblock's ended ban goes to make room for
|
// With room for one ban, the netblock's ended ban goes to make room for
|
||||||
// its new one, whose notes still count it.
|
// its new one, whose notes still count it.
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 1
|
rules.MaxBans = 1
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
||||||
@@ -258,7 +258,7 @@ func TestFullLedgerDropsTheEarlierBanOfTheNetblockBannedAgain(t *testing.T) {
|
|||||||
func TestRequestDuringAnAttackBanMakesItPermanent(t *testing.T) {
|
func TestRequestDuringAnAttackBanMakesItPermanent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
notes := bans.Notes{RuleID: "env-file", Target: "path"}
|
notes := bans.Notes{RuleID: "env-file", Target: "path"}
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ func TestRequestDuringAnAttackBanMakesItPermanent(t *testing.T) {
|
|||||||
func TestAttackAfterAnAttackBanHasEndedBansPermanently(t *testing.T) {
|
func TestAttackAfterAnAttackBanHasEndedBansPermanently(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
// A ban for a broken limit before does not count.
|
// A ban for a broken limit before does not count.
|
||||||
@@ -336,7 +336,7 @@ func TestAttackAfterAnAttackBanHasEndedBansPermanently(t *testing.T) {
|
|||||||
func TestWouldBanGivesTheBanWithoutMakingIt(t *testing.T) {
|
func TestWouldBanGivesTheBanWithoutMakingIt(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
first, _ := ledger.BanForLimit(netblock, midnight(), bans.Notes{})
|
||||||
wantChanged(t, ledger, true)
|
wantChanged(t, ledger, true)
|
||||||
@@ -380,7 +380,7 @@ func TestWouldBanGivesTheBanWithoutMakingIt(t *testing.T) {
|
|||||||
func TestWouldBePermanentAnswersAsTheBanWouldBeMade(t *testing.T) {
|
func TestWouldBePermanentAnswersAsTheBanWouldBeMade(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
now := midnight()
|
now := midnight()
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ func TestWouldBePermanentAnswersAsTheBanWouldBeMade(t *testing.T) {
|
|||||||
func TestAttackBanDoesNotLengthenTheNextBanForALimit(t *testing.T) {
|
func TestAttackBanDoesNotLengthenTheNextBanForALimit(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
// Three times the seven days would be permanent; a limit broken as the
|
// Three times the seven days would be permanent; a limit broken as the
|
||||||
@@ -436,7 +436,7 @@ func TestAttackBanDoesNotLengthenTheNextBanForALimit(t *testing.T) {
|
|||||||
func TestRequestTextsAreCutTo256Bytes(t *testing.T) {
|
func TestRequestTextsAreCutTo256Bytes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
long := strings.Repeat("a", 300)
|
long := strings.Repeat("a", 300)
|
||||||
request := bans.Request{
|
request := bans.Request{
|
||||||
@@ -458,7 +458,7 @@ func TestRequestTextsAreCutTo256Bytes(t *testing.T) {
|
|||||||
func TestLookupFillsTheNotesOfTheNetblocksBansWithoutOne(t *testing.T) {
|
func TestLookupFillsTheNotesOfTheNetblocksBansWithoutOne(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
other := netip.MustParsePrefix("198.51.100.7/32")
|
other := netip.MustParsePrefix("198.51.100.7/32")
|
||||||
|
|
||||||
@@ -494,9 +494,9 @@ func TestLookupFillsTheNotesOfTheNetblocksBansWithoutOne(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultParams are the params at the settings' defaults.
|
// defaultRules are the rules at the settings' defaults.
|
||||||
func defaultParams() bans.Params {
|
func defaultRules() bans.Rules {
|
||||||
return bans.Params{
|
return bans.Rules{
|
||||||
LimitBanDuration: time.Hour,
|
LimitBanDuration: time.Hour,
|
||||||
LimitBanRepeatWindow: day,
|
LimitBanRepeatWindow: day,
|
||||||
MaxBanDuration: 7 * day,
|
MaxBanDuration: 7 * day,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const scenario = "crowdsecurity/ssh-bf"
|
|||||||
func TestCrowdSecBanLastsUntilTheDecisionEnds(t *testing.T) {
|
func TestCrowdSecBanLastsUntilTheDecisionEnds(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
expires := midnight().Add(4 * time.Hour)
|
expires := midnight().Add(4 * time.Hour)
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ func TestCrowdSecBanLastsUntilTheDecisionEnds(t *testing.T) {
|
|||||||
func TestCrowdSecBanIsNeverMadePermanent(t *testing.T) {
|
func TestCrowdSecBanIsNeverMadePermanent(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
expires := midnight().Add(4 * time.Hour)
|
expires := midnight().Add(4 * time.Hour)
|
||||||
ledger.BanForCrowdSec(netblock, midnight(), expires, scenario, bans.Notes{})
|
ledger.BanForCrowdSec(netblock, midnight(), expires, scenario, bans.Notes{})
|
||||||
@@ -72,7 +72,7 @@ func TestCrowdSecBanIsNeverMadePermanent(t *testing.T) {
|
|||||||
func TestCrowdSecBanIsCountedAndDoesNotLengthenTheNextBanForALimit(t *testing.T) {
|
func TestCrowdSecBanIsCountedAndDoesNotLengthenTheNextBanForALimit(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
// Three times the three days would be permanent; a limit broken as the
|
// Three times the three days would be permanent; a limit broken as the
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
func TestChangedAfterABanIsMade(t *testing.T) {
|
func TestChangedAfterABanIsMade(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
|
|
||||||
wantChanged(t, ledger, false)
|
wantChanged(t, ledger, false)
|
||||||
@@ -38,7 +38,7 @@ func TestChangedAfterABanIsMade(t *testing.T) {
|
|||||||
func TestSnapshotListsEveryBanByNetblock(t *testing.T) {
|
func TestSnapshotListsEveryBanByNetblock(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
v6 := netip.MustParsePrefix("2001:db8::/64")
|
v6 := netip.MustParsePrefix("2001:db8::/64")
|
||||||
high := netip.MustParsePrefix("203.0.113.10/32")
|
high := netip.MustParsePrefix("203.0.113.10/32")
|
||||||
low := netip.MustParsePrefix("203.0.113.9/32")
|
low := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
@@ -67,14 +67,14 @@ func TestSnapshotListsEveryBanByNetblock(t *testing.T) {
|
|||||||
func TestLoadedBansCarryOn(t *testing.T) {
|
func TestLoadedBansCarryOn(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
before := bans.New(defaultParams())
|
before := bans.New(defaultRules())
|
||||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||||
ban, _ := before.BanForLimit(netblock, midnight(), bans.Notes{Limit: 1})
|
ban, _ := before.BanForLimit(netblock, midnight(), bans.Notes{Limit: 1})
|
||||||
|
|
||||||
// Loaded into a new ledger, as across a restart, the ban still refuses
|
// Loaded into a new ledger, as across a restart, the ban still refuses
|
||||||
// while it lasts, and once it has ended a broken limit bans for three
|
// while it lasts, and once it has ended a broken limit bans for three
|
||||||
// times as long, with the loaded ban counted among the earlier ones.
|
// times as long, with the loaded ban counted among the earlier ones.
|
||||||
after := bans.New(defaultParams())
|
after := bans.New(defaultRules())
|
||||||
after.Load(before.Snapshot())
|
after.Load(before.Snapshot())
|
||||||
|
|
||||||
_, banned, _ := after.Check(netblock.Addr(), ban.Expires.Add(-time.Second))
|
_, banned, _ := after.Check(netblock.Addr(), ban.Expires.Add(-time.Second))
|
||||||
@@ -96,7 +96,7 @@ func TestLoadedBanRefusesEveryClientInItsNetblock(t *testing.T) {
|
|||||||
// Two entries as an admin might write them, with addresses not masked
|
// Two entries as an admin might write them, with addresses not masked
|
||||||
// to their lengths, the IPv6 one shorter than the /64 an IPv6 client's
|
// to their lengths, the IPv6 one shorter than the /64 an IPv6 client's
|
||||||
// ban covers, beside a ban the ledger makes on one IPv4 address.
|
// ban covers, beside a ban the ledger makes on one IPv4 address.
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{
|
ledger.Load([]bans.Ban{
|
||||||
{Netblock: netip.MustParsePrefix("203.0.113.9/24"), Start: midnight()},
|
{Netblock: netip.MustParsePrefix("203.0.113.9/24"), Start: midnight()},
|
||||||
{Netblock: netip.MustParsePrefix("2001:db8::1/48"), Start: midnight()},
|
{Netblock: netip.MustParsePrefix("2001:db8::1/48"), Start: midnight()},
|
||||||
@@ -145,7 +145,7 @@ func TestPermanentBanStartedBeforeAnEndedOneRefuses(t *testing.T) {
|
|||||||
Expires: midnight().Add(time.Hour),
|
Expires: midnight().Add(time.Hour),
|
||||||
}
|
}
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{permanent, ended})
|
ledger.Load([]bans.Ban{permanent, ended})
|
||||||
|
|
||||||
now := midnight().Add(2 * time.Hour)
|
now := midnight().Add(2 * time.Hour)
|
||||||
@@ -189,7 +189,7 @@ func TestNextBanWorkedOutFromTheBanThatEndedLast(t *testing.T) {
|
|||||||
Expires: midnight().Add(2 * time.Hour),
|
Expires: midnight().Add(2 * time.Hour),
|
||||||
}
|
}
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{nineHours, admins})
|
ledger.Load([]bans.Ban{nineHours, admins})
|
||||||
|
|
||||||
// Once both have ended, a limit broken within the repeat window bans
|
// Once both have ended, a limit broken within the repeat window bans
|
||||||
@@ -219,9 +219,9 @@ func TestLoadKeepsAtMostMaxBansDroppingTheEarliest(t *testing.T) {
|
|||||||
Cause: bans.CauseLimit,
|
Cause: bans.CauseLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 1
|
rules.MaxBans = 1
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
ledger.Load([]bans.Ban{later, earlier})
|
ledger.Load([]bans.Ban{later, earlier})
|
||||||
|
|
||||||
held := ledger.Snapshot()
|
held := ledger.Snapshot()
|
||||||
@@ -235,9 +235,9 @@ func TestLoadReplacesTheBansHeld(t *testing.T) {
|
|||||||
|
|
||||||
// Room for three bans, so that the second load, were it added to the
|
// Room for three bans, so that the second load, were it added to the
|
||||||
// two bans held, would drop none of them to make room.
|
// two bans held, would drop none of them to make room.
|
||||||
params := defaultParams()
|
rules := defaultRules()
|
||||||
params.MaxBans = 3
|
rules.MaxBans = 3
|
||||||
ledger := bans.New(params)
|
ledger := bans.New(rules)
|
||||||
kept := bans.Ban{
|
kept := bans.Ban{
|
||||||
Netblock: netip.MustParsePrefix("2001:db8::/64"),
|
Netblock: netip.MustParsePrefix("2001:db8::/64"),
|
||||||
Start: midnight(),
|
Start: midnight(),
|
||||||
@@ -285,7 +285,7 @@ func TestLoadCutsTheTextsTo256Bytes(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
|
|
||||||
ledger := bans.New(defaultParams())
|
ledger := bans.New(defaultRules())
|
||||||
ledger.Load([]bans.Ban{ban})
|
ledger.Load([]bans.Ban{ban})
|
||||||
|
|
||||||
cut := long[:256]
|
cut := long[:256]
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ const (
|
|||||||
maxParanoiaLevel = 4
|
maxParanoiaLevel = 4
|
||||||
// firstSetupRuleID to lastSetupRuleID are the ids the Core Rule Set
|
// firstSetupRuleID to lastSetupRuleID are the ids the Core Rule Set
|
||||||
// keeps for the rules that set it up, which sww's own rules
|
// keeps for the rules that set it up, which sww's own rules
|
||||||
// have too (see internal/coreruleset). Switching one off would undo a change
|
// have too (see internal/waf). Switching one off would undo a change
|
||||||
// that no setting undoes.
|
// that no setting undoes.
|
||||||
firstSetupRuleID = 900000
|
firstSetupRuleID = 900000
|
||||||
lastSetupRuleID = 900999
|
lastSetupRuleID = 900999
|
||||||
@@ -432,7 +432,7 @@ var (
|
|||||||
"holds a control character, such as the carriage return of a Windows line end",
|
"holds a control character, such as the carriage return of a Windows line end",
|
||||||
)
|
)
|
||||||
errNotAlertEvent = errors.New(
|
errNotAlertEvent = errors.New(
|
||||||
"is not ban, permanent_ban, core_rule_set_match, anomaly, reputation_hit, " +
|
"is not ban, permanent_ban, waf_block, anomaly, reputation_hit, " +
|
||||||
"source_failure or file_error")
|
"source_failure or file_error")
|
||||||
errNotNumberOrOff = errors.New(
|
errNotNumberOrOff = errors.New(
|
||||||
"is not a whole number above zero, such as 60, or off",
|
"is not a whole number above zero, such as 60, or off",
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ func loggedAnomalyDefaults() map[string]string {
|
|||||||
// defaultAlertEvents is the default of SWW_ALERT_EVENTS, and
|
// defaultAlertEvents is the default of SWW_ALERT_EVENTS, and
|
||||||
// defaultAlertCooldown that of SWW_ALERT_COOLDOWN.
|
// defaultAlertCooldown that of SWW_ALERT_COOLDOWN.
|
||||||
const (
|
const (
|
||||||
defaultAlertEvents = "ban,permanent_ban,core_rule_set_match,anomaly,reputation_hit," +
|
defaultAlertEvents = "ban,permanent_ban,waf_block,anomaly,reputation_hit," +
|
||||||
"source_failure,file_error"
|
"source_failure,file_error"
|
||||||
defaultAlertCooldown = "15m"
|
defaultAlertCooldown = "15m"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ var (
|
|||||||
|
|
||||||
// answerHealth answers a request for the health endpoint.
|
// answerHealth answers a request for the health endpoint.
|
||||||
func (rq *request) answerHealth() {
|
func (rq *request) answerHealth() {
|
||||||
rq.line.Action = requestlog.ActionOwnEndpoint
|
rq.line.Action = requestlog.ActionAdmin
|
||||||
// Set here rather than left to Go's server, which would set it only
|
// Set here rather than left to Go's server, which would set it only
|
||||||
// after the log line has taken the response's headers.
|
// after the log line has taken the response's headers.
|
||||||
rq.out.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
rq.out.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
@@ -55,7 +55,7 @@ func (rq *request) answerHealth() {
|
|||||||
// refused with 401. An endpoint whose token is unset answers 404, as any other
|
// refused with 401. An endpoint whose token is unset answers 404, as any other
|
||||||
// path does.
|
// path does.
|
||||||
func (rq *request) answerAdmin() {
|
func (rq *request) answerAdmin() {
|
||||||
rq.line.Action = requestlog.ActionOwnEndpoint
|
rq.line.Action = requestlog.ActionAdmin
|
||||||
|
|
||||||
token, answer := rq.endpoint()
|
token, answer := rq.endpoint()
|
||||||
|
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ func adminEndpoints() []adminEndpoint {
|
|||||||
|
|
||||||
// admin sends a request with method for path, with body, to discriminator's own
|
// admin sends a request with method for path, with body, to discriminator's own
|
||||||
// address, with the admin token, and checks that it is answered with status, its
|
// address, with the admin token, and checks that it is answered with status, its
|
||||||
// log line's action own_endpoint. It returns the answer.
|
// log line's action admin. It returns the answer.
|
||||||
func (s *sender) admin(method, path, body string, status int) answer {
|
func (s *sender) admin(method, path, body string, status int) answer {
|
||||||
s.t.Helper()
|
s.t.Helper()
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ func (s *sender) adminRequest(
|
|||||||
|
|
||||||
line := s.out.endedLines(s.t, s.sent+1)[s.sent]
|
line := s.out.endedLines(s.t, s.sent+1)[s.sent]
|
||||||
s.sent++
|
s.sent++
|
||||||
wantLine(s.t, line, status, requestlog.ActionOwnEndpoint)
|
wantLine(s.t, line, status, requestlog.ActionAdmin)
|
||||||
|
|
||||||
return got
|
return got
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ func TestEachScopeAndWindowOverItsThresholdAlertsOncePerCooldown(t *testing.T) {
|
|||||||
{anomalyASN, anomaly.ScopeASN, netip.Prefix{}, asnDE, map[string]any{"asn": asnDE}},
|
{anomalyASN, anomaly.ScopeASN, netip.Prefix{}, asnDE, map[string]any{"asn": asnDE}},
|
||||||
{anomalyTotal, anomaly.ScopeTotal, netip.Prefix{}, "the whole service", nil},
|
{anomalyTotal, anomaly.ScopeTotal, netip.Prefix{}, "the whole service", nil},
|
||||||
{
|
{
|
||||||
anomalyWatch, anomaly.ScopeWatchedNet, netip.MustParsePrefix(clientsNet),
|
anomalyWatch, anomaly.ScopeWatch, netip.MustParsePrefix(clientsNet),
|
||||||
"the named netblock office, " + clientsNet, map[string]any{"name": "office"},
|
"the named netblock office, " + clientsNet, map[string]any{"name": "office"},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ func TestSixteenThousandCookiesAreRefusedWellWithinTheTimeLimit(t *testing.T) {
|
|||||||
line := s.out.requestLine(t)
|
line := s.out.requestLine(t)
|
||||||
wantLine(t, line, tooLarge, requestlog.ActionRequestHeaderTooLarge)
|
wantLine(t, line, tooLarge, requestlog.ActionRequestHeaderTooLarge)
|
||||||
|
|
||||||
if line.DurationCoreRuleSetMS != nil {
|
if line.DurationWAF != nil {
|
||||||
t.Errorf("the Core Rule Set read the request, for %f ms", *line.DurationCoreRuleSetMS)
|
t.Errorf("the Core Rule Set read the request, for %f ms", *line.DurationWAF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ func TestEachHeaderLimitRefusesARequestOverIt(t *testing.T) {
|
|||||||
wantDisposition(t, got, http.StatusOK, discriminator.DispositionAllow)
|
wantDisposition(t, got, http.StatusOK, discriminator.DispositionAllow)
|
||||||
wantLine(t, line, http.StatusOK, requestlog.ActionForward)
|
wantLine(t, line, http.StatusOK, requestlog.ActionForward)
|
||||||
|
|
||||||
if line.DurationCoreRuleSetMS == nil {
|
if line.DurationWAF == nil {
|
||||||
t.Error("the Core Rule Set did not read a request within the limits")
|
t.Error("the Core Rule Set did not read a request within the limits")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -220,9 +220,9 @@ func TestObserveModeAllowsARequestOverTheHeaderLimitsUnread(t *testing.T) {
|
|||||||
|
|
||||||
line := s.out.requestLine(t)
|
line := s.out.requestLine(t)
|
||||||
if line.WouldAction != requestlog.ActionRequestHeaderTooLarge ||
|
if line.WouldAction != requestlog.ActionRequestHeaderTooLarge ||
|
||||||
line.DurationCoreRuleSetMS != nil {
|
line.DurationWAF != nil {
|
||||||
t.Errorf("would_action %q and duration_core_rule_set_ms %v, want %q and none",
|
t.Errorf("would_action %q and duration_waf %v, want %q and none",
|
||||||
line.WouldAction, line.DurationCoreRuleSetMS, requestlog.ActionRequestHeaderTooLarge)
|
line.WouldAction, line.DurationWAF, requestlog.ActionRequestHeaderTooLarge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,8 +283,8 @@ func TestNotWaitingForGeoJSNeverLowersAClientsLimit(t *testing.T) {
|
|||||||
line := s.out.requestLine(t)
|
line := s.out.requestLine(t)
|
||||||
wantLine(t, line, tooLarge, requestlog.ActionRequestHeaderTooLarge)
|
wantLine(t, line, tooLarge, requestlog.ActionRequestHeaderTooLarge)
|
||||||
|
|
||||||
if line.RateLimitPercent != nil {
|
if line.LimitPercent != nil {
|
||||||
t.Errorf("limit percentage %d, want none", *line.RateLimitPercent)
|
t.Errorf("limit percentage %d, want none", *line.LimitPercent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The client is under no ban, and GeoJS places it in a country.
|
// The client is under no ban, and GeoJS places it in a country.
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ func (rq *request) banForLimit(now time.Time, hit ratelimit.Hit, status int) {
|
|||||||
case ratelimit.KindBytes:
|
case ratelimit.KindBytes:
|
||||||
rq.line.LimitHit = hit.Window + "_bytes" // as counts names the byte totals
|
rq.line.LimitHit = hit.Window + "_bytes" // as counts names the byte totals
|
||||||
case ratelimit.KindRefusals:
|
case ratelimit.KindRefusals:
|
||||||
rq.line.LimitHit = requestlog.LimitHitMinuteRefusals
|
rq.line.LimitHit = requestlog.LimitHitErrorBurst
|
||||||
default:
|
default:
|
||||||
rq.line.LimitHit = hit.Window
|
rq.line.LimitHit = hit.Window
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,16 +79,14 @@ func TestEachBiasedThresholdLowersTheRateLimits(t *testing.T) {
|
|||||||
{http.StatusForbidden, requestlog.ActionClientIsRateLimited},
|
{http.StatusForbidden, requestlog.ActionClientIsRateLimited},
|
||||||
} {
|
} {
|
||||||
line := s.get(tc.from, sent.status, sent.action)
|
line := s.get(tc.from, sent.status, sent.action)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
"50 from "+tc.setting)
|
"50 from "+tc.setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fromKP, which no setting lists, has the whole limit.
|
// fromKP, which no setting lists, has the whole limit.
|
||||||
for range 3 {
|
for range 3 {
|
||||||
line := s.get(fromKP, http.StatusOK, requestlog.ActionForward)
|
line := s.get(fromKP, http.StatusOK, requestlog.ActionForward)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
none)
|
none)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -121,8 +119,7 @@ func TestEachBiasedThresholdLowersTheByteLimits(t *testing.T) {
|
|||||||
t.Errorf("log line has limit_hit %q, want %s", line.LimitHit, minuteBytes)
|
t.Errorf("log line has limit_hit %q, want %s", line.LimitHit, minuteBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
"50 from "+tc.setting)
|
"50 from "+tc.setting)
|
||||||
|
|
||||||
// fromKP, which no setting lists, has the whole limit.
|
// fromKP, which no setting lists, has the whole limit.
|
||||||
@@ -131,8 +128,7 @@ func TestEachBiasedThresholdLowersTheByteLimits(t *testing.T) {
|
|||||||
t.Errorf("log line for %s has limit_hit %q, want none", fromKP, line.LimitHit)
|
t.Errorf("log line for %s has limit_hit %q, want none", fromKP, line.LimitHit)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting, none)
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting, none)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,11 +177,9 @@ func TestBytesPercentSettingsTakeThePlaceOfTheOthersForByteLimits(t *testing.T)
|
|||||||
t.Errorf("log line has limit_hit %q, want %q", line.LimitHit, tc.limitHit)
|
t.Errorf("log line has limit_hit %q, want %q", line.LimitHit, tc.limitHit)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.limitPercent)
|
tc.limitPercent)
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
tc.bytesPercent)
|
tc.bytesPercent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -199,10 +193,10 @@ func TestZeroPercentIsAZeroAllowance(t *testing.T) {
|
|||||||
// The first request breaks the limit, and bans the client; the log line
|
// The first request breaks the limit, and bans the client; the log line
|
||||||
// gives the 0.
|
// gives the 0.
|
||||||
line := s.get(unplaced, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
line := s.get(unplaced, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
||||||
if line.fields["rate_limit_percent"] != float64(0) ||
|
if line.fields["limit_percent"] != float64(0) ||
|
||||||
line.fields["rate_limit_percent_setting"] != unknownLimitPercent {
|
line.fields["limit_percent_setting"] != unknownLimitPercent {
|
||||||
t.Errorf("log line has rate_limit_percent %v from %v, want 0 from %s",
|
t.Errorf("log line has limit_percent %v from %v, want 0 from %s",
|
||||||
line.fields["rate_limit_percent"], line.fields["rate_limit_percent_setting"],
|
line.fields["limit_percent"], line.fields["limit_percent_setting"],
|
||||||
unknownLimitPercent)
|
unknownLimitPercent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +210,7 @@ func TestLowestPercentageApplies(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
env map[string]string
|
env map[string]string
|
||||||
from string
|
from string
|
||||||
// want is the log line's rate_limit_percent, as percentText gives it.
|
// want is the log line's limit_percent, as percentText gives it.
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -257,8 +251,7 @@ func TestLowestPercentageApplies(t *testing.T) {
|
|||||||
s.get(tc.from, http.StatusOK, requestlog.ActionForward)
|
s.get(tc.from, http.StatusOK, requestlog.ActionForward)
|
||||||
|
|
||||||
line := s.get(tc.from, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
line := s.get(tc.from, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.want)
|
tc.want)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -301,8 +294,7 @@ func TestClientWithoutAnAnswerInTimeHasTheUnknownLimitPercent(t *testing.T) {
|
|||||||
|
|
||||||
line := out.requestLine(t)
|
line := out.requestLine(t)
|
||||||
wantLine(t, line, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
wantLine(t, line, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
"0 from "+unknownLimitPercent)
|
"0 from "+unknownLimitPercent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/config"
|
"sneak.berlin/go/smallwebwaf/internal/config"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
||||||
|
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// coreRuleSet inspects the request with the Core Rule Set, unless
|
// coreRuleSet inspects the request with the Core Rule Set, unless
|
||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
// pathExempt decides, and notes the rules it matched and its score in the
|
// pathExempt decides, and notes the rules it matched and its score in the
|
||||||
// log line, and the rules in the metrics. A score at or over
|
// log line, and the rules in the metrics. A score at or over
|
||||||
// SWW_WAF_ANOMALY_THRESHOLD is a match: it adds the tag exploitsignature,
|
// SWW_WAF_ANOMALY_THRESHOLD is a match: it adds the tag exploitsignature,
|
||||||
// raises the core_rule_set_match alert, and in block mode refuses the request with 403,
|
// raises the waf_block alert, and in block mode refuses the request with 403,
|
||||||
// which is an offence its client's history counts. Its figures are the score
|
// which is an offence its client's history counts. Its figures are the score
|
||||||
// and the threshold.
|
// and the threshold.
|
||||||
type coreRuleSet struct{}
|
type coreRuleSet struct{}
|
||||||
@@ -38,12 +38,12 @@ func (coreRuleSet) check(_ context.Context, rq *request, _ time.Time) *verdict {
|
|||||||
result, read, _ := rq.h.coreRuleSet.Inspect(rq.in, rq.client, rq.in.Body)
|
result, read, _ := rq.h.coreRuleSet.Inspect(rq.in, rq.client, rq.in.Body)
|
||||||
rq.requestBytes = int64(len(read))
|
rq.requestBytes = int64(len(read))
|
||||||
|
|
||||||
rq.line.DurationCoreRuleSetMS = new(requestlog.Milliseconds(time.Since(start)))
|
rq.line.DurationWAF = new(requestlog.Milliseconds(time.Since(start)))
|
||||||
rq.line.CoreRuleSetRuleIDs = result.RuleIDs
|
rq.line.WAFRuleIDs = result.RuleIDs
|
||||||
rq.line.CoreRuleSetScore = &result.Score
|
rq.line.WAFScore = &result.Score
|
||||||
|
|
||||||
for _, id := range result.RuleIDs {
|
for _, id := range result.RuleIDs {
|
||||||
rq.h.metrics.CoreRuleSetMatched(cfg.WAFMode, id)
|
rq.h.metrics.WAFMatched(cfg.WAFMode, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
threshold := cfg.WAFAnomalyThreshold
|
threshold := cfg.WAFAnomalyThreshold
|
||||||
@@ -52,26 +52,26 @@ func (coreRuleSet) check(_ context.Context, rq *request, _ time.Time) *verdict {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rq.addTag(config.ExploitSignatureTag)
|
rq.addTag(config.ExploitSignatureTag)
|
||||||
rq.alertCoreRuleSetMatch(result)
|
rq.alertWAFBlock(result)
|
||||||
|
|
||||||
if cfg.WAFMode == config.WAFModeDetect {
|
if cfg.WAFMode == config.WAFModeDetect {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rq.blockedByCoreRuleSet = true
|
rq.wafBlocked = true
|
||||||
|
|
||||||
return &verdict{
|
return &verdict{
|
||||||
action: requestlog.ActionBlockedByCoreRuleSet,
|
action: requestlog.ActionWAFBlocked,
|
||||||
figures: map[string]any{figureScore: result.Score, "threshold": threshold},
|
figures: map[string]any{figureScore: result.Score, "threshold": threshold},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// alertCoreRuleSetMatch raises the core_rule_set_match alert for the request,
|
// alertWAFBlock raises the waf_block alert for the request, which the Core
|
||||||
// which the Core Rule Set scored at result, at or over SWW_WAF_ANOMALY_THRESHOLD. Its
|
// Rule Set scored at result, at or over SWW_WAF_ANOMALY_THRESHOLD. Its
|
||||||
// detail gives the rule ids, the score, the method and the path with the
|
// detail gives the rule ids, the score, the method and the path with the
|
||||||
// query, and, for a request that is not refused for it, the mode: detect,
|
// query, and, for a request that is not refused for it, the mode: detect,
|
||||||
// or observe in observe mode.
|
// or observe in observe mode.
|
||||||
func (rq *request) alertCoreRuleSetMatch(result coreruleset.Result) {
|
func (rq *request) alertWAFBlock(result waf.Result) {
|
||||||
detail := map[string]any{
|
detail := map[string]any{
|
||||||
"rule_ids": result.RuleIDs,
|
"rule_ids": result.RuleIDs,
|
||||||
"score": result.Score,
|
"score": result.Score,
|
||||||
@@ -87,7 +87,7 @@ func (rq *request) alertCoreRuleSetMatch(result coreruleset.Result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rq.h.alerts.Raise(alerts.Alert{
|
rq.h.alerts.Raise(alerts.Alert{
|
||||||
Event: alerts.EventCoreRuleSetMatch,
|
Event: alerts.EventWAFBlock,
|
||||||
Host: rq.site,
|
Host: rq.site,
|
||||||
Client: rq.client,
|
Client: rq.client,
|
||||||
Netblock: rq.h.clientGroup(rq.client),
|
Netblock: rq.h.clientGroup(rq.client),
|
||||||
|
|||||||
@@ -40,30 +40,24 @@ const (
|
|||||||
// SWW_WAF_ANOMALY_THRESHOLD.
|
// SWW_WAF_ANOMALY_THRESHOLD.
|
||||||
const sqlInjection = "/?id=1'%20OR%20'1'='1"
|
const sqlInjection = "/?id=1'%20OR%20'1'='1"
|
||||||
|
|
||||||
// wantCoreRuleSet checks the request log line's core_rule_set_rule_ids and
|
// wantWAF checks the request log line's waf_rule_ids and waf_score, and
|
||||||
// core_rule_set_score, and that it has duration_core_rule_set_ms, or with no
|
// that it has duration_waf, or with no score, that it has none of the
|
||||||
// score, that it has none of the three: the Core Rule Set did not inspect the
|
// three: the Core Rule Set did not inspect the request.
|
||||||
// request.
|
func wantWAF(t *testing.T, line logLine, score *int, ruleIDs ...int) {
|
||||||
func wantCoreRuleSet(t *testing.T, line logLine, score *int, ruleIDs ...int) {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
if !slices.Equal(line.CoreRuleSetRuleIDs, ruleIDs) {
|
if !slices.Equal(line.WAFRuleIDs, ruleIDs) {
|
||||||
t.Errorf("log line has core_rule_set_rule_ids %v, want %v",
|
t.Errorf("log line has waf_rule_ids %v, want %v", line.WAFRuleIDs, ruleIDs)
|
||||||
line.CoreRuleSetRuleIDs, ruleIDs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case score == nil &&
|
case score == nil && (line.WAFScore != nil || line.DurationWAF != nil):
|
||||||
(line.CoreRuleSetScore != nil || line.DurationCoreRuleSetMS != nil):
|
t.Errorf("log line has waf_score %v and duration_waf %v, want neither",
|
||||||
t.Errorf("log line has core_rule_set_score %v and "+
|
line.fields["waf_score"], line.fields["duration_waf"])
|
||||||
"duration_core_rule_set_ms %v, want neither",
|
case score != nil && (line.WAFScore == nil || *line.WAFScore != *score):
|
||||||
line.fields["core_rule_set_score"], line.fields["duration_core_rule_set_ms"])
|
t.Errorf("log line has waf_score %v, want %d", line.fields["waf_score"], *score)
|
||||||
case score != nil &&
|
case score != nil && line.DurationWAF == nil:
|
||||||
(line.CoreRuleSetScore == nil || *line.CoreRuleSetScore != *score):
|
t.Error("log line has no duration_waf")
|
||||||
t.Errorf("log line has core_rule_set_score %v, want %d",
|
|
||||||
line.fields["core_rule_set_score"], *score)
|
|
||||||
case score != nil && line.DurationCoreRuleSetMS == nil:
|
|
||||||
t.Error("log line has no duration_core_rule_set_ms")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +70,7 @@ func TestCoreRuleSetMatchAddsTheExploitSignatureTag(t *testing.T) {
|
|||||||
status int
|
status int
|
||||||
action string
|
action string
|
||||||
}{
|
}{
|
||||||
{block, block, http.StatusForbidden, requestlog.ActionBlockedByCoreRuleSet},
|
{block, block, http.StatusForbidden, requestlog.ActionWAFBlocked},
|
||||||
{detect, detect, http.StatusOK, requestlog.ActionForward},
|
{detect, detect, http.StatusOK, requestlog.ActionForward},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@@ -139,14 +133,14 @@ func TestCoreRuleSetRefusesAttacksInBlockModeAndOnlyLogsThemInDetectMode(t *test
|
|||||||
mode, action string
|
mode, action string
|
||||||
status int
|
status int
|
||||||
}{
|
}{
|
||||||
{block, requestlog.ActionBlockedByCoreRuleSet, http.StatusForbidden},
|
{block, requestlog.ActionWAFBlocked, http.StatusForbidden},
|
||||||
{detect, requestlog.ActionForward, http.StatusOK},
|
{detect, requestlog.ActionForward, http.StatusOK},
|
||||||
} {
|
} {
|
||||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: tc.mode})
|
s, _, _ := startWithClock(t, "", map[string]string{wafMode: tc.mode})
|
||||||
|
|
||||||
line := s.requestWithHeader(client, attack.path, attack.header,
|
line := s.requestWithHeader(client, attack.path, attack.header,
|
||||||
tc.status, tc.action)
|
tc.status, tc.action)
|
||||||
wantCoreRuleSet(t, line, &attack.score, attack.ruleIDs...)
|
wantWAF(t, line, &attack.score, attack.ruleIDs...)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -158,7 +152,7 @@ func TestCoreRuleSetRefusalNamesItsHeuristicScoreAndThreshold(t *testing.T) {
|
|||||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
||||||
|
|
||||||
line := s.request(client, sqlInjection, http.StatusForbidden,
|
line := s.request(client, sqlInjection, http.StatusForbidden,
|
||||||
requestlog.ActionBlockedByCoreRuleSet)
|
requestlog.ActionWAFBlocked)
|
||||||
wantHeuristic(t, line, "core_rule_set", `{"score": 5, "threshold": 5}`)
|
wantHeuristic(t, line, "core_rule_set", `{"score": 5, "threshold": 5}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +163,7 @@ func TestOrdinaryRequestIsInspectedAndPassed(t *testing.T) {
|
|||||||
|
|
||||||
line := s.request(client, "/owner/repo/src/branch/main/README.md?display=source",
|
line := s.request(client, "/owner/repo/src/branch/main/README.md?display=source",
|
||||||
http.StatusOK, requestlog.ActionForward)
|
http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, new(0))
|
wantWAF(t, line, new(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoreRuleSetIsNotRunWhenOffOrForAnExemptClientPathOrRuleFileRefusal(
|
func TestCoreRuleSetIsNotRunWhenOffOrForAnExemptClientPathOrRuleFileRefusal(
|
||||||
@@ -189,26 +183,26 @@ func TestCoreRuleSetIsNotRunWhenOffOrForAnExemptClientPathOrRuleFileRefusal(
|
|||||||
// A client in SWW_ALLOW_NETS, and a path SWW_WAF_EXEMPT_PATHS
|
// A client in SWW_ALLOW_NETS, and a path SWW_WAF_EXEMPT_PATHS
|
||||||
// exempts, are not inspected.
|
// exempts, are not inspected.
|
||||||
line := s.request(allowed, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
line := s.request(allowed, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, nil)
|
wantWAF(t, line, nil)
|
||||||
line = s.request(client, "/api/v1/repos?id=1'%20OR%20'1'='1", http.StatusOK,
|
line = s.request(client, "/api/v1/repos?id=1'%20OR%20'1'='1", http.StatusOK,
|
||||||
requestlog.ActionForward)
|
requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, nil)
|
wantWAF(t, line, nil)
|
||||||
|
|
||||||
// The prefix is matched as rate limit exempt paths are: a path that
|
// The prefix is matched as rate limit exempt paths are: a path that
|
||||||
// goes up and out of it is inspected.
|
// goes up and out of it is inspected.
|
||||||
line = s.request(client, "/api/../?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
line = s.request(client, "/api/../?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
||||||
requestlog.ActionBlockedByCoreRuleSet)
|
requestlog.ActionWAFBlocked)
|
||||||
wantCoreRuleSet(t, line, new(25), 930100, 930110, 942100)
|
wantWAF(t, line, new(25), 930100, 930110, 942100)
|
||||||
|
|
||||||
// A request a rule file refuses is not inspected.
|
// A request a rule file refuses is not inspected.
|
||||||
line = s.request(otherClient, "/blocked?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
line = s.request(otherClient, "/blocked?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
||||||
requestlog.ActionBlockedByBlockRule)
|
requestlog.ActionBlockedByBlockRule)
|
||||||
wantCoreRuleSet(t, line, nil)
|
wantWAF(t, line, nil)
|
||||||
|
|
||||||
// With SWW_WAF_MODE off, no request is.
|
// With SWW_WAF_MODE off, no request is.
|
||||||
s, _, _ = startWithClock(t, "", map[string]string{wafMode: off})
|
s, _, _ = startWithClock(t, "", map[string]string{wafMode: off})
|
||||||
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, nil)
|
wantWAF(t, line, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnomalyThreshold(t *testing.T) {
|
func TestAnomalyThreshold(t *testing.T) {
|
||||||
@@ -222,14 +216,13 @@ func TestAnomalyThreshold(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, new(5), 942100)
|
wantWAF(t, line, new(5), 942100)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, _, _ := startWithClock(t, "", map[string]string{
|
s, _, _ := startWithClock(t, "", map[string]string{
|
||||||
wafMode: block, wafAnomalyThreshold: "5",
|
wafMode: block, wafAnomalyThreshold: "5",
|
||||||
})
|
})
|
||||||
s.request(client, sqlInjection, http.StatusForbidden,
|
s.request(client, sqlInjection, http.StatusForbidden, requestlog.ActionWAFBlocked)
|
||||||
requestlog.ActionBlockedByCoreRuleSet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
||||||
@@ -272,7 +265,7 @@ func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
|||||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
||||||
line, _ := s.requestWithBody(request.method, client, request.path,
|
line, _ := s.requestWithBody(request.method, client, request.path,
|
||||||
request.header, body, http.StatusOK, requestlog.ActionForward)
|
request.header, body, http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, new(0))
|
wantWAF(t, line, new(0))
|
||||||
|
|
||||||
// A list given replaces the default.
|
// A list given replaces the default.
|
||||||
s, _, _ = startWithClock(t, "", map[string]string{
|
s, _, _ = startWithClock(t, "", map[string]string{
|
||||||
@@ -280,12 +273,12 @@ func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
|||||||
})
|
})
|
||||||
score := 5 * len(request.ruleIDs)
|
score := 5 * len(request.ruleIDs)
|
||||||
line, _ = s.requestWithBody(request.method, client, request.path,
|
line, _ = s.requestWithBody(request.method, client, request.path,
|
||||||
request.header, body, http.StatusForbidden, requestlog.ActionBlockedByCoreRuleSet)
|
request.header, body, http.StatusForbidden, requestlog.ActionWAFBlocked)
|
||||||
wantCoreRuleSet(t, line, &score, request.ruleIDs...)
|
wantWAF(t, line, &score, request.ruleIDs...)
|
||||||
|
|
||||||
// And switches off the rules it lists.
|
// And switches off the rules it lists.
|
||||||
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, new(0))
|
wantWAF(t, line, new(0))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,14 +294,14 @@ func TestAttackInAFormBodyIsRefusedOnlyWhileBodiesAreRead(t *testing.T) {
|
|||||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
||||||
line, _ := s.requestWithBody(http.MethodPost, client, "/", header, body,
|
line, _ := s.requestWithBody(http.MethodPost, client, "/", header, body,
|
||||||
http.StatusOK, requestlog.ActionForward)
|
http.StatusOK, requestlog.ActionForward)
|
||||||
wantCoreRuleSet(t, line, new(0))
|
wantWAF(t, line, new(0))
|
||||||
|
|
||||||
s, _, _ = startWithClock(t, "", map[string]string{
|
s, _, _ = startWithClock(t, "", map[string]string{
|
||||||
wafMode: block, wafBodyLimit: sizeLimitSetting,
|
wafMode: block, wafBodyLimit: sizeLimitSetting,
|
||||||
})
|
})
|
||||||
line, _ = s.requestWithBody(http.MethodPost, client, "/", header, body,
|
line, _ = s.requestWithBody(http.MethodPost, client, "/", header, body,
|
||||||
http.StatusForbidden, requestlog.ActionBlockedByCoreRuleSet)
|
http.StatusForbidden, requestlog.ActionWAFBlocked)
|
||||||
wantCoreRuleSet(t, line, new(5), 942100)
|
wantWAF(t, line, new(5), 942100)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBodiesReachTheAppAsSentWhileBodiesAreRead(t *testing.T) {
|
func TestBodiesReachTheAppAsSentWhileBodiesAreRead(t *testing.T) {
|
||||||
@@ -398,33 +391,32 @@ func TestCoreRuleSetRefusalIsAnOffenceAndCountsTowardTheErrorBurst(t *testing.T)
|
|||||||
})
|
})
|
||||||
|
|
||||||
for range 2 {
|
for range 2 {
|
||||||
s.request(client, sqlInjection, http.StatusForbidden,
|
s.request(client, sqlInjection, http.StatusForbidden, requestlog.ActionWAFBlocked)
|
||||||
requestlog.ActionBlockedByCoreRuleSet)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The third refusal in a minute breaks the error burst, and bans the
|
// The third refusal in a minute breaks the error burst, and bans the
|
||||||
// client.
|
// client.
|
||||||
line := s.request(client, sqlInjection, http.StatusForbidden,
|
line := s.request(client, sqlInjection, http.StatusForbidden,
|
||||||
requestlog.ActionBlockedByCoreRuleSet)
|
requestlog.ActionWAFBlocked)
|
||||||
if line.LimitHit != requestlog.LimitHitMinuteRefusals ||
|
if line.LimitHit != requestlog.LimitHitErrorBurst ||
|
||||||
line.Offence != requestlog.OffenceLimit {
|
line.Offence != requestlog.OffenceLimit {
|
||||||
t.Errorf("log line has limit_hit %q and offence %q, want minute_refusals and limit",
|
t.Errorf("log line has limit_hit %q and offence %q, want error_burst and limit",
|
||||||
line.LimitHit, line.Offence)
|
line.LimitHit, line.Offence)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.get(client, http.StatusForbidden, requestlog.ActionTemporarilyBanned)
|
s.get(client, http.StatusForbidden, requestlog.ActionTemporarilyBanned)
|
||||||
|
|
||||||
want := ratelimit.Offences{Limit: 1, BlockedByCoreRuleSet: 3}
|
want := ratelimit.Offences{Limit: 1, WAFBlocked: 3}
|
||||||
if offences := historyOf(t, server, client).Offences; offences != want {
|
if offences := historyOf(t, server, client).Offences; offences != want {
|
||||||
t.Errorf("history counts the offences %+v, want %+v", offences, want)
|
t.Errorf("history counts the offences %+v, want %+v", offences, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics := s.scrape()
|
metrics := s.scrape()
|
||||||
wantMetric(t, metrics,
|
wantMetric(t, metrics,
|
||||||
`sww_core_rule_set_matches_total{instance="app",mode="block",rule_id="942100"}`, 3)
|
`sww_waf_matches_total{instance="app",mode="block",rule_id="942100"}`, 3)
|
||||||
wantMetric(t, metrics,
|
wantMetric(t, metrics,
|
||||||
`sww_offences_total{instance="app",kind="blocked_by_core_rule_set"}`, 3)
|
`sww_offences_total{instance="app",kind="waf_blocked"}`, 3)
|
||||||
wantMetric(t, metrics, `sww_requests_total{action="blocked_by_core_rule_set",`+
|
wantMetric(t, metrics, `sww_requests_total{action="waf_blocked",`+
|
||||||
`instance="app",status_class="4xx"}`, 3)
|
`instance="app",status_class="4xx"}`, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,9 +440,9 @@ func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(t *testing.T
|
|||||||
|
|
||||||
metrics := s.scrape()
|
metrics := s.scrape()
|
||||||
wantMetric(t, metrics,
|
wantMetric(t, metrics,
|
||||||
`sww_core_rule_set_matches_total{instance="app",mode="detect",rule_id="942100"}`, 3)
|
`sww_waf_matches_total{instance="app",mode="detect",rule_id="942100"}`, 3)
|
||||||
wantNoSeries(t, metrics,
|
wantNoSeries(t, metrics,
|
||||||
`sww_offences_total{instance="app",kind="blocked_by_core_rule_set"}`)
|
`sww_offences_total{instance="app",kind="waf_blocked"}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestObserveModeLogsWhatTheCoreRuleSetWouldDo(t *testing.T) {
|
func TestObserveModeLogsWhatTheCoreRuleSetWouldDo(t *testing.T) {
|
||||||
@@ -459,17 +451,17 @@ func TestObserveModeLogsWhatTheCoreRuleSetWouldDo(t *testing.T) {
|
|||||||
s, _, server := startWithClock(t, "", map[string]string{wafMode: block, mode: observe})
|
s, _, server := startWithClock(t, "", map[string]string{wafMode: block, mode: observe})
|
||||||
|
|
||||||
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||||
wantWouldAction(t, line, requestlog.ActionBlockedByCoreRuleSet)
|
wantWouldAction(t, line, requestlog.ActionWAFBlocked)
|
||||||
wantCoreRuleSet(t, line, new(5), 942100)
|
wantWAF(t, line, new(5), 942100)
|
||||||
|
|
||||||
// It is an offence as in enforce mode.
|
// It is an offence as in enforce mode.
|
||||||
want := ratelimit.Offences{BlockedByCoreRuleSet: 1}
|
want := ratelimit.Offences{WAFBlocked: 1}
|
||||||
if offences := historyOf(t, server, client).Offences; offences != want {
|
if offences := historyOf(t, server, client).Offences; offences != want {
|
||||||
t.Errorf("history counts the offences %+v, want %+v", offences, want)
|
t.Errorf("history counts the offences %+v, want %+v", offences, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoreRuleSetMatchRaisesTheCoreRuleSetMatchAlert(t *testing.T) {
|
func TestCoreRuleSetMatchRaisesTheWAFBlockAlert(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
@@ -483,7 +475,7 @@ func TestCoreRuleSetMatchRaisesTheCoreRuleSetMatchAlert(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"block", map[string]string{wafMode: block},
|
"block", map[string]string{wafMode: block},
|
||||||
http.StatusForbidden, requestlog.ActionBlockedByCoreRuleSet, "",
|
http.StatusForbidden, requestlog.ActionWAFBlocked, "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"detect", map[string]string{wafMode: detect},
|
"detect", map[string]string{wafMode: detect},
|
||||||
@@ -518,7 +510,7 @@ func TestCoreRuleSetMatchRaisesTheCoreRuleSetMatchAlert(t *testing.T) {
|
|||||||
wantAlerts(t, queue, alerts.Alert{
|
wantAlerts(t, queue, alerts.Alert{
|
||||||
Instance: alertInstance,
|
Instance: alertInstance,
|
||||||
Time: clk.Now(),
|
Time: clk.Now(),
|
||||||
Event: alerts.EventCoreRuleSetMatch,
|
Event: alerts.EventWAFBlock,
|
||||||
Host: appHost,
|
Host: appHost,
|
||||||
Client: netip.MustParseAddr(client),
|
Client: netip.MustParseAddr(client),
|
||||||
Netblock: netip.MustParsePrefix(client + "/32"),
|
Netblock: netip.MustParsePrefix(client + "/32"),
|
||||||
|
|||||||
@@ -89,12 +89,12 @@ var (
|
|||||||
//
|
//
|
||||||
//nolint:tagliatelle // docs/request-log.md names the fields in snake_case
|
//nolint:tagliatelle // docs/request-log.md names the fields in snake_case
|
||||||
type Report struct {
|
type Report struct {
|
||||||
RequestID string `json:"request_id"`
|
RequestID string `json:"request_id"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
RequestBytes int64 `json:"request_bytes"`
|
RequestBytes int64 `json:"request_bytes"`
|
||||||
ResponseBytes int64 `json:"response_bytes"`
|
ResponseBytes int64 `json:"response_bytes"`
|
||||||
DurationTotalMS float64 `json:"duration_total_ms"`
|
DurationTotal float64 `json:"duration_total"`
|
||||||
DurationUpstreamTotalMS float64 `json:"duration_upstream_total_ms"`
|
DurationUpstreamTotal float64 `json:"duration_upstream_total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns the server `sww discriminator` runs. It answers
|
// New returns the server `sww discriminator` runs. It answers
|
||||||
@@ -208,7 +208,7 @@ func (h *handler) answerQuestion(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// The app never sees this prefix. discriminator's own endpoints are at its
|
// The app never sees this prefix. discriminator's own endpoints are at its
|
||||||
// own address, so this answers as a path with no endpoint does.
|
// own address, so this answers as a path with no endpoint does.
|
||||||
rq.line.Action = requestlog.ActionOwnEndpoint
|
rq.line.Action = requestlog.ActionAdmin
|
||||||
rq.out.Header().Set(DispositionHeader, DispositionDeny)
|
rq.out.Header().Set(DispositionHeader, DispositionDeny)
|
||||||
http.Error(rq.out, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
http.Error(rq.out, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ func readReport(w http.ResponseWriter, r *http.Request) (Report, error) {
|
|||||||
|
|
||||||
for _, name := range []string{
|
for _, name := range []string{
|
||||||
"request_id", "status", "request_bytes", "response_bytes",
|
"request_id", "status", "request_bytes", "response_bytes",
|
||||||
"duration_total_ms", "duration_upstream_total_ms",
|
"duration_total", "duration_upstream_total",
|
||||||
} {
|
} {
|
||||||
value, there := fields[name]
|
value, there := fields[name]
|
||||||
if !there || string(value) == "null" {
|
if !there || string(value) == "null" {
|
||||||
@@ -431,11 +431,11 @@ func (report *Report) checkRanges() error {
|
|||||||
return fmt.Errorf("%w: request_bytes", errReportValue)
|
return fmt.Errorf("%w: request_bytes", errReportValue)
|
||||||
case report.ResponseBytes < 0 || report.ResponseBytes > maxReportedBytes:
|
case report.ResponseBytes < 0 || report.ResponseBytes > maxReportedBytes:
|
||||||
return fmt.Errorf("%w: response_bytes", errReportValue)
|
return fmt.Errorf("%w: response_bytes", errReportValue)
|
||||||
case report.DurationTotalMS < 0 || report.DurationTotalMS > maxReportedMilliseconds:
|
case report.DurationTotal < 0 || report.DurationTotal > maxReportedMilliseconds:
|
||||||
return fmt.Errorf("%w: duration_total_ms", errReportValue)
|
return fmt.Errorf("%w: duration_total", errReportValue)
|
||||||
case report.DurationUpstreamTotalMS < 0 ||
|
case report.DurationUpstreamTotal < 0 ||
|
||||||
report.DurationUpstreamTotalMS > maxReportedMilliseconds:
|
report.DurationUpstreamTotal > maxReportedMilliseconds:
|
||||||
return fmt.Errorf("%w: duration_upstream_total_ms", errReportValue)
|
return fmt.Errorf("%w: duration_upstream_total", errReportValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -459,18 +459,18 @@ func (h *handler) finishWith(ctx context.Context, held *decision, report Report)
|
|||||||
rq.line.Status = report.Status
|
rq.line.Status = report.Status
|
||||||
rq.line.RequestBytes = report.RequestBytes
|
rq.line.RequestBytes = report.RequestBytes
|
||||||
rq.line.ResponseBytes = report.ResponseBytes
|
rq.line.ResponseBytes = report.ResponseBytes
|
||||||
rq.line.DurationTotalMS = report.DurationTotalMS
|
rq.line.DurationTotal = report.DurationTotal
|
||||||
|
|
||||||
if rq.allowed {
|
if rq.allowed {
|
||||||
rq.line.DurationUpstreamTotalMS = &report.DurationUpstreamTotalMS
|
rq.line.DurationUpstreamTotal = &report.DurationUpstreamTotal
|
||||||
|
|
||||||
rq.runBanningHeuristics(ctx, onReport())
|
rq.runBanningHeuristics(ctx, onReport())
|
||||||
rq.countAnomalies()
|
rq.countAnomalies()
|
||||||
rq.addToHistory()
|
rq.addToHistory()
|
||||||
|
|
||||||
rq.h.metrics.RequestReported(&rq.line,
|
rq.h.metrics.RequestReported(&rq.line,
|
||||||
time.Duration(report.DurationTotalMS*float64(time.Millisecond)),
|
time.Duration(report.DurationTotal*float64(time.Millisecond)),
|
||||||
time.Duration(report.DurationUpstreamTotalMS*float64(time.Millisecond)))
|
time.Duration(report.DurationUpstreamTotal*float64(time.Millisecond)))
|
||||||
}
|
}
|
||||||
|
|
||||||
rq.writeLine()
|
rq.writeLine()
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ const (
|
|||||||
reportStatus = "status"
|
reportStatus = "status"
|
||||||
reportRequestBytes = "request_bytes"
|
reportRequestBytes = "request_bytes"
|
||||||
reportResponseBytes = "response_bytes"
|
reportResponseBytes = "response_bytes"
|
||||||
reportDuration = "duration_total_ms"
|
reportDuration = "duration_total"
|
||||||
reportUpstreamDuration = "duration_upstream_total_ms"
|
reportUpstreamDuration = "duration_upstream_total"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Discriminator is a discriminator running for one test, on a clock set to midnight.
|
// Discriminator is a discriminator running for one test, on a clock set to midnight.
|
||||||
@@ -693,7 +693,7 @@ func TestQuestionUnderTheOwnPrefixIsDeniedWith404AfterTheChecks(t *testing.T) {
|
|||||||
wantDisposition(t, got, http.StatusNotFound, discriminator.DispositionDeny)
|
wantDisposition(t, got, http.StatusNotFound, discriminator.DispositionDeny)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantLine(t, s.out.requestLine(t), http.StatusNotFound, requestlog.ActionOwnEndpoint)
|
wantLine(t, s.out.requestLine(t), http.StatusNotFound, requestlog.ActionAdmin)
|
||||||
|
|
||||||
got := s.ask(otherClient, discriminator.MetricsPath)
|
got := s.ask(otherClient, discriminator.MetricsPath)
|
||||||
wantDisposition(t, got, http.StatusForbidden, discriminator.DispositionDeny)
|
wantDisposition(t, got, http.StatusForbidden, discriminator.DispositionDeny)
|
||||||
@@ -725,9 +725,9 @@ func TestObserveModeRefusalAnsweredAllowCountsForTheErrorBurst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lines := s.out.requestLines(t, 2)
|
lines := s.out.requestLines(t, 2)
|
||||||
if lines[0].LimitHit != "" || lines[1].LimitHit != requestlog.LimitHitMinuteRefusals {
|
if lines[0].LimitHit != "" || lines[1].LimitHit != requestlog.LimitHitErrorBurst {
|
||||||
t.Errorf("log lines have limit_hit %q and %q, want none and %q",
|
t.Errorf("log lines have limit_hit %q and %q, want none and %q",
|
||||||
lines[0].LimitHit, lines[1].LimitHit, requestlog.LimitHitMinuteRefusals)
|
lines[0].LimitHit, lines[1].LimitHit, requestlog.LimitHitErrorBurst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,9 +744,9 @@ func TestDeniedQuestionCountsForTheErrorBurst(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lines := s.out.requestLines(t, 2)
|
lines := s.out.requestLines(t, 2)
|
||||||
if lines[0].LimitHit != "" || lines[1].LimitHit != requestlog.LimitHitMinuteRefusals {
|
if lines[0].LimitHit != "" || lines[1].LimitHit != requestlog.LimitHitErrorBurst {
|
||||||
t.Errorf("log lines have limit_hit %q and %q, want none and %q",
|
t.Errorf("log lines have limit_hit %q and %q, want none and %q",
|
||||||
lines[0].LimitHit, lines[1].LimitHit, requestlog.LimitHitMinuteRefusals)
|
lines[0].LimitHit, lines[1].LimitHit, requestlog.LimitHitErrorBurst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,7 +901,7 @@ func TestDeniedRequestIsFinishedAtItsDecision(t *testing.T) {
|
|||||||
|
|
||||||
got := s.report(discriminator.Report{
|
got := s.report(discriminator.Report{
|
||||||
RequestID: denied.Header.Get(requestIDHeader), Status: http.StatusForbidden,
|
RequestID: denied.Header.Get(requestIDHeader), Status: http.StatusForbidden,
|
||||||
ResponseBytes: 1000, DurationTotalMS: 2,
|
ResponseBytes: 1000, DurationTotal: 2,
|
||||||
})
|
})
|
||||||
wantStatus(t, got, http.StatusNoContent)
|
wantStatus(t, got, http.StatusNoContent)
|
||||||
|
|
||||||
@@ -935,7 +935,7 @@ func TestMetricsCountAnAllowedRequestFromItsReport(t *testing.T) {
|
|||||||
got := s.report(discriminator.Report{
|
got := s.report(discriminator.Report{
|
||||||
RequestID: id, Status: http.StatusBadGateway,
|
RequestID: id, Status: http.StatusBadGateway,
|
||||||
RequestBytes: bodyBytes, ResponseBytes: answerBytes,
|
RequestBytes: bodyBytes, ResponseBytes: answerBytes,
|
||||||
DurationTotalMS: 5, DurationUpstreamTotalMS: 4,
|
DurationTotal: 5, DurationUpstreamTotal: 4,
|
||||||
})
|
})
|
||||||
wantStatus(t, got, http.StatusNoContent)
|
wantStatus(t, got, http.StatusNoContent)
|
||||||
|
|
||||||
@@ -951,8 +951,7 @@ func TestMetricsCountAnAllowedRequestFromItsReport(t *testing.T) {
|
|||||||
unscraped := startDiscriminator(t, "", map[string]string{metricsToken: token})
|
unscraped := startDiscriminator(t, "", map[string]string{metricsToken: token})
|
||||||
|
|
||||||
got = unscraped.report(discriminator.Report{
|
got = unscraped.report(discriminator.Report{
|
||||||
RequestID: unscraped.allowed(client), Status: http.StatusBadGateway,
|
RequestID: unscraped.allowed(client), Status: http.StatusBadGateway, DurationTotal: 5,
|
||||||
DurationTotalMS: 5,
|
|
||||||
})
|
})
|
||||||
wantStatus(t, got, http.StatusNoContent)
|
wantStatus(t, got, http.StatusNoContent)
|
||||||
wantMetric(t, unscraped.metrics(),
|
wantMetric(t, unscraped.metrics(),
|
||||||
@@ -1190,8 +1189,8 @@ func wantReportsFields(t *testing.T, line logLine) {
|
|||||||
if line.DiscriminatorLine != requestlog.DiscriminatorLineReport ||
|
if line.DiscriminatorLine != requestlog.DiscriminatorLineReport ||
|
||||||
line.Status != http.StatusCreated ||
|
line.Status != http.StatusCreated ||
|
||||||
line.RequestBytes != bodyBytes || line.ResponseBytes != answerBytes ||
|
line.RequestBytes != bodyBytes || line.ResponseBytes != answerBytes ||
|
||||||
line.DurationTotalMS != 12.5 || line.DurationUpstreamTotalMS == nil ||
|
line.DurationTotal != 12.5 || line.DurationUpstreamTotal == nil ||
|
||||||
*line.DurationUpstreamTotalMS != 10.25 {
|
*line.DurationUpstreamTotal != 10.25 {
|
||||||
t.Errorf("the report's line lacks the report's fields: %+v", line.Line)
|
t.Errorf("the report's line lacks the report's fields: %+v", line.Line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1206,8 +1205,8 @@ func wantSameDecision(t *testing.T, reported, decided logLine) {
|
|||||||
same.Status = decided.Status
|
same.Status = decided.Status
|
||||||
same.RequestBytes = decided.RequestBytes
|
same.RequestBytes = decided.RequestBytes
|
||||||
same.ResponseBytes = decided.ResponseBytes
|
same.ResponseBytes = decided.ResponseBytes
|
||||||
same.DurationTotalMS = decided.DurationTotalMS
|
same.DurationTotal = decided.DurationTotal
|
||||||
same.DurationUpstreamTotalMS = decided.DurationUpstreamTotalMS
|
same.DurationUpstreamTotal = decided.DurationUpstreamTotal
|
||||||
same.Counts.MinuteBytes = decided.Counts.MinuteBytes
|
same.Counts.MinuteBytes = decided.Counts.MinuteBytes
|
||||||
same.Counts.HourBytes = decided.Counts.HourBytes
|
same.Counts.HourBytes = decided.Counts.HourBytes
|
||||||
same.Counts.DayBytes = decided.Counts.DayBytes
|
same.Counts.DayBytes = decided.Counts.DayBytes
|
||||||
@@ -1225,7 +1224,7 @@ func wantDecisionsFields(t *testing.T, line logLine, id, query, accept string) {
|
|||||||
|
|
||||||
if line.DiscriminatorLine != requestlog.DiscriminatorLineDecision ||
|
if line.DiscriminatorLine != requestlog.DiscriminatorLineDecision ||
|
||||||
line.Status != http.StatusOK || line.ResponseBytes != 0 ||
|
line.Status != http.StatusOK || line.ResponseBytes != 0 ||
|
||||||
line.DurationUpstreamTotalMS != nil || line.DurationChecksMS == nil ||
|
line.DurationUpstreamTotal != nil || line.DurationChecks == nil ||
|
||||||
line.RequestID != id || line.Query != query ||
|
line.RequestID != id || line.Query != query ||
|
||||||
!line.HasAuthorization || !line.HasCookie ||
|
!line.HasAuthorization || !line.HasCookie ||
|
||||||
line.RequestHeaders["accept"] != accept || len(line.RuleIDs) != 1 ||
|
line.RequestHeaders["accept"] != accept || len(line.RuleIDs) != 1 ||
|
||||||
@@ -1261,7 +1260,7 @@ func TestReportWritesTheLastLineWithTheDecisionsAndTheReportsFields(t *testing.T
|
|||||||
got := s.report(discriminator.Report{
|
got := s.report(discriminator.Report{
|
||||||
RequestID: id, Status: http.StatusCreated,
|
RequestID: id, Status: http.StatusCreated,
|
||||||
RequestBytes: bodyBytes, ResponseBytes: answerBytes,
|
RequestBytes: bodyBytes, ResponseBytes: answerBytes,
|
||||||
DurationTotalMS: 12.5, DurationUpstreamTotalMS: 10.25,
|
DurationTotal: 12.5, DurationUpstreamTotal: 10.25,
|
||||||
})
|
})
|
||||||
wantStatus(t, got, http.StatusNoContent)
|
wantStatus(t, got, http.StatusNoContent)
|
||||||
|
|
||||||
@@ -1306,7 +1305,7 @@ func TestEveryDeniedRequestsReportGetsItsLastLine(t *testing.T) {
|
|||||||
0, requestlog.ActionClientDenied,
|
0, requestlog.ActionClientDenied,
|
||||||
},
|
},
|
||||||
{"own prefix", nil, discriminator.HealthPath, http.StatusNotFound,
|
{"own prefix", nil, discriminator.HealthPath, http.StatusNotFound,
|
||||||
requestlog.ActionOwnEndpoint},
|
requestlog.ActionAdmin},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@@ -1318,7 +1317,7 @@ func TestEveryDeniedRequestsReportGetsItsLastLine(t *testing.T) {
|
|||||||
do(t, req)
|
do(t, req)
|
||||||
|
|
||||||
got := s.report(discriminator.Report{
|
got := s.report(discriminator.Report{
|
||||||
RequestID: id, Status: tc.status, ResponseBytes: 8, DurationTotalMS: 3,
|
RequestID: id, Status: tc.status, ResponseBytes: 8, DurationTotal: 3,
|
||||||
})
|
})
|
||||||
wantStatus(t, got, http.StatusNoContent)
|
wantStatus(t, got, http.StatusNoContent)
|
||||||
|
|
||||||
@@ -1326,8 +1325,8 @@ func TestEveryDeniedRequestsReportGetsItsLastLine(t *testing.T) {
|
|||||||
wantLine(t, line, tc.status, tc.action)
|
wantLine(t, line, tc.status, tc.action)
|
||||||
|
|
||||||
if line.DiscriminatorLine != requestlog.DiscriminatorLineReport ||
|
if line.DiscriminatorLine != requestlog.DiscriminatorLineReport ||
|
||||||
line.RequestID != id || line.ResponseBytes != 8 || line.DurationTotalMS != 3 ||
|
line.RequestID != id || line.ResponseBytes != 8 || line.DurationTotal != 3 ||
|
||||||
line.DurationUpstreamTotalMS != nil {
|
line.DurationUpstreamTotal != nil {
|
||||||
t.Errorf("the report's line is %+v", line.Line)
|
t.Errorf("the report's line is %+v", line.Line)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1584,10 +1583,9 @@ func TestCoreRuleSetAlertNamesTheSite(t *testing.T) {
|
|||||||
wantDisposition(t, got, http.StatusForbidden, discriminator.DispositionDeny)
|
wantDisposition(t, got, http.StatusForbidden, discriminator.DispositionDeny)
|
||||||
|
|
||||||
waiting := s.queue.Snapshot().Waiting[alerts.DestinationWebhook]
|
waiting := s.queue.Snapshot().Waiting[alerts.DestinationWebhook]
|
||||||
if len(waiting) != 1 || waiting[0].Event != alerts.EventCoreRuleSetMatch ||
|
if len(waiting) != 1 || waiting[0].Event != alerts.EventWAFBlock ||
|
||||||
waiting[0].Host != siteA {
|
waiting[0].Host != siteA {
|
||||||
t.Errorf("alerts waiting are %+v, want a core_rule_set_match naming %s",
|
t.Errorf("alerts waiting are %+v, want a waf_block naming %s", waiting, siteA)
|
||||||
waiting, siteA)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ func TestMetricsCountTheTraffic(t *testing.T) {
|
|||||||
out.endedLines(t, 2)
|
out.endedLines(t, 2)
|
||||||
|
|
||||||
forward := `{action="forward",instance="app",status_class="2xx"}`
|
forward := `{action="forward",instance="app",status_class="2xx"}`
|
||||||
notFound := `{action="own_endpoint",instance="app",status_class="4xx"}`
|
notFound := `{action="admin",instance="app",status_class="4xx"}`
|
||||||
|
|
||||||
// The request for the metrics is itself under way.
|
// The request for the metrics is itself under way.
|
||||||
metrics := scrape(t, server.Addr)
|
metrics := scrape(t, server.Addr)
|
||||||
@@ -347,7 +347,7 @@ func TestMetricsCountGeoJSRequestsAndFailures(t *testing.T) {
|
|||||||
|
|
||||||
wantMetric(t, metrics, `sww_geojs_requests_total{instance="app"}`, 1)
|
wantMetric(t, metrics, `sww_geojs_requests_total{instance="app"}`, 1)
|
||||||
wantMetric(t, metrics, `sww_geojs_failures_total{instance="app"}`, 1)
|
wantMetric(t, metrics, `sww_geojs_failures_total{instance="app"}`, 1)
|
||||||
wantMetric(t, metrics, `sww_requests_without_geojs_answer_total{instance="app"}`, 1)
|
wantMetric(t, metrics, `sww_geojs_unanswered_total{instance="app"}`, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// keptAnswer returns GeoJS's answer that the client at addr is in
|
// keptAnswer returns GeoJS's answer that the client at addr is in
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ import (
|
|||||||
"sneak.berlin/go/smallwebwaf/internal/anomaly"
|
"sneak.berlin/go/smallwebwaf/internal/anomaly"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/bans"
|
"sneak.berlin/go/smallwebwaf/internal/bans"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/config"
|
"sneak.berlin/go/smallwebwaf/internal/config"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/lookup"
|
"sneak.berlin/go/smallwebwaf/internal/lookup"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/metrics"
|
"sneak.berlin/go/smallwebwaf/internal/metrics"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/ratelimit"
|
"sneak.berlin/go/smallwebwaf/internal/ratelimit"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/reputation"
|
"sneak.berlin/go/smallwebwaf/internal/reputation"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/routewatch"
|
"sneak.berlin/go/smallwebwaf/internal/routewatch"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/rules"
|
"sneak.berlin/go/smallwebwaf/internal/rules"
|
||||||
|
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// adminPrefix starts the path of each of discriminator's own endpoints. The app never
|
// adminPrefix starts the path of each of discriminator's own endpoints. The app never
|
||||||
@@ -65,7 +65,7 @@ type Params struct {
|
|||||||
LookupFile *lookup.File
|
LookupFile *lookup.File
|
||||||
// CoreRuleSet is what NewCoreRuleSet returns: what inspects requests
|
// CoreRuleSet is what NewCoreRuleSet returns: what inspects requests
|
||||||
// while SWW_WAF_MODE is not off, and nil while it is.
|
// while SWW_WAF_MODE is not off, and nil while it is.
|
||||||
CoreRuleSet *coreruleset.CoreRuleSet
|
CoreRuleSet *waf.CoreRuleSet
|
||||||
// Now tells the time by which requests are counted for the rate
|
// Now tells the time by which requests are counted for the rate
|
||||||
// limits, bans are made and run out, and GeoJS's answers are kept,
|
// limits, bans are made and run out, and GeoJS's answers are kept,
|
||||||
// normally time.Now in UTC, the time the state files give.
|
// normally time.Now in UTC, the time the state files give.
|
||||||
@@ -129,7 +129,7 @@ func newHandler(params Params) *handler {
|
|||||||
BytesPerHour: params.Config.BytesLimitPerHour,
|
BytesPerHour: params.Config.BytesLimitPerHour,
|
||||||
BytesPerDay: params.Config.BytesLimitPerDay,
|
BytesPerDay: params.Config.BytesLimitPerDay,
|
||||||
}, params.Config.MaxTrackedClients),
|
}, params.Config.MaxTrackedClients),
|
||||||
ledger: bans.New(bans.Params{
|
ledger: bans.New(bans.Rules{
|
||||||
LimitBanDuration: params.Config.LimitBanDuration,
|
LimitBanDuration: params.Config.LimitBanDuration,
|
||||||
LimitBanRepeatWindow: params.Config.LimitBanRepeatWindow,
|
LimitBanRepeatWindow: params.Config.LimitBanRepeatWindow,
|
||||||
MaxBanDuration: params.Config.MaxBanDuration,
|
MaxBanDuration: params.Config.MaxBanDuration,
|
||||||
@@ -224,15 +224,15 @@ func newReputation(
|
|||||||
// SWW_CORE_RULE_SET_EXCLUSIONS_FILE, or nil while SWW_WAF_MODE is off. It
|
// SWW_CORE_RULE_SET_EXCLUSIONS_FILE, or nil while SWW_WAF_MODE is off. It
|
||||||
// reads at most QuestionBodyMaxBytes less one byte: a question's body of
|
// reads at most QuestionBodyMaxBytes less one byte: a question's body of
|
||||||
// QuestionBodyMaxBytes may be cut short, and the Core Rule Set does not read a
|
// QuestionBodyMaxBytes may be cut short, and the Core Rule Set does not read a
|
||||||
// JSON or XML body over its limit. An exclusions file that coreruleset.New refuses is
|
// JSON or XML body over its limit. An exclusions file that waf.New refuses is
|
||||||
// an error in every mode. While the mode is off, a set file is loaded with the
|
// an error in every mode. While the mode is off, a set file is loaded with the
|
||||||
// Core Rule Set only to check it.
|
// Core Rule Set only to check it.
|
||||||
func NewCoreRuleSet(cfg *config.Config) (*coreruleset.CoreRuleSet, error) {
|
func NewCoreRuleSet(cfg *config.Config) (*waf.CoreRuleSet, error) {
|
||||||
if cfg.WAFMode == config.WAFModeOff && cfg.CoreRuleSetExclusionsFile == "" {
|
if cfg.WAFMode == config.WAFModeOff && cfg.CoreRuleSetExclusionsFile == "" {
|
||||||
return nil, nil //nolint:nilnil // off is no Core Rule Set, and no error
|
return nil, nil //nolint:nilnil // off is no Core Rule Set, and no error
|
||||||
}
|
}
|
||||||
|
|
||||||
coreRuleSet, err := coreruleset.New(coreruleset.Params{
|
coreRuleSet, err := waf.New(waf.Params{
|
||||||
ParanoiaLevel: cfg.WAFParanoiaLevel, DisabledRules: cfg.WAFDisabledRules,
|
ParanoiaLevel: cfg.WAFParanoiaLevel, DisabledRules: cfg.WAFDisabledRules,
|
||||||
BodyLimit: min(cfg.WAFBodyLimit, QuestionBodyMaxBytes-1),
|
BodyLimit: min(cfg.WAFBodyLimit, QuestionBodyMaxBytes-1),
|
||||||
ExclusionsFile: cfg.CoreRuleSetExclusionsFile,
|
ExclusionsFile: cfg.CoreRuleSetExclusionsFile,
|
||||||
@@ -266,7 +266,7 @@ type handler struct {
|
|||||||
abuseIPDB *reputation.AbuseIPDB
|
abuseIPDB *reputation.AbuseIPDB
|
||||||
routeWatch *routewatch.Client
|
routeWatch *routewatch.Client
|
||||||
rules *rules.Files
|
rules *rules.Files
|
||||||
coreRuleSet *coreruleset.CoreRuleSet
|
coreRuleSet *waf.CoreRuleSet
|
||||||
alerts *alerts.Queue
|
alerts *alerts.Queue
|
||||||
// awaitingReport holds the decision on each answered question by its id
|
// awaitingReport holds the decision on each answered question by its id
|
||||||
// until its report comes, and nil for a question still being handled.
|
// until its report comes, and nil for a question still being handled.
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ func (rateLimits) check(_ context.Context, rq *request, now time.Time) *verdict
|
|||||||
}
|
}
|
||||||
|
|
||||||
rq.limitPercent, rq.bytesPercent = rq.limitPercentages()
|
rq.limitPercent, rq.bytesPercent = rq.limitPercentages()
|
||||||
rq.line.RateLimitPercent, rq.line.RateLimitPercentSetting = rq.limitPercent.logged()
|
rq.line.LimitPercent, rq.line.LimitPercentSetting = rq.limitPercent.logged()
|
||||||
rq.line.BytesLimitPercent, rq.line.BytesLimitPercentSetting = rq.bytesPercent.logged()
|
rq.line.BytesPercent, rq.line.BytesPercentSetting = rq.bytesPercent.logged()
|
||||||
|
|
||||||
counts, hit, over := rq.h.limiter.Count(rq.h.clientGroup(rq.client), now,
|
counts, hit, over := rq.h.limiter.Count(rq.h.clientGroup(rq.client), now,
|
||||||
rq.limitPercent.percent)
|
rq.limitPercent.percent)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (refusalLimit) check(_ context.Context, rq *request, now time.Time) *verdic
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !rq.attack && !rq.blockedByBlockRule && !rq.blockedByCoreRuleSet {
|
if !rq.attack && !rq.blockedByBlockRule && !rq.wafBlocked {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ func (refusalLimit) check(_ context.Context, rq *request, now time.Time) *verdic
|
|||||||
status := rq.out.status
|
status := rq.out.status
|
||||||
|
|
||||||
switch rq.line.WouldAction {
|
switch rq.line.WouldAction {
|
||||||
case requestlog.ActionBlockedByBlockRule, requestlog.ActionBlockedByCoreRuleSet:
|
case requestlog.ActionBlockedByBlockRule, requestlog.ActionWAFBlocked:
|
||||||
status = http.StatusForbidden
|
status = http.StatusForbidden
|
||||||
case requestlog.ActionTemporarilyBanned, requestlog.ActionPermanentlyBanned:
|
case requestlog.ActionTemporarilyBanned, requestlog.ActionPermanentlyBanned:
|
||||||
status = cfg.BanResponse
|
status = cfg.BanResponse
|
||||||
|
|||||||
@@ -107,9 +107,9 @@ func TestErrorBurstBreaksAtOneOverTheThreshold(t *testing.T) {
|
|||||||
// The fourth is answered as the others were, breaks the error
|
// The fourth is answered as the others were, breaks the error
|
||||||
// burst, and bans the client.
|
// burst, and bans the client.
|
||||||
line := tc.refusals[3].send(s, client)
|
line := tc.refusals[3].send(s, client)
|
||||||
if line.LimitHit != requestlog.LimitHitMinuteRefusals ||
|
if line.LimitHit != requestlog.LimitHitErrorBurst ||
|
||||||
line.Offence != requestlog.OffenceLimit {
|
line.Offence != requestlog.OffenceLimit {
|
||||||
t.Errorf("log line has limit_hit %q and offence %q, want minute_refusals "+
|
t.Errorf("log line has limit_hit %q and offence %q, want error_burst "+
|
||||||
"and limit", line.LimitHit, line.Offence)
|
"and limit", line.LimitHit, line.Offence)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,8 +277,7 @@ func TestErrorBurstOffOrAtItsDefault(t *testing.T) {
|
|||||||
line = blockRule.send(s, client)
|
line = blockRule.send(s, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
broken := line.LimitHit == requestlog.LimitHitMinuteRefusals
|
if broken := line.LimitHit == requestlog.LimitHitErrorBurst; broken != tc.broken {
|
||||||
if broken != tc.broken {
|
|
||||||
t.Errorf("the 31st refusal broke the error burst: %t, want %t",
|
t.Errorf("the 31st refusal broke the error burst: %t, want %t",
|
||||||
broken, tc.broken)
|
broken, tc.broken)
|
||||||
}
|
}
|
||||||
@@ -307,8 +306,8 @@ func TestErrorBurstCountsEachClientTheChecksApplyTo(t *testing.T) {
|
|||||||
blockRule.send(s, exempt)
|
blockRule.send(s, exempt)
|
||||||
|
|
||||||
line := blockRule.send(s, exempt)
|
line := blockRule.send(s, exempt)
|
||||||
if line.LimitHit != requestlog.LimitHitMinuteRefusals {
|
if line.LimitHit != requestlog.LimitHitErrorBurst {
|
||||||
t.Errorf("log line has limit_hit %q, want minute_refusals", line.LimitHit)
|
t.Errorf("log line has limit_hit %q, want error_burst", line.LimitHit)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.get(exempt, http.StatusForbidden, requestlog.ActionTemporarilyBanned)
|
s.get(exempt, http.StatusForbidden, requestlog.ActionTemporarilyBanned)
|
||||||
@@ -368,8 +367,8 @@ func TestObserveModeLogsAndAlertsTheErrorBurst(t *testing.T) {
|
|||||||
line := s.request(client, blockedPath, http.StatusOK, requestlog.ActionForward)
|
line := s.request(client, blockedPath, http.StatusOK, requestlog.ActionForward)
|
||||||
wantWouldAction(t, line, requestlog.ActionBlockedByBlockRule)
|
wantWouldAction(t, line, requestlog.ActionBlockedByBlockRule)
|
||||||
|
|
||||||
if line.LimitHit != requestlog.LimitHitMinuteRefusals || line.BanExpires != "" {
|
if line.LimitHit != requestlog.LimitHitErrorBurst || line.BanExpires != "" {
|
||||||
t.Errorf("log line has limit_hit %q and ban_expires %q, want minute_refusals "+
|
t.Errorf("log line has limit_hit %q and ban_expires %q, want error_burst "+
|
||||||
"and none", line.LimitHit, line.BanExpires)
|
"and none", line.LimitHit, line.BanExpires)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func TestEachBlocklistActionForAListedAddressAndAListedNetblock(t *testing.T) {
|
|||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
action string
|
action string
|
||||||
// statuses and actions are those of a listed client's three
|
// statuses and actions are those of a listed client's three
|
||||||
// requests, and percent their rate_limit_percent, as percentText gives it.
|
// requests, and percent their limit_percent, as percentText gives it.
|
||||||
statuses []int
|
statuses []int
|
||||||
actions []string
|
actions []string
|
||||||
percent string
|
percent string
|
||||||
@@ -90,8 +90,8 @@ func TestEachBlocklistActionForAListedAddressAndAListedNetblock(t *testing.T) {
|
|||||||
for i := range 3 {
|
for i := range 3 {
|
||||||
line := s.get(from, tc.statuses[i], tc.actions[i])
|
line := s.get(from, tc.statuses[i], tc.actions[i])
|
||||||
wantReputation(t, line, dropURL)
|
wantReputation(t, line, dropURL)
|
||||||
wantPercent(t, "rate_limit_percent", line.RateLimitPercent,
|
wantPercent(t, "limit_percent", line.LimitPercent,
|
||||||
line.RateLimitPercentSetting, tc.percent)
|
line.LimitPercentSetting, tc.percent)
|
||||||
|
|
||||||
// A request refused for the list is not counted.
|
// A request refused for the list is not counted.
|
||||||
counted := line.fields["counts"] != nil
|
counted := line.fields["counts"] != nil
|
||||||
@@ -106,8 +106,7 @@ func TestEachBlocklistActionForAListedAddressAndAListedNetblock(t *testing.T) {
|
|||||||
for range 3 {
|
for range 3 {
|
||||||
line := s.get(unplaced, http.StatusOK, forward)
|
line := s.get(unplaced, http.StatusOK, forward)
|
||||||
wantReputation(t, line)
|
wantReputation(t, line)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
none)
|
none)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +207,7 @@ func TestBlocklistLimitTakesPartInTheLowestPercentageOfEveryLimit(t *testing.T)
|
|||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
action, asnPercent string
|
action, asnPercent string
|
||||||
// want is the upload's rate_limit_percent and bytes_limit_percent, as
|
// want is the upload's limit_percent and bytes_percent, as
|
||||||
// percentText gives them, and limitHit its limit_hit.
|
// percentText gives them, and limitHit its limit_hit.
|
||||||
want, limitHit string
|
want, limitHit string
|
||||||
}{
|
}{
|
||||||
@@ -230,11 +229,9 @@ func TestBlocklistLimitTakesPartInTheLowestPercentageOfEveryLimit(t *testing.T)
|
|||||||
// The upload's 100 bytes are over 49, a quarter of 199, and 99,
|
// The upload's 100 bytes are over 49, a quarter of 199, and 99,
|
||||||
// half of it, and within 199.
|
// half of it, and within 199.
|
||||||
line := s.uploadFrom(fromDE)
|
line := s.uploadFrom(fromDE)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.want)
|
tc.want)
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
tc.want)
|
tc.want)
|
||||||
|
|
||||||
if line.LimitHit != tc.limitHit {
|
if line.LimitHit != tc.limitHit {
|
||||||
@@ -291,11 +288,9 @@ func TestASNLimitPercentFileCountsAsTheSettingDoesTheLowerWinning(t *testing.T)
|
|||||||
loadLists(t, server, map[string][]string{asnURL: {"# by AS number", tc.file}})
|
loadLists(t, server, map[string][]string{asnURL: {"# by AS number", tc.file}})
|
||||||
|
|
||||||
line := s.uploadFrom(fromDE)
|
line := s.uploadFrom(fromDE)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.limitPercent)
|
tc.limitPercent)
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
tc.bytesPercent)
|
tc.bytesPercent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -390,7 +385,7 @@ func TestEachReputationActionForAClientADNSBLZoneLists(t *testing.T) {
|
|||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
action string
|
action string
|
||||||
// statuses and actions are those of a listed client's three
|
// statuses and actions are those of a listed client's three
|
||||||
// requests, and percent their rate_limit_percent, as percentText gives it.
|
// requests, and percent their limit_percent, as percentText gives it.
|
||||||
statuses []int
|
statuses []int
|
||||||
actions []string
|
actions []string
|
||||||
percent string
|
percent string
|
||||||
@@ -427,8 +422,8 @@ func TestEachReputationActionForAClientADNSBLZoneLists(t *testing.T) {
|
|||||||
line := s.get(from, tc.statuses[i], tc.actions[i])
|
line := s.get(from, tc.statuses[i], tc.actions[i])
|
||||||
// In the order SWW_DNSBL_ZONES names them.
|
// In the order SWW_DNSBL_ZONES names them.
|
||||||
wantReputation(t, line, listedBy[from]...)
|
wantReputation(t, line, listedBy[from]...)
|
||||||
wantPercent(t, "rate_limit_percent", line.RateLimitPercent,
|
wantPercent(t, "limit_percent", line.LimitPercent,
|
||||||
line.RateLimitPercentSetting, tc.percent)
|
line.LimitPercentSetting, tc.percent)
|
||||||
|
|
||||||
// A request refused for the verdict is not counted.
|
// A request refused for the verdict is not counted.
|
||||||
counted := line.fields["counts"] != nil
|
counted := line.fields["counts"] != nil
|
||||||
@@ -443,8 +438,7 @@ func TestEachReputationActionForAClientADNSBLZoneLists(t *testing.T) {
|
|||||||
for range 3 {
|
for range 3 {
|
||||||
line := s.get(unplaced, http.StatusOK, forward)
|
line := s.get(unplaced, http.StatusOK, forward)
|
||||||
wantReputation(t, line)
|
wantReputation(t, line)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
none)
|
none)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,7 +546,7 @@ func TestReputationLimitTakesPartInTheLowestPercentageOfEveryLimit(t *testing.T)
|
|||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
blocklistAction, reputationAction string
|
blocklistAction, reputationAction string
|
||||||
// want is the request's rate_limit_percent and bytes_limit_percent, as
|
// want is the request's limit_percent and bytes_percent, as
|
||||||
// percentText gives them.
|
// percentText gives them.
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
@@ -577,11 +571,9 @@ func TestReputationLimitTakesPartInTheLowestPercentageOfEveryLimit(t *testing.T)
|
|||||||
// Named by the blocklist, then by the zone.
|
// Named by the blocklist, then by the zone.
|
||||||
line := s.get(fromDE, http.StatusOK, requestlog.ActionForward)
|
line := s.get(fromDE, http.StatusOK, requestlog.ActionForward)
|
||||||
wantReputation(t, line, dropURL, dnsblZone)
|
wantReputation(t, line, dropURL, dnsblZone)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.want)
|
tc.want)
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
tc.want)
|
tc.want)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -827,7 +819,7 @@ func TestClientRefusedForAnOffenceIsCheckedWithAbuseIPDBAtItsNextRequest(t *test
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"the Core Rule Set", sqlInjection, http.StatusForbidden,
|
"the Core Rule Set", sqlInjection, http.StatusForbidden,
|
||||||
requestlog.ActionBlockedByCoreRuleSet, ratelimit.Offences{BlockedByCoreRuleSet: 1},
|
requestlog.ActionWAFBlocked, ratelimit.Offences{WAFBlocked: 1},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"a ban rule", probePath, http.StatusForbidden, requestlog.ActionTemporarilyBanned,
|
"a ban rule", probePath, http.StatusForbidden, requestlog.ActionTemporarilyBanned,
|
||||||
@@ -871,7 +863,7 @@ func TestEachReputationActionForAClientAbuseIPDBScoresAtOrOverTheMinimum(t *test
|
|||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
action string
|
action string
|
||||||
// statuses and actions are those of fromDE's three requests, and
|
// statuses and actions are those of fromDE's three requests, and
|
||||||
// percent their rate_limit_percent, as percentText gives it.
|
// percent their limit_percent, as percentText gives it.
|
||||||
statuses []int
|
statuses []int
|
||||||
actions []string
|
actions []string
|
||||||
percent string
|
percent string
|
||||||
@@ -904,8 +896,7 @@ func TestEachReputationActionForAClientAbuseIPDBScoresAtOrOverTheMinimum(t *test
|
|||||||
for i := range 3 {
|
for i := range 3 {
|
||||||
line := s.get(fromDE, tc.statuses[i], tc.actions[i])
|
line := s.get(fromDE, tc.statuses[i], tc.actions[i])
|
||||||
wantReputation(t, line, abuseipdb)
|
wantReputation(t, line, abuseipdb)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
tc.percent)
|
tc.percent)
|
||||||
|
|
||||||
// A request refused for the score is not counted.
|
// A request refused for the score is not counted.
|
||||||
@@ -919,8 +910,7 @@ func TestEachReputationActionForAClientAbuseIPDBScoresAtOrOverTheMinimum(t *test
|
|||||||
for range 3 {
|
for range 3 {
|
||||||
line := s.get(fromKP, http.StatusOK, forward)
|
line := s.get(fromKP, http.StatusOK, forward)
|
||||||
wantReputation(t, line)
|
wantReputation(t, line)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
none)
|
none)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ type decision struct {
|
|||||||
limitPercent, bytesPercent percentage
|
limitPercent, bytesPercent percentage
|
||||||
// attack is true for a request that matched a ban rule or asked for a
|
// attack is true for a request that matched a ban rule or asked for a
|
||||||
// trap path, blockedByBlockRule for one a block rule refused, and
|
// trap path, blockedByBlockRule for one a block rule refused, and
|
||||||
// blockedByCoreRuleSet for one the Core Rule Set refused, each an offence
|
// wafBlocked for one the Core Rule Set refused, each an offence its
|
||||||
// its client's history counts.
|
// client's history counts.
|
||||||
attack, blockedByBlockRule, blockedByCoreRuleSet bool
|
attack, blockedByBlockRule, wafBlocked bool
|
||||||
// reputation is the reputation sources that list the client, for the
|
// reputation is the reputation sources that list the client, for the
|
||||||
// notes of a ban the request makes.
|
// notes of a ban the request makes.
|
||||||
reputation []bans.ReputationHit
|
reputation []bans.ReputationHit
|
||||||
@@ -188,7 +188,7 @@ func (rq *request) check(ctx context.Context) *refusal {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
case action == requestlog.ActionBlockedByBlockRule ||
|
case action == requestlog.ActionBlockedByBlockRule ||
|
||||||
action == requestlog.ActionBlockedByCoreRuleSet:
|
action == requestlog.ActionWAFBlocked:
|
||||||
return &refusal{status: http.StatusForbidden, action: action}
|
return &refusal{status: http.StatusForbidden, action: action}
|
||||||
case action == requestlog.ActionRequestHeaderTooLarge:
|
case action == requestlog.ActionRequestHeaderTooLarge:
|
||||||
return &refusal{status: http.StatusRequestHeaderFieldsTooLarge, action: action}
|
return &refusal{status: http.StatusRequestHeaderFieldsTooLarge, action: action}
|
||||||
@@ -262,8 +262,8 @@ func (rq *request) finish() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
duration := time.Since(rq.start)
|
duration := time.Since(rq.start)
|
||||||
line.DurationTotalMS = requestlog.Milliseconds(duration)
|
line.DurationTotal = requestlog.Milliseconds(duration)
|
||||||
line.DurationChecksMS = timing(rq.start, rq.checked)
|
line.DurationChecks = timing(rq.start, rq.checked)
|
||||||
|
|
||||||
// Counted before the log line is written, so that the metrics count
|
// Counted before the log line is written, so that the metrics count
|
||||||
// every request whose line is out. An allowed request is the exception:
|
// every request whose line is out. An allowed request is the exception:
|
||||||
@@ -304,15 +304,15 @@ func timing(start, end time.Time) *float64 {
|
|||||||
// when it comes.
|
// when it comes.
|
||||||
func (rq *request) addToHistory() {
|
func (rq *request) addToHistory() {
|
||||||
request := ratelimit.Request{
|
request := ratelimit.Request{
|
||||||
Forwarded: rq.allowed,
|
Forwarded: rq.allowed,
|
||||||
Refused: rq.refused != nil,
|
Refused: rq.refused != nil,
|
||||||
Status: rq.out.status,
|
Status: rq.out.status,
|
||||||
RequestBytes: rq.requestBytes,
|
RequestBytes: rq.requestBytes,
|
||||||
ResponseBytes: rq.out.bytes,
|
ResponseBytes: rq.out.bytes,
|
||||||
BrokeLimit: rq.line.Offence == requestlog.OffenceLimit,
|
BrokeLimit: rq.line.Offence == requestlog.OffenceLimit,
|
||||||
Attack: rq.attack,
|
Attack: rq.attack,
|
||||||
BlockedByBlockRule: rq.blockedByBlockRule,
|
BlockedByBlockRule: rq.blockedByBlockRule,
|
||||||
BlockedByCoreRuleSet: rq.blockedByCoreRuleSet,
|
WAFBlocked: rq.wafBlocked,
|
||||||
}
|
}
|
||||||
|
|
||||||
rq.h.limiter.AddToHistory(rq.h.clientGroup(rq.client), rq.h.now(), request)
|
rq.h.limiter.AddToHistory(rq.h.clientGroup(rq.client), rq.h.now(), request)
|
||||||
|
|||||||
@@ -156,9 +156,9 @@ func wantBareLine(t *testing.T, line logLine) {
|
|||||||
|
|
||||||
// withTimings returns want with the timings of line.
|
// withTimings returns want with the timings of line.
|
||||||
func withTimings(line logLine, want requestlog.Line) requestlog.Line {
|
func withTimings(line logLine, want requestlog.Line) requestlog.Line {
|
||||||
want.DurationTotalMS = line.DurationTotalMS
|
want.DurationTotal = line.DurationTotal
|
||||||
want.DurationChecksMS = line.DurationChecksMS
|
want.DurationChecks = line.DurationChecks
|
||||||
want.DurationUpstreamTotalMS = line.DurationUpstreamTotalMS
|
want.DurationUpstreamTotal = line.DurationUpstreamTotal
|
||||||
|
|
||||||
return want
|
return want
|
||||||
}
|
}
|
||||||
@@ -226,10 +226,10 @@ func TestTimingsAreInOrder(t *testing.T) {
|
|||||||
|
|
||||||
// A request passed to the app has every timing; one refused, none of
|
// A request passed to the app has every timing; one refused, none of
|
||||||
// the app's; the health check, which runs no check, only the total.
|
// the app's; the health check, which runs no check, only the total.
|
||||||
wantTimings(t, forwarded, "duration_total_ms", "duration_checks_ms",
|
wantTimings(t, forwarded, "duration_total", "duration_checks",
|
||||||
"duration_upstream_total_ms")
|
"duration_upstream_total")
|
||||||
wantTimings(t, refused, "duration_total_ms", "duration_checks_ms")
|
wantTimings(t, refused, "duration_total", "duration_checks")
|
||||||
wantTimings(t, health, "duration_total_ms")
|
wantTimings(t, health, "duration_total")
|
||||||
|
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
return
|
return
|
||||||
@@ -237,9 +237,9 @@ func TestTimingsAreInOrder(t *testing.T) {
|
|||||||
|
|
||||||
// In whole microseconds, as they are logged, so that the sum below is
|
// In whole microseconds, as they are logged, so that the sum below is
|
||||||
// exact.
|
// exact.
|
||||||
total := microseconds(forwarded.DurationTotalMS)
|
total := microseconds(forwarded.DurationTotal)
|
||||||
checks := microseconds(*forwarded.DurationChecksMS)
|
checks := microseconds(*forwarded.DurationChecks)
|
||||||
upstream := microseconds(*forwarded.DurationUpstreamTotalMS)
|
upstream := microseconds(*forwarded.DurationUpstreamTotal)
|
||||||
|
|
||||||
// The checks end before the request is handed to the app.
|
// The checks end before the request is handed to the app.
|
||||||
if checks+upstream > total {
|
if checks+upstream > total {
|
||||||
@@ -247,9 +247,9 @@ func TestTimingsAreInOrder(t *testing.T) {
|
|||||||
total, checks, upstream)
|
total, checks, upstream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *refused.DurationChecksMS > refused.DurationTotalMS {
|
if *refused.DurationChecks > refused.DurationTotal {
|
||||||
t.Errorf("refused request's checks took %v of %v milliseconds",
|
t.Errorf("refused request's checks took %v of %v milliseconds",
|
||||||
*refused.DurationChecksMS, refused.DurationTotalMS)
|
*refused.DurationChecks, refused.DurationTotal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,8 +88,7 @@ func TestTagLimitPercentLowersALimitTheLowestWinning(t *testing.T) {
|
|||||||
s.get(fromDE, http.StatusOK, requestlog.ActionForward)
|
s.get(fromDE, http.StatusOK, requestlog.ActionForward)
|
||||||
|
|
||||||
line := s.get(fromDE, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
line := s.get(fromDE, http.StatusForbidden, requestlog.ActionClientIsRateLimited)
|
||||||
wantPercent(t, "rate_limit_percent",
|
wantPercent(t, "limit_percent", line.LimitPercent, line.LimitPercentSetting,
|
||||||
line.RateLimitPercent, line.RateLimitPercentSetting,
|
|
||||||
"25 from "+tagLimitPercent)
|
"25 from "+tagLimitPercent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,8 +108,7 @@ func TestTagLimitPercentLowersAByteLimitByAListTag(t *testing.T) {
|
|||||||
t.Errorf("log line has limit_hit %q, want %s", line.LimitHit, minuteBytes)
|
t.Errorf("log line has limit_hit %q, want %s", line.LimitHit, minuteBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting,
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting,
|
|
||||||
"50 from "+tagLimitPercent)
|
"50 from "+tagLimitPercent)
|
||||||
|
|
||||||
// fromKP, which the list does not hold, has the whole limit.
|
// fromKP, which the list does not hold, has the whole limit.
|
||||||
@@ -119,6 +117,5 @@ func TestTagLimitPercentLowersAByteLimitByAListTag(t *testing.T) {
|
|||||||
t.Errorf("log line for %s has limit_hit %q, want none", fromKP, line.LimitHit)
|
t.Errorf("log line for %s has limit_hit %q, want none", fromKP, line.LimitHit)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantPercent(t, "bytes_limit_percent",
|
wantPercent(t, "bytes_percent", line.BytesPercent, line.BytesPercentSetting, none)
|
||||||
line.BytesLimitPercent, line.BytesLimitPercentSetting, none)
|
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ func (g *GeoJS) LookUp(ctx context.Context, client netip.Prefix) Answer {
|
|||||||
|
|
||||||
answer, found := g.kept(client)
|
answer, found := g.kept(client)
|
||||||
if !found {
|
if !found {
|
||||||
g.metrics.RequestsWithoutGeoJSAnswer.Inc()
|
g.metrics.GeoJSUnanswered.Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
w, waiting := g.waiting[client]
|
w, waiting := g.waiting[client]
|
||||||
@@ -296,7 +296,7 @@ func (g *GeoJS) answerOrWait(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if w == nil {
|
if w == nil {
|
||||||
g.metrics.RequestsWithoutGeoJSAnswer.Inc()
|
g.metrics.GeoJSUnanswered.Inc()
|
||||||
|
|
||||||
return Answer{}, nil // too many clients wait already
|
return Answer{}, nil // too many clients wait already
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ func (g *GeoJS) answerOrWait(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if w.late {
|
if w.late {
|
||||||
g.metrics.RequestsWithoutGeoJSAnswer.Inc()
|
g.metrics.GeoJSUnanswered.Inc()
|
||||||
|
|
||||||
return Answer{}, nil
|
return Answer{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -846,7 +846,7 @@ func wantAsked(t *testing.T, geojs *standIn, i int, want ...string) {
|
|||||||
func wantUnanswered(t *testing.T, m *metrics.Metrics, want float64) {
|
func wantUnanswered(t *testing.T, m *metrics.Metrics, want float64) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
got := testutil.ToFloat64(m.RequestsWithoutGeoJSAnswer)
|
got := testutil.ToFloat64(m.GeoJSUnanswered)
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("%v requests went without an answer, want %v", got, want)
|
t.Errorf("%v requests went without an answer, want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-29
@@ -28,15 +28,15 @@ type Metrics struct {
|
|||||||
registry prometheus.Registerer
|
registry prometheus.Registerer
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
|
|
||||||
inFlight prometheus.Gauge
|
inFlight prometheus.Gauge
|
||||||
requests *prometheus.CounterVec
|
requests *prometheus.CounterVec
|
||||||
requestBytes *prometheus.CounterVec
|
requestBytes *prometheus.CounterVec
|
||||||
responseBytes *prometheus.CounterVec
|
responseBytes *prometheus.CounterVec
|
||||||
requestDuration prometheus.Histogram
|
requestDuration prometheus.Histogram
|
||||||
upstreamDuration prometheus.Histogram
|
upstreamDuration prometheus.Histogram
|
||||||
rateLimitHits *prometheus.CounterVec
|
rateLimitHits *prometheus.CounterVec
|
||||||
offences *prometheus.CounterVec
|
offences *prometheus.CounterVec
|
||||||
coreRuleSetMatches *prometheus.CounterVec
|
wafMatches *prometheus.CounterVec
|
||||||
// ruleMatches are made by AddRules, and reputationHits by
|
// ruleMatches are made by AddRules, and reputationHits by
|
||||||
// AddReputation.
|
// AddReputation.
|
||||||
ruleMatches *prometheus.CounterVec
|
ruleMatches *prometheus.CounterVec
|
||||||
@@ -45,12 +45,12 @@ type Metrics struct {
|
|||||||
asns *busiest
|
asns *busiest
|
||||||
|
|
||||||
// GeoJSRequests are the requests to GeoJS, and GeoJSFailures those
|
// GeoJSRequests are the requests to GeoJS, and GeoJSFailures those
|
||||||
// that failed. RequestsWithoutGeoJSAnswer are the requests that needed
|
// that failed. GeoJSUnanswered are the requests that needed their
|
||||||
// their client's answer, for a setting that acts on it, and went on
|
// client's answer, for a setting that acts on it, and went on without
|
||||||
// without it because GeoJS had not given it in time.
|
// it because GeoJS had not given it in time.
|
||||||
GeoJSRequests prometheus.Counter
|
GeoJSRequests prometheus.Counter
|
||||||
GeoJSFailures prometheus.Counter
|
GeoJSFailures prometheus.Counter
|
||||||
RequestsWithoutGeoJSAnswer prometheus.Counter
|
GeoJSUnanswered prometheus.Counter
|
||||||
|
|
||||||
stateFileWrites *prometheus.CounterVec
|
stateFileWrites *prometheus.CounterVec
|
||||||
stateFileWriteFailures *prometheus.CounterVec
|
stateFileWriteFailures *prometheus.CounterVec
|
||||||
@@ -101,7 +101,7 @@ func New(topN int, instanceName string) *Metrics {
|
|||||||
[]string{"window", "kind"}),
|
[]string{"window", "kind"}),
|
||||||
offences: counterVec("sww_offences_total",
|
offences: counterVec("sww_offences_total",
|
||||||
"Offences, by kind.", []string{"kind"}),
|
"Offences, by kind.", []string{"kind"}),
|
||||||
coreRuleSetMatches: counterVec("sww_core_rule_set_matches_total",
|
wafMatches: counterVec("sww_waf_matches_total",
|
||||||
"Requests that matched a rule of the Core Rule Set, by SWW_WAF_MODE "+
|
"Requests that matched a rule of the Core Rule Set, by SWW_WAF_MODE "+
|
||||||
"and the rule's id.", []string{"mode", "rule_id"}),
|
"and the rule's id.", []string{"mode", "rule_id"}),
|
||||||
countries: newCountries(topN),
|
countries: newCountries(topN),
|
||||||
@@ -114,8 +114,8 @@ func New(topN int, instanceName string) *Metrics {
|
|||||||
Name: "sww_geojs_failures_total",
|
Name: "sww_geojs_failures_total",
|
||||||
Help: "Requests to GeoJS that failed.",
|
Help: "Requests to GeoJS that failed.",
|
||||||
}),
|
}),
|
||||||
RequestsWithoutGeoJSAnswer: prometheus.NewCounter(prometheus.CounterOpts{
|
GeoJSUnanswered: prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
Name: "sww_requests_without_geojs_answer_total",
|
Name: "sww_geojs_unanswered_total",
|
||||||
Help: "Requests that needed their client's answer from GeoJS and " +
|
Help: "Requests that needed their client's answer from GeoJS and " +
|
||||||
"went on without it, because GeoJS had not given it in time.",
|
"went on without it, because GeoJS had not given it in time.",
|
||||||
}),
|
}),
|
||||||
@@ -139,9 +139,9 @@ func New(topN int, instanceName string) *Metrics {
|
|||||||
collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
|
collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
|
||||||
m.inFlight, m.requests, m.requestBytes, m.responseBytes,
|
m.inFlight, m.requests, m.requestBytes, m.responseBytes,
|
||||||
m.requestDuration, m.upstreamDuration,
|
m.requestDuration, m.upstreamDuration,
|
||||||
m.rateLimitHits, m.offences, m.coreRuleSetMatches,
|
m.rateLimitHits, m.offences, m.wafMatches,
|
||||||
m.countries, m.asns,
|
m.countries, m.asns,
|
||||||
m.GeoJSRequests, m.GeoJSFailures, m.RequestsWithoutGeoJSAnswer,
|
m.GeoJSRequests, m.GeoJSFailures, m.GeoJSUnanswered,
|
||||||
m.stateFileWrites, m.stateFileWriteFailures,
|
m.stateFileWrites, m.stateFileWriteFailures,
|
||||||
m.stateFileLastWrite, m.stateFileSize,
|
m.stateFileLastWrite, m.stateFileSize,
|
||||||
m.stateFileEditsTakenIn, m.stateFileEditsSetAside,
|
m.stateFileEditsTakenIn, m.stateFileEditsSetAside,
|
||||||
@@ -232,7 +232,7 @@ func (m *Metrics) AddRemoteLog(remote *remotelog.Sender) {
|
|||||||
return float64(remote.Dropped())
|
return float64(remote.Dropped())
|
||||||
}),
|
}),
|
||||||
prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
||||||
Name: "sww_remote_log_lines_waiting",
|
Name: "sww_remote_log_buffer_depth",
|
||||||
Help: "Log lines in the buffer, waiting to be sent.",
|
Help: "Log lines in the buffer, waiting to be sent.",
|
||||||
}, func() float64 {
|
}, func() float64 {
|
||||||
return float64(remote.Depth())
|
return float64(remote.Depth())
|
||||||
@@ -355,7 +355,7 @@ func (m *Metrics) AddAlerts(queue *alerts.Queue) {
|
|||||||
return float64(queue.Counts(name).Sent)
|
return float64(queue.Counts(name).Sent)
|
||||||
}),
|
}),
|
||||||
prometheus.NewCounterFunc(prometheus.CounterOpts{
|
prometheus.NewCounterFunc(prometheus.CounterOpts{
|
||||||
Name: "sww_alert_send_failures_total",
|
Name: "sww_alerts_failed_total",
|
||||||
Help: "Requests to the destination that failed.",
|
Help: "Requests to the destination that failed.",
|
||||||
ConstLabels: destination,
|
ConstLabels: destination,
|
||||||
}, func() float64 {
|
}, func() float64 {
|
||||||
@@ -424,10 +424,10 @@ func (m *Metrics) LimitHit(hit ratelimit.Hit) {
|
|||||||
// them.
|
// them.
|
||||||
func (m *Metrics) Offences(r ratelimit.Request) {
|
func (m *Metrics) Offences(r ratelimit.Request) {
|
||||||
for kind, committed := range map[string]bool{
|
for kind, committed := range map[string]bool{
|
||||||
"limit": r.BrokeLimit,
|
"limit": r.BrokeLimit,
|
||||||
"attack": r.Attack,
|
"attack": r.Attack,
|
||||||
"blocked_by_block_rule": r.BlockedByBlockRule,
|
"blocked_by_block_rule": r.BlockedByBlockRule,
|
||||||
"blocked_by_core_rule_set": r.BlockedByCoreRuleSet,
|
"waf_blocked": r.WAFBlocked,
|
||||||
} {
|
} {
|
||||||
if committed {
|
if committed {
|
||||||
m.offences.WithLabelValues(kind).Inc()
|
m.offences.WithLabelValues(kind).Inc()
|
||||||
@@ -441,10 +441,10 @@ func (m *Metrics) RuleMatched(id, action string) {
|
|||||||
m.ruleMatches.WithLabelValues(id, action).Inc()
|
m.ruleMatches.WithLabelValues(id, action).Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CoreRuleSetMatched counts a request that matched the Core Rule Set's rule id,
|
// WAFMatched counts a request that matched the Core Rule Set's rule id,
|
||||||
// with SWW_WAF_MODE at mode.
|
// with SWW_WAF_MODE at mode.
|
||||||
func (m *Metrics) CoreRuleSetMatched(mode string, id int) {
|
func (m *Metrics) WAFMatched(mode string, id int) {
|
||||||
m.coreRuleSetMatches.WithLabelValues(mode, strconv.Itoa(id)).Inc()
|
m.wafMatches.WithLabelValues(mode, strconv.Itoa(id)).Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateFileWritten counts a write of the state file name, of size bytes,
|
// StateFileWritten counts a write of the state file name, of size bytes,
|
||||||
|
|||||||
@@ -123,12 +123,11 @@ type Offences struct {
|
|||||||
// Limit is its requests that broke a rate limit, a byte limit or the
|
// Limit is its requests that broke a rate limit, a byte limit or the
|
||||||
// error burst, Attack those that were a clear sign of attack, a match
|
// error burst, Attack those that were a clear sign of attack, a match
|
||||||
// of a ban rule or a request for a trap path, BlockedByBlockRule those a
|
// of a ban rule or a request for a trap path, BlockedByBlockRule those a
|
||||||
// block rule refused, and BlockedByCoreRuleSet those the Core Rule Set
|
// block rule refused, and WAFBlocked those the Core Rule Set refused.
|
||||||
// refused.
|
Limit int64 `json:"limit"`
|
||||||
Limit int64 `json:"limit"`
|
Attack int64 `json:"attack"`
|
||||||
Attack int64 `json:"attack"`
|
BlockedByBlockRule int64 `json:"blocked_by_block_rule"`
|
||||||
BlockedByBlockRule int64 `json:"blocked_by_block_rule"`
|
WAFBlocked int64 `json:"waf_blocked"`
|
||||||
BlockedByCoreRuleSet int64 `json:"blocked_by_core_rule_set"`
|
|
||||||
// TokenRefused is what a clients.json written by an earlier version gives,
|
// TokenRefused is what a clients.json written by an earlier version gives,
|
||||||
// which must still load. Nothing adds to it.
|
// which must still load. Nothing adds to it.
|
||||||
TokenRefused int64 `json:"token_refused,omitempty"`
|
TokenRefused int64 `json:"token_refused,omitempty"`
|
||||||
@@ -149,11 +148,11 @@ type Request struct {
|
|||||||
// BrokeLimit is true for a request that broke a rate limit, a byte
|
// BrokeLimit is true for a request that broke a rate limit, a byte
|
||||||
// limit or the error burst, Attack for one that matched a ban rule or
|
// limit or the error burst, Attack for one that matched a ban rule or
|
||||||
// asked for a trap path, BlockedByBlockRule for one a block rule refused,
|
// asked for a trap path, BlockedByBlockRule for one a block rule refused,
|
||||||
// and BlockedByCoreRuleSet for one the Core Rule Set refused.
|
// and WAFBlocked for one the Core Rule Set refused.
|
||||||
BrokeLimit bool
|
BrokeLimit bool
|
||||||
Attack bool
|
Attack bool
|
||||||
BlockedByBlockRule bool
|
BlockedByBlockRule bool
|
||||||
BlockedByCoreRuleSet bool
|
WAFBlocked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a Limiter for limits, with no client counted yet, whose
|
// New returns a Limiter for limits, with no client counted yet, whose
|
||||||
@@ -328,8 +327,8 @@ func (l *Limiter) AddToHistory(client netip.Prefix, now time.Time, r Request) {
|
|||||||
h.Offences.BlockedByBlockRule++
|
h.Offences.BlockedByBlockRule++
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.BlockedByCoreRuleSet {
|
if r.WAFBlocked {
|
||||||
h.Offences.BlockedByCoreRuleSet++
|
h.Offences.WAFBlocked++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ const (
|
|||||||
// block rule.
|
// block rule.
|
||||||
ActionBlockedByBlockRule = "blocked_by_block_rule"
|
ActionBlockedByBlockRule = "blocked_by_block_rule"
|
||||||
|
|
||||||
// ActionBlockedByCoreRuleSet is a request refused because the Core Rule
|
// ActionWAFBlocked is a request refused because the Core Rule Set
|
||||||
// Set scored it at or over SWW_WAF_ANOMALY_THRESHOLD.
|
// scored it at or over SWW_WAF_ANOMALY_THRESHOLD.
|
||||||
ActionBlockedByCoreRuleSet = "blocked_by_core_rule_set"
|
ActionWAFBlocked = "waf_blocked"
|
||||||
|
|
||||||
// ActionClientDenied is a request refused because its client is in
|
// ActionClientDenied is a request refused because its client is in
|
||||||
// SWW_DENY_NETS, in a blocklist while SWW_BLOCKLIST_ACTION is deny,
|
// SWW_DENY_NETS, in a blocklist while SWW_BLOCKLIST_ACTION is deny,
|
||||||
@@ -55,9 +55,9 @@ const (
|
|||||||
// ActionCountryDenied is a request refused because its client's country
|
// ActionCountryDenied is a request refused because its client's country
|
||||||
// is not in SWW_EXCLUSIVELY_ALLOWED_COUNTRIES.
|
// is not in SWW_EXCLUSIVELY_ALLOWED_COUNTRIES.
|
||||||
ActionCountryDenied = "country_denied"
|
ActionCountryDenied = "country_denied"
|
||||||
// ActionOwnEndpoint is a request discriminator answered at one of its own
|
// ActionAdmin is a request discriminator answered at one of its own
|
||||||
// endpoints, or a question about a path under /_sww/.
|
// endpoints, or a question about a path under /_sww/.
|
||||||
ActionOwnEndpoint = "own_endpoint"
|
ActionAdmin = "admin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OffenceLimit is the offence a request line names for a request that
|
// OffenceLimit is the offence a request line names for a request that
|
||||||
@@ -65,9 +65,9 @@ const (
|
|||||||
// limit.
|
// limit.
|
||||||
const OffenceLimit = "limit"
|
const OffenceLimit = "limit"
|
||||||
|
|
||||||
// LimitHitMinuteRefusals is the limit_hit a request line names for a request
|
// LimitHitErrorBurst is the limit_hit a request line names for a request
|
||||||
// that broke the error burst.
|
// that broke the error burst.
|
||||||
const LimitHitMinuteRefusals = "minute_refusals"
|
const LimitHitErrorBurst = "error_burst"
|
||||||
|
|
||||||
// The discriminator_line a request line names, which says which of
|
// The discriminator_line a request line names, which says which of
|
||||||
// discriminator's two lines about a question it is.
|
// discriminator's two lines about a question it is.
|
||||||
@@ -141,9 +141,8 @@ type Line struct {
|
|||||||
// WouldAction is, in observe mode, the action enforce mode would have
|
// WouldAction is, in observe mode, the action enforce mode would have
|
||||||
// taken with a request it would have refused: ActionClientDenied,
|
// taken with a request it would have refused: ActionClientDenied,
|
||||||
// ActionTemporarilyBanned, ActionPermanentlyBanned, ActionCountryDenied,
|
// ActionTemporarilyBanned, ActionPermanentlyBanned, ActionCountryDenied,
|
||||||
// ActionClientIsRateLimited, ActionBlockedByBlockRule,
|
// ActionClientIsRateLimited, ActionBlockedByBlockRule, ActionWAFBlocked,
|
||||||
// ActionBlockedByCoreRuleSet, or, in discriminator,
|
// or, in discriminator, ActionRequestHeaderTooLarge for the header limits.
|
||||||
// ActionRequestHeaderTooLarge for the header limits.
|
|
||||||
WouldAction string `json:"would_action,omitempty"`
|
WouldAction string `json:"would_action,omitempty"`
|
||||||
// Heuristic is the name of the heuristic that refused the request, in
|
// Heuristic is the name of the heuristic that refused the request, in
|
||||||
// observe mode too, and HeuristicFigures are the figures it acted on, by
|
// observe mode too, and HeuristicFigures are the figures it acted on, by
|
||||||
@@ -155,15 +154,15 @@ type Line struct {
|
|||||||
// request.
|
// request.
|
||||||
AfterAnswerHeuristic string `json:"after_answer_heuristic,omitempty"`
|
AfterAnswerHeuristic string `json:"after_answer_heuristic,omitempty"`
|
||||||
AfterAnswerHeuristicFigures map[string]any `json:"after_answer_heuristic_figures,omitempty"` //nolint:lll // a struct tag cannot be split
|
AfterAnswerHeuristicFigures map[string]any `json:"after_answer_heuristic_figures,omitempty"` //nolint:lll // a struct tag cannot be split
|
||||||
// RateLimitPercent and RateLimitPercentSetting are, for a request the
|
// LimitPercent and LimitPercentSetting are, for a request the rate
|
||||||
// rate limits counted whose client a biased threshold gives a percentage
|
// limits counted whose client a biased threshold gives a percentage of
|
||||||
// of the rate limits below 100, that percentage and the setting that gave
|
// the rate limits below 100, that percentage and the setting that gave
|
||||||
// it. BytesLimitPercent and BytesLimitPercentSetting are the same for the
|
// it. BytesPercent and BytesPercentSetting are the same for the byte
|
||||||
// byte limits.
|
// limits.
|
||||||
RateLimitPercent *int64 `json:"rate_limit_percent,omitempty"`
|
LimitPercent *int64 `json:"limit_percent,omitempty"`
|
||||||
RateLimitPercentSetting string `json:"rate_limit_percent_setting,omitempty"`
|
LimitPercentSetting string `json:"limit_percent_setting,omitempty"`
|
||||||
BytesLimitPercent *int64 `json:"bytes_limit_percent,omitempty"`
|
BytesPercent *int64 `json:"bytes_percent,omitempty"`
|
||||||
BytesLimitPercentSetting string `json:"bytes_limit_percent_setting,omitempty"`
|
BytesPercentSetting string `json:"bytes_percent_setting,omitempty"`
|
||||||
// Counts are, for a request the rate limits counted, the client's
|
// Counts are, for a request the rate limits counted, the client's
|
||||||
// requests as they counted them with this one, and its bytes as the
|
// requests as they counted them with this one, and its bytes as the
|
||||||
// byte limits counted them, with this request's once it has ended if
|
// byte limits counted them, with this request's once it has ended if
|
||||||
@@ -171,15 +170,15 @@ type Line struct {
|
|||||||
Counts ratelimit.Counts `json:"counts,omitzero"`
|
Counts ratelimit.Counts `json:"counts,omitzero"`
|
||||||
// RuleIDs are the ids of the rule file rules the request matched.
|
// RuleIDs are the ids of the rule file rules the request matched.
|
||||||
RuleIDs []string `json:"rule_ids,omitempty"`
|
RuleIDs []string `json:"rule_ids,omitempty"`
|
||||||
// CoreRuleSetRuleIDs are the ids of the Core Rule Set's rules the request
|
// WAFRuleIDs are the ids of the Core Rule Set's rules the request
|
||||||
// matched, and CoreRuleSetScore its anomaly score, nil for a request the
|
// matched, and WAFScore its anomaly score, nil for a request the Core
|
||||||
// Core Rule Set did not inspect.
|
// Rule Set did not inspect.
|
||||||
CoreRuleSetRuleIDs []int `json:"core_rule_set_rule_ids,omitempty"`
|
WAFRuleIDs []int `json:"waf_rule_ids,omitempty"`
|
||||||
CoreRuleSetScore *int `json:"core_rule_set_score,omitempty"`
|
WAFScore *int `json:"waf_score,omitempty"`
|
||||||
// LimitHit is the window whose limit the request went over, named as
|
// LimitHit is the window whose limit the request went over, named as
|
||||||
// Counts names its count: minute, hour or day for a rate limit, and
|
// Counts names its count: minute, hour or day for a rate limit, and
|
||||||
// minute_bytes, hour_bytes or day_bytes for a byte limit; or
|
// minute_bytes, hour_bytes or day_bytes for a byte limit; or
|
||||||
// LimitHitMinuteRefusals for the error burst.
|
// LimitHitErrorBurst for the error burst.
|
||||||
LimitHit string `json:"limit_hit,omitempty"`
|
LimitHit string `json:"limit_hit,omitempty"`
|
||||||
// Reputation are the URLs of the blocklists that list the client, then
|
// Reputation are the URLs of the blocklists that list the client, then
|
||||||
// that of the CrowdSec decision list when it does, then the DNSBL zones
|
// that of the CrowdSec decision list when it does, then the DNSBL zones
|
||||||
@@ -198,15 +197,15 @@ type Line struct {
|
|||||||
// ends: a time, or "permanent".
|
// ends: a time, or "permanent".
|
||||||
BanExpires string `json:"ban_expires,omitempty"`
|
BanExpires string `json:"ban_expires,omitempty"`
|
||||||
|
|
||||||
// The timings. DurationChecksMS is the time until the checks were done, and
|
// The timings, in milliseconds. DurationChecks is the time until the
|
||||||
// DurationCoreRuleSetMS the part of it the Core Rule Set took.
|
// checks were done, and DurationWAF the part of it the Core Rule Set
|
||||||
// DurationUpstreamTotalMS is what the report of an allowed request gives,
|
// took. DurationUpstreamTotal is what the report of an allowed request gives,
|
||||||
// from the hand-over to the app until the end of its answer. Each but
|
// from the hand-over to the app until the end of its answer. Each but
|
||||||
// DurationTotalMS is nil for a request that did not get that far.
|
// DurationTotal is nil for a request that did not get that far.
|
||||||
DurationTotalMS float64 `json:"duration_total_ms"`
|
DurationTotal float64 `json:"duration_total"`
|
||||||
DurationChecksMS *float64 `json:"duration_checks_ms,omitempty"`
|
DurationChecks *float64 `json:"duration_checks,omitempty"`
|
||||||
DurationCoreRuleSetMS *float64 `json:"duration_core_rule_set_ms,omitempty"`
|
DurationWAF *float64 `json:"duration_waf,omitempty"`
|
||||||
DurationUpstreamTotalMS *float64 `json:"duration_upstream_total_ms,omitempty"`
|
DurationUpstreamTotal *float64 `json:"duration_upstream_total,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RProxyLine is rproxy's short line in the request log about one request. The
|
// RProxyLine is rproxy's short line in the request log about one request. The
|
||||||
@@ -226,11 +225,11 @@ type RProxyLine struct {
|
|||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
RequestBytes int64 `json:"request_bytes"`
|
RequestBytes int64 `json:"request_bytes"`
|
||||||
ResponseBytes int64 `json:"response_bytes"`
|
ResponseBytes int64 `json:"response_bytes"`
|
||||||
// DurationRequestMS runs from the request's headers being read until the app
|
// DurationRequest runs in milliseconds from the request's headers being read
|
||||||
// has been sent the whole request, or the answer has started if that is
|
// until the app has been sent the whole request, or the answer has started
|
||||||
// sooner. DurationResponseMS runs from then until the answer ends.
|
// if that is sooner. DurationResponse runs from then until the answer ends.
|
||||||
DurationRequestMS float64 `json:"duration_request_ms"`
|
DurationRequest float64 `json:"duration_request"`
|
||||||
DurationResponseMS float64 `json:"duration_response_ms"`
|
DurationResponse float64 `json:"duration_response"`
|
||||||
// Disposition is the valid disposition discriminator answered or, while
|
// Disposition is the valid disposition discriminator answered or, while
|
||||||
// DefaultDisposition is true, the value of SWRP_DEFAULT_DISPOSITION. It is ""
|
// DefaultDisposition is true, the value of SWRP_DEFAULT_DISPOSITION. It is ""
|
||||||
// when neither gave one.
|
// when neither gave one.
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ func TestWriteWritesOneJSONLineMarkedRequest(t *testing.T) {
|
|||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
|
|
||||||
err := requestlog.Write(&out, &requestlog.Line{
|
err := requestlog.Write(&out, &requestlog.Line{
|
||||||
Time: requestlog.FormatTime(time.Date(2026, 10, 3, 12, 0, 0, 0, time.UTC)),
|
Time: requestlog.FormatTime(time.Date(2026, 10, 3, 12, 0, 0, 0, time.UTC)),
|
||||||
ClientIP: "203.0.113.9",
|
ClientIP: "203.0.113.9",
|
||||||
Status: 200,
|
Status: 200,
|
||||||
Action: requestlog.ActionForward,
|
Action: requestlog.ActionForward,
|
||||||
DurationTotalMS: requestlog.Milliseconds(1500 * time.Microsecond),
|
DurationTotal: requestlog.Milliseconds(1500 * time.Microsecond),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("write: %v", err)
|
t.Fatalf("write: %v", err)
|
||||||
@@ -43,7 +43,7 @@ func TestWriteWritesOneJSONLineMarkedRequest(t *testing.T) {
|
|||||||
want := map[string]any{
|
want := map[string]any{
|
||||||
"type": "request", "time": "2026-10-03T12:00:00.000Z",
|
"type": "request", "time": "2026-10-03T12:00:00.000Z",
|
||||||
"client_ip": "203.0.113.9", "status": 200.0, "action": "forward",
|
"client_ip": "203.0.113.9", "status": 200.0, "action": "forward",
|
||||||
"duration_total_ms": 1.5,
|
"duration_total": 1.5,
|
||||||
}
|
}
|
||||||
for name, value := range want {
|
for name, value := range want {
|
||||||
if fields[name] != value {
|
if fields[name] != value {
|
||||||
@@ -55,9 +55,9 @@ func TestWriteWritesOneJSONLineMarkedRequest(t *testing.T) {
|
|||||||
"forwarded_for", "content_type", "content_length", "request_headers",
|
"forwarded_for", "content_type", "content_length", "request_headers",
|
||||||
"has_authorization", "has_cookie", "websocket", "response_content_type",
|
"has_authorization", "has_cookie", "websocket", "response_content_type",
|
||||||
"upstream_status", "cache_control", "location", "aborted", "counts",
|
"upstream_status", "cache_control", "location", "aborted", "counts",
|
||||||
"limit_hit", "offence", "ban_expires", "duration_checks_ms",
|
"limit_hit", "offence", "ban_expires", "duration_checks",
|
||||||
"duration_upstream_connect", "duration_upstream_first_byte",
|
"duration_upstream_connect", "duration_upstream_first_byte",
|
||||||
"duration_upstream_total_ms",
|
"duration_upstream_total",
|
||||||
}
|
}
|
||||||
for _, name := range unset {
|
for _, name := range unset {
|
||||||
_, present := fields[name]
|
_, present := fields[name]
|
||||||
@@ -82,7 +82,7 @@ func TestWriteRProxyLineWritesOneJSONLineWithOnlyItsFields(t *testing.T) {
|
|||||||
|
|
||||||
const want = `{"type":"request","time":"","request_id":"an-id","client_ip":"",` +
|
const want = `{"type":"request","time":"","request_id":"an-id","client_ip":"",` +
|
||||||
`"host":"","method":"","path":"","query":"","status":0,"request_bytes":0,` +
|
`"host":"","method":"","path":"","query":"","status":0,"request_bytes":0,` +
|
||||||
`"response_bytes":0,"duration_request_ms":0,"duration_response_ms":0,` +
|
`"response_bytes":0,"duration_request":0,"duration_response":0,` +
|
||||||
`"disposition":"allow"}` + "\n"
|
`"disposition":"allow"}` + "\n"
|
||||||
if out.String() != want {
|
if out.String() != want {
|
||||||
t.Errorf("wrote %s, want %s", out.String(), want)
|
t.Errorf("wrote %s, want %s", out.String(), want)
|
||||||
|
|||||||
@@ -371,8 +371,8 @@ func (rq *request) finish(ctx context.Context) {
|
|||||||
Status: rq.out.status,
|
Status: rq.out.status,
|
||||||
RequestBytes: requestBytes,
|
RequestBytes: requestBytes,
|
||||||
ResponseBytes: responseBytes,
|
ResponseBytes: responseBytes,
|
||||||
DurationRequestMS: requestlog.Milliseconds(requestEnd.Sub(rq.start)),
|
DurationRequest: requestlog.Milliseconds(requestEnd.Sub(rq.start)),
|
||||||
DurationResponseMS: requestlog.Milliseconds(end.Sub(requestEnd)),
|
DurationResponse: requestlog.Milliseconds(end.Sub(requestEnd)),
|
||||||
Disposition: rq.disposition,
|
Disposition: rq.disposition,
|
||||||
DefaultDisposition: rq.byDefault,
|
DefaultDisposition: rq.byDefault,
|
||||||
})
|
})
|
||||||
@@ -385,14 +385,14 @@ func (rq *request) finish(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
report := &discriminator.Report{
|
report := &discriminator.Report{
|
||||||
RequestID: rq.id,
|
RequestID: rq.id,
|
||||||
Status: min(rq.out.status, reportStatusMax),
|
Status: min(rq.out.status, reportStatusMax),
|
||||||
RequestBytes: requestBytes,
|
RequestBytes: requestBytes,
|
||||||
ResponseBytes: responseBytes,
|
ResponseBytes: responseBytes,
|
||||||
DurationTotalMS: requestlog.Milliseconds(end.Sub(rq.start)),
|
DurationTotal: requestlog.Milliseconds(end.Sub(rq.start)),
|
||||||
}
|
}
|
||||||
if !rq.upstreamStart.IsZero() {
|
if !rq.upstreamStart.IsZero() {
|
||||||
report.DurationUpstreamTotalMS = requestlog.Milliseconds(end.Sub(rq.upstreamStart))
|
report.DurationUpstreamTotal = requestlog.Milliseconds(end.Sub(rq.upstreamStart))
|
||||||
}
|
}
|
||||||
|
|
||||||
rq.h.sendReport(ctx, report)
|
rq.h.sendReport(ctx, report)
|
||||||
|
|||||||
@@ -727,7 +727,7 @@ func TestDenyGivesTheVisitorDiscriminatorsAnswer(t *testing.T) {
|
|||||||
report := standIn.report(t)
|
report := standIn.report(t)
|
||||||
if report.Status != http.StatusForbidden ||
|
if report.Status != http.StatusForbidden ||
|
||||||
report.ResponseBytes != int64(len(deniedBody)) ||
|
report.ResponseBytes != int64(len(deniedBody)) ||
|
||||||
report.DurationUpstreamTotalMS != 0 {
|
report.DurationUpstreamTotal != 0 {
|
||||||
t.Errorf("report %+v, of a request denied", report)
|
t.Errorf("report %+v, of a request denied", report)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,9 +871,9 @@ func TestALineForARequestClosedWithoutAnAnswerHasNoNegativeTime(t *testing.T) {
|
|||||||
|
|
||||||
line := out.requestLine(t)
|
line := out.requestLine(t)
|
||||||
|
|
||||||
duration, ok := line["duration_response_ms"].(float64)
|
duration, ok := line["duration_response"].(float64)
|
||||||
if !ok || duration < 0 {
|
if !ok || duration < 0 {
|
||||||
t.Errorf("line %v, want a duration_response_ms that is not negative", line)
|
t.Errorf("line %v, want a duration_response that is not negative", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1428,8 +1428,8 @@ func TestReportGivesWhatHappened(t *testing.T) {
|
|||||||
if report.RequestID == "" || report.Status != http.StatusOK ||
|
if report.RequestID == "" || report.Status != http.StatusOK ||
|
||||||
report.RequestBytes != int64(len(body)) ||
|
report.RequestBytes != int64(len(body)) ||
|
||||||
report.ResponseBytes != int64(len(greeting)) ||
|
report.ResponseBytes != int64(len(greeting)) ||
|
||||||
report.DurationTotalMS <= 0 || report.DurationUpstreamTotalMS <= 0 ||
|
report.DurationTotal <= 0 || report.DurationUpstreamTotal <= 0 ||
|
||||||
report.DurationUpstreamTotalMS > report.DurationTotalMS {
|
report.DurationUpstreamTotal > report.DurationTotal {
|
||||||
t.Errorf("report %+v, of %d bytes up and %d back", report, len(body), len(greeting))
|
t.Errorf("report %+v, of %d bytes up and %d back", report, len(body), len(greeting))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1748,7 +1748,7 @@ func TestLogLineGivesTheRequestAsSent(t *testing.T) {
|
|||||||
t.Errorf("default_disposition is %v, want it left out", line["default_disposition"])
|
t.Errorf("default_disposition is %v, want it left out", line["default_disposition"])
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range []string{"duration_request_ms", "duration_response_ms"} {
|
for _, name := range []string{"duration_request", "duration_response"} {
|
||||||
duration, ok := line[name].(float64)
|
duration, ok := line[name].(float64)
|
||||||
if !ok || duration <= 0 {
|
if !ok || duration <= 0 {
|
||||||
t.Errorf("%s is %v, want a time", name, line[name])
|
t.Errorf("%s is %v, want a time", name, line[name])
|
||||||
|
|||||||
@@ -891,7 +891,7 @@ func missingFromCounter(counter anomaly.Counter) string {
|
|||||||
return "netblock"
|
return "netblock"
|
||||||
case scope == anomaly.ScopeASN && counter.ASN == "":
|
case scope == anomaly.ScopeASN && counter.ASN == "":
|
||||||
return "asn"
|
return "asn"
|
||||||
case scope == anomaly.ScopeWatchedNet && counter.Name == "":
|
case scope == anomaly.ScopeWatch && counter.Name == "":
|
||||||
return "name"
|
return "name"
|
||||||
case countsWithoutStart(counter.Minute):
|
case countsWithoutStart(counter.Minute):
|
||||||
return "minute.start"
|
return "minute.start"
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ const filledAlertsJSON = `{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"scope": "watched_net",
|
"scope": "watch",
|
||||||
"netblock": "203.0.113.0/24",
|
"netblock": "203.0.113.0/24",
|
||||||
"name": "office",
|
"name": "office",
|
||||||
"hour": {
|
"hour": {
|
||||||
@@ -831,12 +831,12 @@ func TestAlertsJSONEntryWithoutAFieldItNeedsStopsTheStart(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"an anomaly counter of a named netblock without its name",
|
"an anomaly counter of a named netblock without its name",
|
||||||
`{"version": 1, "anomaly_counters": [` +
|
`{"version": 1, "anomaly_counters": [` +
|
||||||
`{"scope": "watched_net", "netblock": "203.0.113.0/24"}]}`,
|
`{"scope": "watch", "netblock": "203.0.113.0/24"}]}`,
|
||||||
`: anomaly_counters entry 1 has no "name"`,
|
`: anomaly_counters entry 1 has no "name"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"an anomaly counter of a named netblock without its netblock",
|
"an anomaly counter of a named netblock without its netblock",
|
||||||
`{"version": 1, "anomaly_counters": [{"scope": "watched_net", "name": "office"}]}`,
|
`{"version": 1, "anomaly_counters": [{"scope": "watch", "name": "office"}]}`,
|
||||||
`: anomaly_counters entry 1 has no "netblock"`,
|
`: anomaly_counters entry 1 has no "netblock"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1729,7 +1729,7 @@ func newParams(dir string) state.Params {
|
|||||||
Dir: dir,
|
Dir: dir,
|
||||||
WriteDelay: time.Hour,
|
WriteDelay: time.Hour,
|
||||||
CounterInterval: time.Hour,
|
CounterInterval: time.Hour,
|
||||||
Ledger: bans.New(bans.Params{
|
Ledger: bans.New(bans.Rules{
|
||||||
LimitBanDuration: time.Hour,
|
LimitBanDuration: time.Hour,
|
||||||
LimitBanRepeatWindow: 24 * time.Hour,
|
LimitBanRepeatWindow: 24 * time.Hour,
|
||||||
MaxBanDuration: 7 * 24 * time.Hour,
|
MaxBanDuration: 7 * 24 * time.Hour,
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,6 @@ import (
|
|||||||
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
"sneak.berlin/go/smallwebwaf/internal/alerts"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/config"
|
"sneak.berlin/go/smallwebwaf/internal/config"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/discriminator"
|
"sneak.berlin/go/smallwebwaf/internal/discriminator"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/lookup"
|
"sneak.berlin/go/smallwebwaf/internal/lookup"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/remotelog"
|
"sneak.berlin/go/smallwebwaf/internal/remotelog"
|
||||||
@@ -30,6 +29,7 @@ import (
|
|||||||
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
"sneak.berlin/go/smallwebwaf/internal/requestlog"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/rules"
|
"sneak.berlin/go/smallwebwaf/internal/rules"
|
||||||
"sneak.berlin/go/smallwebwaf/internal/state"
|
"sneak.berlin/go/smallwebwaf/internal/state"
|
||||||
|
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// shutdownTimeout is how long requests in progress may take to finish
|
// shutdownTimeout is how long requests in progress may take to finish
|
||||||
@@ -197,7 +197,7 @@ func RunDiscriminator(ctx context.Context, params Params) int {
|
|||||||
func newServer(
|
func newServer(
|
||||||
cfg *config.Config, stdout io.Writer, processLog *slog.Logger,
|
cfg *config.Config, stdout io.Writer, processLog *slog.Logger,
|
||||||
now func() time.Time, ruleFiles *rules.Files, alertQueue *alerts.Queue,
|
now func() time.Time, ruleFiles *rules.Files, alertQueue *alerts.Queue,
|
||||||
crs *coreruleset.CoreRuleSet,
|
crs *waf.CoreRuleSet,
|
||||||
) (*discriminator.Server, error) {
|
) (*discriminator.Server, error) {
|
||||||
var lookupFile *lookup.File
|
var lookupFile *lookup.File
|
||||||
|
|
||||||
|
|||||||
@@ -962,7 +962,7 @@ func TestStalledRemoteLogEndpointHoldsUpNoRequest(t *testing.T) {
|
|||||||
metrics := metricsText(t, url+"_sww/metrics", token)
|
metrics := metricsText(t, url+"_sww/metrics", token)
|
||||||
for _, series := range []string{
|
for _, series := range []string{
|
||||||
`sww_remote_log_lines_sent_total{instance="fsn1app1/blog"} 0`,
|
`sww_remote_log_lines_sent_total{instance="fsn1app1/blog"} 0`,
|
||||||
`sww_remote_log_lines_waiting{instance="fsn1app1/blog"} 1`,
|
`sww_remote_log_buffer_depth{instance="fsn1app1/blog"} 1`,
|
||||||
} {
|
} {
|
||||||
if !strings.Contains(metrics, "\n"+series+"\n") {
|
if !strings.Contains(metrics, "\n"+series+"\n") {
|
||||||
t.Errorf("no %q in the metrics:\n%s", series, metrics)
|
t.Errorf("no %q in the metrics:\n%s", series, metrics)
|
||||||
@@ -1068,12 +1068,8 @@ func TestBanIsAlertedAndAnAlertNotSentIsKeptAcrossARestart(t *testing.T) {
|
|||||||
metrics := metricsWith(t, url+"_sww/metrics", token,
|
metrics := metricsWith(t, url+"_sww/metrics", token,
|
||||||
"\nsww_alerts_sent_total"+ofWebhook+" 1\n")
|
"\nsww_alerts_sent_total"+ofWebhook+" 1\n")
|
||||||
|
|
||||||
for _, series := range []string{
|
for _, series := range []string{"failed", "suppressed", "dropped"} {
|
||||||
"sww_alert_send_failures_total",
|
zero := "\nsww_alerts_" + series + "_total" + ofWebhook + " 0\n"
|
||||||
"sww_alerts_suppressed_total",
|
|
||||||
"sww_alerts_dropped_total",
|
|
||||||
} {
|
|
||||||
zero := "\n" + series + ofWebhook + " 0\n"
|
|
||||||
if !strings.Contains(metrics, zero) {
|
if !strings.Contains(metrics, zero) {
|
||||||
t.Errorf("no %q in the metrics:\n%s", zero, metrics)
|
t.Errorf("no %q in the metrics:\n%s", zero, metrics)
|
||||||
}
|
}
|
||||||
|
|||||||
File renamed without changes.
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Ordinary gitea 1.27 requests that the Core Rule Set must let through at the
|
# Ordinary gitea 1.27 requests that the Core Rule Set must let through at the
|
||||||
# defaults. Each line is a path and query, and may end with one header after a
|
# defaults. Each line is a path and query, and may end with one header after a
|
||||||
# space. The tests of internal/coreruleset inspect each as a GET. The Core Rule Set reads
|
# space. The tests of internal/waf inspect each as a GET. The Core Rule Set reads
|
||||||
# the query and the headers the same way for any method.
|
# the query and the headers the same way for any method.
|
||||||
|
|
||||||
# Searches with ordinary words and symbols.
|
# Searches with ordinary words and symbols.
|
||||||
+359
@@ -0,0 +1,359 @@
|
|||||||
|
# Ordinary WordPress 7.1.4 requests, one JSON object a line, that the Core Rule
|
||||||
|
# Set must let through. Recorded from a browser and an API client, with the
|
||||||
|
# password, the cookies that sign in, the contents of uploaded files and the
|
||||||
|
# author of a plugin replaced.
|
||||||
|
{"method": "GET", "target": "/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/install.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/css/dashicons.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/css/buttons.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/css/forms.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/css/dist/base-styles/admin-schemes.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/css/install.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/css/l10n.min.css?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/js/language-chooser.min.js?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/jquery/jquery.min.js?ver=3.7.1", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/wordpress-logo-gray.svg?ver=20260303", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/css/install.min.css?ver=7.1.4", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/spinner.gif", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/css/install.min.css?ver=7.1.4", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/install.php?step=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 9", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/install.php", "Accept-Encoding: gzip, deflate"], "body": "language="}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/clipboard.min.js?ver=2.0.11", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php?step=1", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/underscore.min.js?ver=1.13.8", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php?step=1", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/wp-util.min.js?ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/install.php?step=1", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203120.0892329216003417968750", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/2026/11/09/hello-world/", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/install.php?step=2", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 203", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/install.php?step=1", "Accept-Encoding: gzip, deflate"], "body": "weblog_title=Example+Blog&user_name=editor1&admin_password=Tr0ub4dor%263-horse-staple%21&admin_password2=Tr0ub4dor%263-horse-staple%21&admin_email=editor1%40example.com&Submit=Install+WordPress&language="}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: */*", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?p=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?page_id=2", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/sample-page/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?cat=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/category/uncategorized/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/404-image.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/category/uncategorized/", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?m=202611", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/2026/11/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?author=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/author/editor1/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?feed=rss2", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/feed/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?feed=comments-rss2", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/comments/feed/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=hello", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=O%27Reilly+books", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=how+to+select+a+table+from+a+catalog", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=%22union+station%22+tickets", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=rock+%26+roll", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=cat+food", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=script+writing", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=one%2Ftwo", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?paged=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/hello-world/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/search/hello/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-sitemap.xml", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-sitemap-index.xsl", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-sitemap.xml", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-sitemap-posts-post-1.xml", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-sitemap.xsl", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-sitemap-posts-post-1.xml", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/robots.txt", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-login.php?action=lostpassword", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,buttons,forms,l10n,wp-base-styles,wp-tooltip,login&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-login.php?action=lostpassword", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-login.php?redirect_to=http%3A%2F%2Fblog.example%2Fwp-admin%2F&reauth=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=clipboard,jquery-core,jquery-migrate,zxcvbn-async,wp-hooks&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-login.php?redirect_to=http%3A%2F%2Fblog.example%2Fwp-admin%2F&reauth=1", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-comments-post.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 241", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/2026/11/09/hello-world/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": "comment=Nice+post%21+I%27d+add+that+select+wines+%26+cheese+go+well%3B+see+https%3A%2F%2Fexample.org%2Fx%3Fa%3D1.&author=Jo+Reader&email=jo%40example.com&url=https%3A%2F%2Fexample.org%2F&submit=Post+Comment&comment_post_ID=1&comment_parent=0"}
|
||||||
|
{"method": "GET", "target": "/2026/11/09/hello-world/?unapproved=2&moderation-hash=c87857727b8aab5e31944f32f2f17826", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/2026/11/09/hello-world/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-login.php?action=lostpassword", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 58", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-login.php?action=lostpassword", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": "user_login=editor1&redirect_to=&wp-submit=Get+New+Password"}
|
||||||
|
{"method": "GET", "target": "/wp-login.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-login.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 171", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-login.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": "log=editor1%40example.com&pwd=wrong%27+pass--+%3B+%22quoted%22+%3Cb%3E+%26+%2Fetc%2Fhosts&wp-submit=Log+In&redirect_to=http%3A%2F%2Fblog.example%2Fwp-admin%2F&testcookie=1"}
|
||||||
|
{"method": "POST", "target": "/wp-login.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 127", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-login.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": "log=editor1&pwd=Tr0ub4dor%263-horse-staple%21&wp-submit=Log+In&redirect_to=http%3A%2F%2Fblog.example%2Fwp-admin%2F&testcookie=1"}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203150.3890221118927001953125", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=hoverIntent,wp-dom-ready,wp-hooks&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,site-health,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-poi&load%5Bchunk_1%5D=nter,widgets,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/users/me?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/admin-ajax.php?action=wp-compression-test&test=1&_ajax_nonce=874d028d1a&1794203151554", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/js/thickbox/loadingAnimation.gif", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/admin-ajax.php?action=wp-compression-test&test=no&_ajax_nonce=874d028d1a&1794203151641", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 60", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": "_wpnonce=52dc4bc08a&timezone=UTC&action=get-community-events"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/index.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203150"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/admin-ajax.php?action=dashboard-widgets&widget=dashboard_primary&pagenow=dashboard", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html, */*; q=0.01", "X-Requested-With: XMLHttpRequest", "Referer: http://blog.example/wp-admin/index.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203152"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/update-core.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203152"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-pointer,widgets&load%5Bchunk_1%5D=,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-theme,wp-components,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/update-core.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203153"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203153"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-pointer,widgets&load%5Bchunk_1%5D=,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203154"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 126", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203154"], "body": "data%5Bwp-check-locked-posts%5D%5B%5D=post-1&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-post&has_focus=true"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/post-new.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203154"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,moxiejs,plupload&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,buttons,media-views,editor-buttons,wp-theme,wp-components,wp-preferences,wp-block-editor,wp-reusable-blocks,&load%5Bchunk_1%5D=wp-patterns,wp-media-utils,wp-editor,wp-base-styles,common,forms,wp-reset-editor-styles,wp-block-library,wp-block-editor-content&load%5Bchunk_2%5D=,wp-edit-blocks,wp-commands,wp-edit-post,wp-block-directory,wp-format-library,admin-menu,dashboard,list-tables,edit,revisions,me&load%5Bchunk_3%5D=dia,themes,about,nav-menus,wp-pointer,widgets,site-icon,l10n,wp-tooltip,wp-auth-check&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/users/me?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 118", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": "{\"meta\":{\"persisted_preferences\":{\"core\":{\"isComplementaryAreaVisible\":true},\"_modified\":\"2026-11-09T05:45:57.030Z\"}}}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=wp-polyfill&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=6&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/blocks?context=edit&per_page=100&page=1&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/wp_pattern_category?context=view&per_page=100&_fields=id%2Cname%2Cdescription%2Cslug&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?post_status=publish&post_type=post", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203155"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=hello&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203157"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit-tags.php?taxonomy=category", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203158"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit-tags.php?taxonomy=post_tag", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203159"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203160"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,buttons,media-views,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menu&load%5Bchunk_1%5D=s,wp-pointer,widgets,site-icon,l10n,wp-base-styles,wp-tooltip,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/upload.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203160"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-includes/images/spinner.gif", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,buttons,media-views,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menu&load%5Bchunk_1%5D=s,wp-pointer,widgets,site-icon,l10n,wp-base-styles,wp-tooltip,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203160"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 128", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/upload.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203160"], "body": "action=query-attachments&post_id=0&query%5Borderby%5D=date&query%5Border%5D=DESC&query%5Bposts_per_page%5D=80&query%5Bpaged%5D=1"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203160"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/media-new.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203161"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,wp-dom-ready,wp-hooks&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/media-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203162"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=hoverIntent&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/media-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203162"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?post_type=page", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203162"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 171", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203163"], "body": "data%5Bwp-check-locked-posts%5D%5B%5D=post-3&data%5Bwp-check-locked-posts%5D%5B%5D=post-2&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-page&has_focus=true"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/post-new.php?post_type=page", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203163"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=8&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203164"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/block-patterns/patterns?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203164"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/users/me?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 158", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203164"], "body": "{\"meta\":{\"persisted_preferences\":{\"core\":{\"isComplementaryAreaVisible\":true},\"_modified\":\"2026-11-09T05:46:05.490Z\",\"core/edit-post\":{\"welcomeGuide\":false}}}}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit-comments.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203164"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit-comments.php?comment_status=moderated", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203165"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/themes.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203166"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/screenshot.png?ver=1.5", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/themes.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203167"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfour/screenshot.png?ver=1.6", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/themes.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203167"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentythree/screenshot.png?ver=1.7", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/themes.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203167"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/theme-install.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203167"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 73", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/theme-install.php?browse=popular", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203168"], "body": "request%5Bper_page%5D=100&request%5Bbrowse%5D=popular&action=query-themes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/site-editor.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203168"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,wp-theme,wp-components,wp-preferences,wp-block-editor,wp-reusable-blocks,wp-patterns,wp-media-utils,wp-edito&load%5Bchunk_1%5D=r,wp-base-styles,common,forms,wp-reset-editor-styles,wp-block-library,wp-block-editor-content,wp-edit-blocks,wp-commands,wp-edit&load%5Bchunk_2%5D=-site,wp-format-library,buttons,media-views,wp-block-directory,admin-menu,dashboard,list-tables,edit,revisions,media,themes,abou&load%5Bchunk_3%5D=t,nav-menus,wp-pointer,widgets,site-icon,l10n,wp-tooltip,wp-auth-check&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203169"], "body": ""}
|
||||||
|
{"method": "OPTIONS", "target": "/wp-json/wp/v2/settings?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203169"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/nav-menus.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203169"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/widgets.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203169"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/customize.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203169"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-pointer,widgets,site-icon&load%5Bchunk_1%5D=,l10n,wp-base-styles,wp-tooltip,buttons,customize-controls,customize-nav-menus,code-editor,media-views&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/customize.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203172"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,wp-hooks,underscore,wp-dom-ready&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/customize.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203172"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=heartbeat,customize-base,wp-util,customize-controls,backbone,wp-backbone,accordion,wp-sanitize,customize-nav-menus,imgareaselect&load%5Bchunk_1%5D=,customize-models,shortcode,media-models,wp-plupload&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/customize.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203172"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?customize_changeset_uuid=45b3ef42-f34c-4dde-bde2-41c27b05accf&customize_theme=twentytwentyfive&customize_messenger_channel=preview-0", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/customize.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203172"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugins.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203172"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugins.php?plugin_status=inactive", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203173"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203174"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?tab=popular", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203175"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=contact+form&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203178"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203180"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,code-editor,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-poi&load%5Bchunk_1%5D=nter,widgets,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203184"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,wp-codemirror,underscore&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203184"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?plugin=akismet%2Fakismet.php&file=akismet%2Fakismet.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203184"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?file=akismet%2Fclass.akismet.php&plugin=akismet%2Fakismet.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203185"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?file=hello.php&plugin=hello.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203186"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/theme-editor.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203188"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/users.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203189"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/user-new.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203190"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,utils,zxcvbn-async&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Referer: http://blog.example/wp-admin/user-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203191"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203193.0920450687408447265625", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/profile.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203191"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/users.php?s=editor&action=-1&new_role&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203192"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/tools.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203194"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/import.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203195"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/export.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203196"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/types/post?context=edit", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "X-WP-Nonce: b40ef802e6", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP Cookie check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203197; wp-settings-1=", "Connection: close"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/site-health.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203197"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-site-health/v1/tests/dotorg-communication?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "X-WP-Nonce: b40ef802e6", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Referer: http://blog.example/wp-admin/site-health.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203198"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/site-health.php?tab=debug", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203198"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-site-health/v1/directory-sizes", "headers": ["Host: blog.example", "Connection: keep-alive", "X-WP-Nonce: b40ef802e6", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Referer: http://blog.example/wp-admin/site-health.php?tab=debug", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203198"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/export-personal-data.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203198"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/erase-personal-data.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203200"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-general.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203201"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=media-views&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/options-general.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203202"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-writing.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203202"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-reading.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203203"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-discussion.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203204"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-media.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203205"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203208.0107820034027099609375", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-permalink.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203206"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-privacy.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203207"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/about.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203209"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/about-release-badge.svg?ver=7.1", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/about.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203210"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/about-header-default.svg?ver=7.1", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-pointer,widgets&load%5Bchunk_1%5D=,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203210"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/credits.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203210"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/about-header-credits.svg?ver=7.1", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,common,forms,admin-menu,dashboard,list-tables,edit,revisions,media,themes,about,nav-menus,wp-pointer,widgets&load%5Bchunk_1%5D=,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-theme,wp-components,wp-commands&ver=7.1.4", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203211"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/freedoms.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203211"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/freedom-1.svg?ver=6.5", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/freedoms.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203212"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/images/freedom-2.svg?ver=6.5", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/freedoms.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203212"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/privacy.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203212"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=9&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/tags?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 20", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": "{\"name\":\"bob's tag\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/categories?search=a&per_page=20&_fields=id%2Cname&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=hello&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?per_page=10&_fields=id%2Ctitle&context=edit&status=draft%2Cpublish&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/block-types?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/themes?status=active&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/plugins?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/settings?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?post=1&per_page=5&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/pages?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 84", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": "{\"title\":\"An about page\",\"content\":\"<p>Our story & more</p>\",\"status\":\"publish\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/settings?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 52", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": "{\"title\":\"Example Blog\",\"description\":\"Bob's words\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/users/me?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 63", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": "{\"description\":\"Writer of <em>things</em>; likes select wines\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-site-health/v1/tests/background-updates?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Cookie: wordpress_test_cookie=WP Cookie check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215", "Connection: close", "Content-Length: 25", "Content-Type: application/x-www-form-urlencoded"], "body": "site-health=loopback-test"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-site-health/v1/tests/loopback-requests?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-site-health/v1/tests/https-status?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/oembed/1.0/proxy?url=https%3A%2F%2Fexample.org%2Fvideo%2F123&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/url-details?url=https%3A%2F%2Fexample.org%2F&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/block-renderer/core/archives?context=edit&attributes%5BdisplayAsDropdown%5D=false&post_id=1&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203215"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=11&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: */*", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/templates/lookup?slug=single-post-bobs-first-post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/uploads/2026/11/a.png", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/11/autosaves?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 968", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": "{\"status\":\"draft\",\"title\":\"Bob's first post: a guide\",\"excerpt\":\"a short summary\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\",\"meta\":{\"footnotes\":\"\"}}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/11?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 896", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=11&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": "{\"id\":11,\"slug\":\"bobs-first-post\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 123", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=11&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": "data%5Bwp-refresh-post-lock%5D%5Bpost_id%5D=11&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=post&has_focus=true"}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203235.2958478927612304687500", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/11?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 890", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=11&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": "{\"id\":11,\"status\":\"publish\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/post.php?post=11&action=edit", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203220"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?p=11", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203240"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/2026/11/09/bobs-first-post/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203240"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?p=11&preview=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203240"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/revision.php?revision=12", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203240"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 58", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/revision.php?revision=12", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203248"], "body": "compare%5B%5D=12%3A11&action=get-revision-diffs&post_id=11"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?post_type=wp_block", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203248"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/load-styles.php?c=0&dir=ltr&load%5Bchunk_0%5D=dashicons,admin-bar,wp-theme,wp-components,wp-list-reusable-blocks,common,forms,admin-menu,dashboard,list-tables,edit,revisions,&load%5Bchunk_1%5D=media,themes,about,nav-menus,wp-pointer,widgets,site-icon,l10n,wp-base-styles,wp-tooltip,buttons,wp-auth-check,wp-commands&ver=7.1.4", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/css,*/*;q=0.1", "Referer: http://blog.example/wp-admin/edit.php?post_type=wp_block", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203249"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 85", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php?post_type=wp_block", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203249"], "body": "interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-wp_block&has_focus=true"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options-permalink.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 189", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-permalink.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203250"], "body": "_wpnonce=4c458d2a5d&_wp_http_referer=%2Fwp-admin%2Foptions-permalink.php&selection=%2F%25postname%25%2F&permalink_structure=%2F%25postname%25%2F&category_base=&tag_base=&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-permalink.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-permalink.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203250"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-login.php?redirect_to=http%3A%2F%2Fblog.example%2Fwp-admin%2F", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203251"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=13&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/13/autosaves?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 968", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": "{\"status\":\"draft\",\"title\":\"Bob's first post: a guide\",\"excerpt\":\"a short summary\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\",\"meta\":{\"footnotes\":\"\"}}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/13?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 896", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=13&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": "{\"id\":13,\"slug\":\"bobs-first-post\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/templates/lookup?slug=single-post-bobs-first-post-2&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post.php?post=13&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 123", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=13&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": "data%5Bwp-refresh-post-lock%5D%5Bpost_id%5D=13&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=post&has_focus=true"}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203288.2769880294799804687500", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts/13?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 890", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=13&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": "{\"id\":13,\"status\":\"publish\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\nSELECT name FROM users WHERE id = 1;\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\\n\\n<!-- wp:shortcode -->\\n[gallery ids=\\\"1,2\\\"]\\n<!-- /wp:shortcode -->\\n\\n<!-- wp:image {\\\"id\\\":5,\\\"sizeSlug\\\":\\\"large\\\"} -->\\n<figure class=\\\"wp-block-image size-large\\\"><img src=\\\"http://blog.example/wp-content/uploads/2026/11/a.png\\\" alt=\\\"\\\" class=\\\"wp-image-5\\\"/></figure>\\n<!-- /wp:image -->\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/post.php?post=13&action=edit", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203276"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?p=13", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203292"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/bobs-first-post-2/", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203292"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?p=13&preview=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203292"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/revision.php?revision=14", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203292"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 58", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/revision.php?revision=14", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203301"], "body": "compare%5B%5D=14%3A13&action=get-revision-diffs&post_id=13"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=15&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203303"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=17&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 415", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryAaeabRwojB6M1Wog", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "------WebKitFormBoundaryAaeabRwojB6M1Wog\r\nContent-Disposition: form-data; name=\"file\"; filename=\"holiday-photo.png\"\r\nContent-Type: image/png\r\n\r\nimage data\r\n------WebKitFormBoundaryAaeabRwojB6M1Wog\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\nBob's picture\r\n------WebKitFormBoundaryAaeabRwojB6M1Wog\r\nContent-Disposition: form-data; name=\"alt_text\"\r\n\r\na small picture\r\n------WebKitFormBoundaryAaeabRwojB6M1Wog--\r\n"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media/18?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 53", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "{\"caption\":\"A caption\",\"description\":\"A description\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 409", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryZ3NQqb5rHLeqDitl", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "------WebKitFormBoundaryZ3NQqb5rHLeqDitl\r\nContent-Disposition: form-data; name=\"file\"; filename=\"bin-day.png\"\r\nContent-Type: image/png\r\n\r\nimage data\r\n------WebKitFormBoundaryZ3NQqb5rHLeqDitl\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\nBob's picture\r\n------WebKitFormBoundaryZ3NQqb5rHLeqDitl\r\nContent-Disposition: form-data; name=\"alt_text\"\r\n\r\na small picture\r\n------WebKitFormBoundaryZ3NQqb5rHLeqDitl--\r\n"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media/19?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 53", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "{\"caption\":\"A caption\",\"description\":\"A description\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 417", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryPj3tR1NjEw5stIqA", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "------WebKitFormBoundaryPj3tR1NjEw5stIqA\r\nContent-Disposition: form-data; name=\"file\"; filename=\"my passwd reset.png\"\r\nContent-Type: image/png\r\n\r\nimage data\r\n------WebKitFormBoundaryPj3tR1NjEw5stIqA\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\nBob's picture\r\n------WebKitFormBoundaryPj3tR1NjEw5stIqA\r\nContent-Disposition: form-data; name=\"alt_text\"\r\n\r\na small picture\r\n------WebKitFormBoundaryPj3tR1NjEw5stIqA--\r\n"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/media/20?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 53", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": "{\"caption\":\"A caption\",\"description\":\"A description\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/media-new.php?browser-uploader", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203308"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/async-upload.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 778", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFjx3GBevQOAuXrl5", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/media-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203310"], "body": "------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nscan-01.png\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"post_id\"\r\n\r\n0\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"_wpnonce\"\r\n\r\n87ab0e0dbf\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\n\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"tab\"\r\n\r\n\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"short\"\r\n\r\n1\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5\r\nContent-Disposition: form-data; name=\"async-upload\"; filename=\"scan-01.png\"\r\nContent-Type: image/png\r\n\r\nimage data\r\n------WebKitFormBoundaryFjx3GBevQOAuXrl5--\r\n"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/async-upload.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 24", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/media-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203310"], "body": "attachment_id=21&fetch=3"}
|
||||||
|
{"method": "GET", "target": "/wp-content/uploads/2026/11/scan-01.png", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/media-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203310"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/uploads/2026/11/holiday-photo.png", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Referer: http://blog.example/wp-admin/upload.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203317"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?item=6", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203317"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 472", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-general.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203324"], "body": "option_page=general&action=update&_wpnonce=d9d12950f3&_wp_http_referer=%2Fwp-admin%2Foptions-general.php&blogname=Example+Blog&blogdescription=Bob%27s+words+%26+thoughts&site_icon=0&siteurl=http%3A%2F%2Fblog.example&home=http%3A%2F%2Fblog.example&new_admin_email=editor1%40example.com&default_role=subscriber&WPLANG=&timezone_string=UTC%2B0&date_format=F+j%2C+Y&date_format_custom=F+j%2C+Y&time_format=g%3Ai+a&time_format_custom=g%3Ai+a&start_of_week=1&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-general.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-general.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203324"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 197", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-reading.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203326"], "body": "option_page=reading&action=update&_wpnonce=1872e80cc5&_wp_http_referer=%2Fwp-admin%2Foptions-reading.php&show_on_front=posts&posts_per_page=12&posts_per_rss=10&rss_use_excerpt=0&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-reading.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-reading.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203326"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 616", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-discussion.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203328"], "body": "option_page=discussion&action=update&_wpnonce=1ac818c98b&_wp_http_referer=%2Fwp-admin%2Foptions-discussion.php&default_pingback_flag=1&default_ping_status=open&default_comment_status=open&require_name_email=1&close_comments_days_old=14&show_comments_cookies_opt_in=1&thread_comments=1&thread_comments_depth=5&comments_per_page=50&default_comments_page=newest&comment_order=asc&comments_notify=1&moderation_notify=1&wp_notes_notify=1&comment_previously_approved=1&comment_max_links=2&moderation_keys=buy+now%0D%0Acheap+watches&disallowed_keys=&show_avatars=1&avatar_rating=G&avatar_default=mystery&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-discussion.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-discussion.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203328"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 283", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-media.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203330"], "body": "option_page=media&action=update&_wpnonce=fe10b63129&_wp_http_referer=%2Fwp-admin%2Foptions-media.php&thumbnail_size_w=160&thumbnail_size_h=150&thumbnail_crop=1&medium_size_w=300&medium_size_h=300&large_size_w=1024&large_size_h=1024&uploads_use_yearmonth_folders=1&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-media.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-media.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203330"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/options.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 339", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-writing.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203332"], "body": "option_page=writing&action=update&_wpnonce=1e8037a08d&_wp_http_referer=%2Fwp-admin%2Foptions-writing.php&default_category=1&default_post_format=0&mailserver_url=mail.example.com&mailserver_port=110&mailserver_login=login%40example.com&mailserver_pass=&default_email_category=1&ping_sites=https%3A%2F%2Fexample.org%2Frpc&submit=Save+Changes"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-writing.php?settings-updated=true", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/options-writing.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203332"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 226", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit-tags.php?taxonomy=category", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203334"], "body": "action=add-tag&screen=edit-category&taxonomy=category&post_type=post&_wpnonce_add-tag=f99019c9ad&_wp_http_referer=%2Fwp-admin%2Fedit-tags.php%3Ftaxonomy%3Dcategory&tag-name=Food+%26+Drink&slug=food-drink&parent=-1&description="}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugins.php?action=activate&plugin=akismet%2Fakismet.php&plugin_status=all&paged=1&s&_wpnonce=8b9b53e587", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203337"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugins.php?activate=true&plugin_status=all&paged=1&s=", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203337"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/options-general.php?page=akismet-key-config&view=start", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203339"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugins.php?action=activate&plugin=hello.php&plugin_status=all&paged=1&s&_wpnonce=5f6bf67faf", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203339"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?plugin=hello.php&file=hello.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203340"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 54", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/plugin-editor.php?plugin=hello.php&file=hello.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203342"], "body": "pointer=plugin_editor_notice&action=dismiss-wp-pointer"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?plugin=hello.php&file=hello.php&wp_scrape_key=8e954aa3fcf28d6a7f8071208fa1b507&wp_scrape_nonce=743587269", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP Cookie check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203342", "Connection: close"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?wp_scrape_key=8e954aa3fcf28d6a7f8071208fa1b507&wp_scrape_nonce=743587269", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP Cookie check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203342", "Connection: close"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 3611", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/plugin-editor.php?plugin=hello.php&file=hello.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203342"], "body": "nonce=ce99c3187f&_wp_http_referer=%2Fwp-admin%2Fplugin-editor.php%3Fplugin%3Dhello.php%26file%3Dhello.php&newcontent=%3C%3Fphp%0A%2F**%0A+*+%40package+Hello_Dolly%0A+*+%40version+1.7.2%0A+*%2F%0A%2F*%0APlugin+Name%3A+Hello+Dolly%0APlugin+URI%3A+http%3A%2F%2Fwordpress.org%2Fplugins%2Fhello-dolly%2F%0ADescription%3A+This+is+not+just+a+plugin%2C+it+symbolizes+the+hope+and+enthusiasm+of+an+entire+generation+summed+up+in+two+words+sung+most+famously+by+Louis+Armstrong%3A+Hello%2C+Dolly.+When+activated+you+will+randomly+see+a+lyric+from+%3Ccite%3EHello%2C+Dolly%3C%2Fcite%3E+in+the+upper+right+of+your+admin+screen+on+every+page.%0AAuthor%3A+Example+Author%0AVersion%3A+1.7.2%0AAuthor+URI%3A+http%3A%2F%2Fexample.com%2F%0AText+Domain%3A+hello-dolly%0A*%2F%0A%0A%2F%2F+Don't+load+directly.%0Aif+(+!+defined(+'ABSPATH'+)+)+%7B%0A%09exit%3B%0A%7D%0A%0Afunction+hello_dolly_get_lyric()+%7B%0A%09%2F**+These+are+the+lyrics+to+Hello+Dolly+*%2F%0A%09%24lyrics+%3D+%22Hello%2C+Dolly%0AWell%2C+hello%2C+Dolly%0AIt's+so+nice+to+have+you+back+where+you+belong%0AYou're+lookin'+swell%2C+Dolly%0AI+can+tell%2C+Dolly%0AYou're+still+glowin'%2C+you're+still+crowin'%0AYou're+still+goin'+strong%0AI+feel+the+room+swayin'%0AWhile+the+band's+playin'%0AOne+of+our+old+favorite+songs+from+way+back+when%0ASo%2C+take+her+wrap%2C+fellas%0ADolly%2C+never+go+away+again%0AHello%2C+Dolly%0AWell%2C+hello%2C+Dolly%0AIt's+so+nice+to+have+you+back+where+you+belong%0AYou're+lookin'+swell%2C+Dolly%0AI+can+tell%2C+Dolly%0AYou're+still+glowin'%2C+you're+still+crowin'%0AYou're+still+goin'+strong%0AI+feel+the+room+swayin'%0AWhile+the+band's+playin'%0AOne+of+our+old+favorite+songs+from+way+back+when%0ASo%2C+golly%2C+gee%2C+fellas%0AHave+a+little+faith+in+me%2C+fellas%0ADolly%2C+never+go+away%0APromise%2C+you'll+never+go+away%0ADolly'll+never+go+away+again%22%3B%0A%0A%09%2F%2F+Here+we+split+it+into+lines.%0A%09%24lyrics+%3D+explode(+%22%5Cn%22%2C+%24lyrics+)%3B%0A%0A%09%2F%2F+And+then+randomly+choose+a+line.%0A%09return+wptexturize(+%24lyrics%5B+mt_rand(+0%2C+count(+%24lyrics+)+-+1+)+%5D+)%3B%0A%7D%0A%0A%2F%2F+This+just+echoes+the+chosen+line%2C+we'll+position+it+later.%0Afunction+hello_dolly()+%7B%0A%09%24chosen+%3D+hello_dolly_get_lyric()%3B%0A%09%24lang+++%3D+''%3B%0A%09if+(+'en_'+!%3D%3D+substr(+get_user_locale()%2C+0%2C+3+)+)+%7B%0A%09%09%24lang+%3D+'+lang%3D%22en%22'%3B%0A%09%7D%0A%0A%09printf(%0A%09%09'%3Cp+id%3D%22dolly%22%3E%3Cspan+class%3D%22screen-reader-text%22%3E%25s+%3C%2Fspan%3E%3Cspan+dir%3D%22ltr%22%25s%3E%25s%3C%2Fspan%3E%3C%2Fp%3E'%2C%0A%09%09__(+'Quote+from+Hello+Dolly+song%2C+by+Jerry+Herman%3A'+)%2C%0A%09%09%24lang%2C%0A%09%09%24chosen%0A%09)%3B%0A%7D%0A%0A%2F%2F+Now+we+set+that+function+up+to+execute+when+the+admin_notices+action+is+called.%0Aadd_action(+'admin_notices'%2C+'hello_dolly'+)%3B%0A%0A%2F%2F+We+need+some+CSS+to+position+the+paragraph.%0Afunction+dolly_css()+%7B%0A%09echo+%22%0A%09%3Cstyle+type%3D'text%2Fcss'%3E%0A%09%23dolly+%7B%0A%09%09float%3A+right%3B%0A%09%09padding%3A+5px+10px%3B%0A%09%09margin%3A+0%3B%0A%09%09font-size%3A+12px%3B%0A%09%09line-height%3A+1.6666%3B%0A%09%7D%0A%09.rtl+%23dolly+%7B%0A%09%09float%3A+left%3B%0A%09%7D%0A%09.block-editor-page+%23dolly+%7B%0A%09%09display%3A+none%3B%0A%09%7D%0A%09%40media+screen+and+(max-width%3A+782px)+%7B%0A%09%09%23dolly%2C%0A%09%09.rtl+%23dolly+%7B%0A%09%09%09float%3A+none%3B%0A%09%09%09padding-left%3A+0%3B%0A%09%09%09padding-right%3A+0%3B%0A%09%09%7D%0A%09%7D%0A%09%3C%2Fstyle%3E%0A%09%22%3B%0A%7D%0A%0Aadd_action(+'admin_head'%2C+'dolly_css'+)%3B%0A&action=edit-theme-plugin-file&file=hello.php&plugin=hello.php&docs-list="}
|
||||||
|
{"method": "GET", "target": "/wp-admin/theme-editor.php?file=style.css&theme=twentytwentyfive", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203342"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/themes.php?theme=twentytwentyfour", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203349"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/customize.php?return=%2Fwp-admin%2Fthemes.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203349"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?customize_changeset_uuid=3a1c1c1e-e2b2-47ca-a042-c99fe3ad52dd&customize_theme=twentytwentyfive&customize_messenger_channel=preview-0", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/customize.php?return=%2Fwp-admin%2Fthemes.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203350"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 218", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "data%5Bwp-check-locked-posts%5D%5B%5D=post-13&data%5Bwp-check-locked-posts%5D%5B%5D=post-11&data%5Bwp-check-locked-posts%5D%5B%5D=post-1&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-post&has_focus=true"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 82", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "interval=60&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-post&has_focus=false"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 94", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=closed-postboxes&closed=dashboard_primary&hidden=&closedpostboxesnonce=0&page=dashboard"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 41", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=ajax-tag-search&tax=post_tag&q=bob"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 142", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=query-attachments&post_id=0&query%5Borderby%5D=date&query%5Border%5D=DESC&query%5Bposts_per_page%5D=80&query%5Bpaged%5D=1&_ajax_nonce=0"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 33", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=wp-compression-test&test=1"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 54", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=wp-link-ajax&search=hello&_ajax_linking_nonce=0"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 40", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With: XMLHttpRequest", "Accept: */*", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "action=oembed-cache&post=1&_ajax_nonce=0"}
|
||||||
|
{"method": "POST", "target": "/wp-cron.php?doing_wp_cron=1794203360.3913509845733642578125", "headers": ["Host: blog.example", "User-Agent: WordPress/7.1.4; http://blog.example", "Accept: */*", "Accept-Encoding: deflate, gzip, br, zstd", "Connection: close", "Content-Length: 0", "Content-Type: application/x-www-form-urlencoded"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 377", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203356"], "body": "post_title=Bob's+quick+title&post_name=bobs-first-post-2&mm=11&jj=09&aa=2026&hh=05&mn=48&ss=08&post_author=1&post_password=&post_category%5B%5D=0&post_category%5B%5D=1&tax_input%5Bpost_tag%5D=&comment_status=open&ping_status=open&_status=publish&_inline_edit=80b31520db&post_view=list&screen=edit-post&action=inline-save&post_type=post&post_ID=13&edit_date=true&post_status=all"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/profile.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 467", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/profile.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203362"], "body": "_wpnonce=931bec229d&_wp_http_referer=%2Fwp-admin%2Fprofile.php&from=profile&checkuser_id=1&color-nonce=1c207de10d&admin_color=modern&admin_bar_front=1&locale=site-default&user_login=editor1&first_name=Bob&last_name=&nickname=editor1&display_name=editor1&email=editor1%40example.com&url=http%3A%2F%2Fblog.example&description=I+write+about+%2Fetc%2F+and+%3Cem%3Ecats%3C%2Fem%3E.&pass1=&pass2=&new_application_password_name=&action=update&user_id=1&submit=Update+Profile"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/profile.php?updated=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/profile.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203362"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/user-new.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 293", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/user-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203364"], "body": "action=createuser&_wpnonce_create-user=0a10e6c68f&_wp_http_referer=%2Fwp-admin%2Fuser-new.php&user_login=author2&email=author2%40example.com&first_name=&last_name=&url=&pass1=Pw-for-author2-is-long%21&pass2=Pw-for-author2-is-long%21&send_user_notification=1&role=subscriber&createuser=Add+User"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/users.php?update=add&id=2", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/user-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203364"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 79", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit-comments.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203365"], "body": "_ajax_nonce=575b959a1d&action=dim-comment&id=2&dimClass=unapproved&new=approved"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 81", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit-comments.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203365"], "body": "_ajax_nonce=575b959a1d&action=dim-comment&id=2&dimClass=unapproved&new=unapproved"}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 358", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: */*", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit-comments.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203369"], "body": "newcomment_author=&newcomment_author_email=&newcomment_author_url=&action=replyto-comment&comment_ID=2&comment_post_ID=1&status=&position=-1&checkbox=1&mode=detail&_ajax_nonce-replyto-comment=465b2dff40&_wp_unfiltered_html_comment=8f43bb2d1f&content=Thanks%2C+Jo!+Try+%60ls+-la%60+and+%3Cb%3Ethen%3C%2Fb%3E+restart.&id=1&comments_listing=all&approve_parent=1"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/comment.php?action=editcomment&c=2", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203369"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/comment.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 613", "Upgrade-Insecure-Requests: 1", "Content-Type: application/x-www-form-urlencoded", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Origin: http://blog.example", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/comment.php?action=editcomment&c=2", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203373"], "body": "_wpnonce=e9770a5628&_wp_http_referer=%2Fwp-admin%2Fcomment.php%3Faction%3Deditcomment%26c%3D2&action=editedcomment&comment_ID=2&comment_post_ID=1&newcomment_author=Jo+Reader&newcomment_author_email=jo%40example.com&newcomment_author_url=https%3A%2F%2Fexample.org%2F&content=An+edited+comment%2C+it%27s+about+select+wines.&closedpostboxesnonce=b39bd4c73a&comment_status=1&mm=11&jj=09&aa=2026&hh=05&mn=45&ss=44&hidden_mm=11&cur_mm=11&hidden_jj=09&cur_jj=09&hidden_aa=2026&cur_aa=2026&hidden_hh=05&cur_hh=05&hidden_mn=45&cur_mn=49&comment_parent=0&save=Update&c=2&p=1&referredby=&_wp_original_http_referer=&noredir=1"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit-comments.php?p=1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/comment.php?action=editcomment&c=2", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203373"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=23&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203386"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-admin/admin-ajax.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 263", "X-Requested-With: XMLHttpRequest", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, text/javascript, */*; q=0.01", "Content-Type: application/x-www-form-urlencoded; charset=UTF-8", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/edit.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203393"], "body": "data%5Bwp-check-locked-posts%5D%5B%5D=post-10&data%5Bwp-check-locked-posts%5D%5B%5D=post-16&data%5Bwp-check-locked-posts%5D%5B%5D=post-3&data%5Bwp-check-locked-posts%5D%5B%5D=post-2&interval=10&_nonce=f06ef15ba2&action=heartbeat&screen_id=edit-page&has_focus=true"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/comments?context=edit&post=24&type=note&status=all&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/post-new.php?post_type=page", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/botany-flowers-closeup.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/red-hibiscus-closeup.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/grid-flower-2.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/campanula-alliariifolia-flower.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-content/themes/twentytwentyfive/assets/images/delphinium-flowers.webp", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: image/jxl,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/template-parts/twentytwentyfive//header?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/template-parts/twentytwentyfive//footer?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?context=edit&offset=0&order=desc&orderby=date&per_page=3&ignore_sticky=false&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?context=edit&offset=0&order=desc&orderby=date&per_page=12&ignore_sticky=false&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/menus?context=view&per_page=100&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp-block-editor/v1/navigation-fallback?_embed=true&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/types/post?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/navigation?context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: b40ef802e6", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?customize_changeset_uuid=f8b37173-205c-47cb-8499-41107f2fbe14&customize_theme=twentytwentyfive&customize_messenger_channel=preview-0", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/customize.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203401"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/users/me/application-passwords?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 28", "X-WP-Nonce: b40ef802e6", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: application/json, */*;q=0.1", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/profile.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432"], "body": "{\"name\":\"Example phone app\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-json/", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?per_page=5&search=hello", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/posts", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "content-type: application/json", "content-length: 77", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": "{\"title\": \"From the app\", \"content\": \"<p>It's a test</p>\", \"status\": \"draft\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/pages?slug=sample-page", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/users/me?context=edit", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/comments", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "content-type: application/json", "content-length: 102", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": "{\"post\": 1, \"content\": \"A note from the app\", \"author_name\": \"Bob\", \"author_email\": \"bob@example.com\"}"}
|
||||||
|
{"method": "GET", "target": "/?rest_route=/wp/v2/posts&per_page=2", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fblog.example%2Fhello-world%2F", "headers": ["user-agent: ExamplePublisher/1.0", "accept: */*", "accept-encoding: gzip,deflate,br", "Authorization: Basic ZWRpdG9yMTphYmNkIGVmZ2ggaWprbCBtbm9wIHFyc3QgdXZ3eA==", "cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203432", "Host: blog.example", "Connection: keep-alive"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-login.php?action=logout&_wpnonce=e9a74137b6", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794203454"], "body": ""}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/templates/twentytwentyfive//index?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 169", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207357"], "body": "{\"id\":\"twentytwentyfive//index\",\"content\":\"<!-- wp:template-part {\\\"slug\\\":\\\"header\\\"} /-->\\n\\n<!-- wp:paragraph -->\\n<p>Our opening hours.</p>\\n<!-- /wp:paragraph -->\"}"}
|
||||||
|
{"method": "POST", "target": "/wp-json/wp/v2/template-parts/twentytwentyfive//header?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 170", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/site-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207357"], "body": "{\"id\":\"twentytwentyfive//header\",\"content\":\"<!-- wp:template-part {\\\"slug\\\":\\\"header\\\"} /-->\\n\\n<!-- wp:paragraph -->\\n<p>Our opening hours.</p>\\n<!-- /wp:paragraph -->\"}"}
|
||||||
|
{"method": "POST", "target": "/index.php?rest_route=%2Fwp%2Fv2%2Fposts%2F12&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 590", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207411"], "body": "{\"id\":12,\"title\":\"A guide to the plain address\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\",\"status\":\"draft\"}"}
|
||||||
|
{"method": "POST", "target": "/index.php?rest_route=%2Fwp%2Fv2%2Fposts%2F12&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 553", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=12&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207411"], "body": "{\"id\":12,\"status\":\"publish\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\"}"}
|
||||||
|
{"method": "POST", "target": "/index.php/wp-json/wp/v2/posts/14?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 590", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207416"], "body": "{\"id\":14,\"title\":\"A guide to the index address\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\",\"status\":\"draft\"}"}
|
||||||
|
{"method": "POST", "target": "/index.php/wp-json/wp/v2/posts/14?_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "Content-Length: 553", "X-WP-Nonce: c799cf7667", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-HTTP-Method-Override: PUT", "Content-Type: application/json", "Origin: http://blog.example", "Referer: http://blog.example/wp-admin/post.php?post=14&action=edit", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207416"], "body": "{\"id\":14,\"status\":\"publish\",\"content\":\"<!-- wp:paragraph -->\\n<p>It's a post about the Union station and how to select a table from the catalog & more. Visit <a href=\\\"https://example.com/a?b=1&c=2\\\">the page</a>.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:code -->\\n<pre class=\\\"wp-block-code\\\"><code>curl -s https://example.org/install | sh\\ncat /etc/hosts</code></pre>\\n<!-- /wp:code -->\\n\\n<!-- wp:html -->\\n<iframe src=\\\"https://example.org/embed\\\" onload=\\\"console.log('ok')\\\"></iframe>\\n<script>document.title = 'x';</script>\\n<!-- /wp:html -->\"}"}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?file=akismet%2Fviews%2Fconfig.php&plugin=akismet%2Fakismet.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?file=example-plugin%2Fbin%2Finstall.sh&plugin=example-plugin%2Fexample-plugin.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207404"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-editor.php?file=example-plugin%2Fdocker-compose.yml&plugin=example-plugin%2Fexample-plugin.php", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207406"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/theme-editor.php?file=inc%2Fconfig.php&theme=example-theme", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-editor.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207407"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=python3", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207357"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/index.php?s=python3", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207357"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=python3&post_status=all&post_type=post&_wpnonce=3a4f1df05d&_wp_http_referer=%2Fwp-admin%2Fedit.php&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207365"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=python3&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207365"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter=&s=python3&_wpnonce=f27c858c25&_wp_http_referer=%2Fwp-admin%2Fupload.php%3Fmode%3Dlist&action=-1&affected=&_ajax_nonce=a654b3ca7f&ps=", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207366"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter&s=python3&action=-1&affected&_ajax_nonce=a654b3ca7f&ps", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207366"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=python3&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-install.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207366"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=powershell", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207368"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/index.php?s=powershell", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207368"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=powershell&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207373"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter&s=powershell&action=-1&affected&_ajax_nonce=a654b3ca7f&ps", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207375"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=powershell&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-install.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207375"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=sudo+apt+install+nginx", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207378"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/index.php?s=sudo+apt+install+nginx", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207378"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=sudo+apt+install+nginx&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207383"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter&s=sudo+apt+install+nginx&action=-1&affected&_ajax_nonce=a654b3ca7f&ps", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207384"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=sudo+apt+install+nginx&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-install.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207385"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=chmod+%2Bx", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207386"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/index.php?s=chmod+%2Bx", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207386"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=chmod+%2Bx&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207390"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter&s=chmod+%2Bx&action=-1&affected&_ajax_nonce=a654b3ca7f&ps", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207391"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=chmod+%2Bx&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-install.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207391"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/?s=ls+-la", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/index.php?s=ls+-la", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207394"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/edit.php?s=ls+-la&post_status=all&post_type=post&action=-1&m=0&cat=0&paged=1&action2=-1", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/edit.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207397"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/upload.php?mode=list&attachment-filter&s=ls+-la&action=-1&affected&_ajax_nonce=a654b3ca7f&ps", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/upload.php?mode=list", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207398"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-admin/plugin-install.php?s=ls+-la&tab=search&type=term", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Referer: http://blog.example/wp-admin/plugin-install.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207399"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=python3&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?search=python3&per_page=20&context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=powershell&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?search=powershell&per_page=20&context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=sudo%20apt%20install%20nginx&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?search=sudo%20apt%20install%20nginx&per_page=20&context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=chmod%20%2Bx&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?search=chmod%20%2Bx&per_page=20&context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/search?search=ls%20-la&per_page=20&type=post&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-json/wp/v2/posts?search=ls%20-la&per_page=20&context=edit&_locale=user", "headers": ["Host: blog.example", "Connection: keep-alive", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36", "Accept: application/json, */*;q=0.1", "X-WP-Nonce: c799cf7667", "Referer: http://blog.example/wp-admin/post-new.php", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_8f08caa83939d4856f3c9b1fa17104b4=editor1%7C1893456000%7Cabcdefghijklmnopqrstuvwxyz0123456789ABCDEFG%7C0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef; wp-settings-time-1=1794207402"], "body": ""}
|
||||||
|
{"method": "GET", "target": "/wp-login.php?loggedout=true&wp_lang=en_US", "headers": ["Host: blog.example", "Connection: keep-alive", "Upgrade-Insecure-Requests: 1", "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/jxl,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding: gzip, deflate", "Cookie: wordpress_test_cookie=WP%20Cookie%20check"], "body": ""}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// Package coreruleset runs the OWASP Core Rule Set 4.25.0, through Coraza, on the
|
// Package waf runs the OWASP Core Rule Set 4.25.0, through Coraza, on the
|
||||||
// method, the URL with its query and the headers of a request, and on its
|
// method, the URL with its query and the headers of a request, and on its
|
||||||
// body while SWW_WAF_BODY_LIMIT is set, with the eight changes sww
|
// body while SWW_WAF_BODY_LIMIT is set, with the nine changes sww
|
||||||
// makes to it and the exclusions in SWW_CORE_RULE_SET_EXCLUSIONS_FILE, as
|
// makes to it and the exclusions in SWW_CORE_RULE_SET_EXCLUSIONS_FILE, as
|
||||||
// "Attack detection" under "Settings" in SPEC.md describes them. It reads no
|
// "Attack detection" under "Settings" in SPEC.md describes them. It reads no
|
||||||
// response.
|
// response.
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
// its no_fs_access tag, as the Dockerfile and script/build build it: of a
|
// its no_fs_access tag, as the Dockerfile and script/build build it: of a
|
||||||
// file in a multipart body, Coraza then counts the bytes instead of
|
// file in a multipart body, Coraza then counts the bytes instead of
|
||||||
// writing them to the system's temporary directory.
|
// writing them to the system's temporary directory.
|
||||||
package coreruleset
|
package waf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
@@ -32,8 +32,8 @@ import (
|
|||||||
|
|
||||||
// directives are the Core Rule Set as sww runs it, with the
|
// directives are the Core Rule Set as sww runs it, with the
|
||||||
// paranoia level for %d, bodyDirectives for the first %s while
|
// paranoia level for %d, bodyDirectives for the first %s while
|
||||||
// SWW_WAF_BODY_LIMIT is set, the exclusions file for the second, and
|
// SWW_WAF_BODY_LIMIT is set, the exclusions file for the second,
|
||||||
// giteaExclusions for the third.
|
// giteaExclusions for the third, and wordpressExclusions for the fourth.
|
||||||
// Each rule sww adds has an id from 900000 to 900999, the ids the
|
// Each rule sww adds has an id from 900000 to 900999, the ids the
|
||||||
// Core Rule Set keeps for the rules that set it up, which
|
// Core Rule Set keeps for the rules that set it up, which
|
||||||
// SWW_WAF_DISABLED_RULES and the exclusions file refuse, so that no
|
// SWW_WAF_DISABLED_RULES and the exclusions file refuse, so that no
|
||||||
@@ -84,6 +84,9 @@ SecRule ARGUMENTS_LIMIT_REACHED "@eq 1" "id:900300,phase:2,pass,\
|
|||||||
# The eighth change comes before the rules for the same reason.
|
# The eighth change comes before the rules for the same reason.
|
||||||
%s
|
%s
|
||||||
|
|
||||||
|
# The ninth change comes before the rules for the same reason.
|
||||||
|
%s
|
||||||
|
|
||||||
# The sixth: only the rules for requests are loaded, and no response is
|
# The sixth: only the rules for requests are loaded, and no response is
|
||||||
# inspected.
|
# inspected.
|
||||||
Include @owasp_crs/REQUEST-*.conf
|
Include @owasp_crs/REQUEST-*.conf
|
||||||
@@ -175,6 +178,13 @@ SecRule MULTIPART_STRICT_ERROR "!@eq 0" "id:900450,phase:2,pass,\
|
|||||||
//go:embed gitea.conf
|
//go:embed gitea.conf
|
||||||
var giteaExclusions string
|
var giteaExclusions string
|
||||||
|
|
||||||
|
// wordpressExclusions are the ninth change: the fields of WordPress's own
|
||||||
|
// requests that skip the rules that refused them there, as Coraza
|
||||||
|
// directives.
|
||||||
|
//
|
||||||
|
//go:embed wordpress.conf
|
||||||
|
var wordpressExclusions string
|
||||||
|
|
||||||
// cookiesNotRead are the cookies the Core Rule Set reads a request
|
// cookiesNotRead are the cookies the Core Rule Set reads a request
|
||||||
// without, the rest of the fifth change.
|
// without, the rest of the fifth change.
|
||||||
//
|
//
|
||||||
@@ -288,7 +298,7 @@ type CoreRuleSet struct {
|
|||||||
bodyLimit int64
|
bodyLimit int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns the Core Rule Set with the eight changes, at params'
|
// New returns the Core Rule Set with the nine changes, at params'
|
||||||
// paranoia level, without the rules it switches off, reading request
|
// paranoia level, without the rules it switches off, reading request
|
||||||
// bodies up to params' limit, and with params' exclusions file loaded
|
// bodies up to params' limit, and with params' exclusions file loaded
|
||||||
// before the Core Rule Set's rules. An exclusions file is an error if it
|
// before the Core Rule Set's rules. An exclusions file is an error if it
|
||||||
@@ -316,7 +326,7 @@ func New(params Params) (*CoreRuleSet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
text := fmt.Sprintf(directives, params.ParanoiaLevel, body, exclusions,
|
text := fmt.Sprintf(directives, params.ParanoiaLevel, body, exclusions,
|
||||||
giteaExclusions)
|
giteaExclusions, wordpressExclusions)
|
||||||
|
|
||||||
if len(params.DisabledRules) > 0 {
|
if len(params.DisabledRules) > 0 {
|
||||||
ids := make([]string, len(params.DisabledRules))
|
ids := make([]string, len(params.DisabledRules))
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package coreruleset_test
|
package waf_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@@ -12,7 +13,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"sneak.berlin/go/smallwebwaf/internal/coreruleset"
|
"sneak.berlin/go/smallwebwaf/internal/waf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// defaultDisabledRules are the rules SWW_WAF_DISABLED_RULES switches off
|
// defaultDisabledRules are the rules SWW_WAF_DISABLED_RULES switches off
|
||||||
@@ -23,12 +24,10 @@ var defaultDisabledRules = []int{920340, 920420, 920440, 920640, 930130, 930140}
|
|||||||
|
|
||||||
// newCoreRuleSet returns the Core Rule Set at paranoia level level, with
|
// newCoreRuleSet returns the Core Rule Set at paranoia level level, with
|
||||||
// the rules in disabled switched off.
|
// the rules in disabled switched off.
|
||||||
func newCoreRuleSet(t *testing.T, level int, disabled ...int) *coreruleset.CoreRuleSet {
|
func newCoreRuleSet(t *testing.T, level int, disabled ...int) *waf.CoreRuleSet {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
crs, err := coreruleset.New(coreruleset.Params{
|
crs, err := waf.New(waf.Params{ParanoiaLevel: level, DisabledRules: disabled})
|
||||||
ParanoiaLevel: level, DisabledRules: disabled,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("load the Core Rule Set: %v", err)
|
t.Fatalf("load the Core Rule Set: %v", err)
|
||||||
}
|
}
|
||||||
@@ -51,7 +50,7 @@ func get(target string, headers ...string) request {
|
|||||||
|
|
||||||
// inspect returns what crs finds in r, sent to git.example by a browser,
|
// inspect returns what crs finds in r, sent to git.example by a browser,
|
||||||
// whose Host, User-Agent and Accept r.headers may replace.
|
// whose Host, User-Agent and Accept r.headers may replace.
|
||||||
func inspect(t *testing.T, crs *coreruleset.CoreRuleSet, r request) coreruleset.Result {
|
func inspect(t *testing.T, crs *waf.CoreRuleSet, r request) waf.Result {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
result, _ := inspectBody(t, crs, r, "")
|
result, _ := inspectBody(t, crs, r, "")
|
||||||
@@ -62,8 +61,8 @@ func inspect(t *testing.T, crs *coreruleset.CoreRuleSet, r request) coreruleset.
|
|||||||
// inspectBody is inspect for r with body, which is announced with its
|
// inspectBody is inspect for r with body, which is announced with its
|
||||||
// Content-Length unless it is "", and returns what crs read of body too.
|
// Content-Length unless it is "", and returns what crs read of body too.
|
||||||
func inspectBody(
|
func inspectBody(
|
||||||
t *testing.T, crs *coreruleset.CoreRuleSet, r request, body string,
|
t *testing.T, crs *waf.CoreRuleSet, r request, body string,
|
||||||
) (coreruleset.Result, string) {
|
) (waf.Result, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
req := httptest.NewRequestWithContext(t.Context(), r.method,
|
req := httptest.NewRequestWithContext(t.Context(), r.method,
|
||||||
@@ -98,9 +97,7 @@ func inspectBody(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wantResult checks what crs finds in r.
|
// wantResult checks what crs finds in r.
|
||||||
func wantResult(
|
func wantResult(t *testing.T, crs *waf.CoreRuleSet, r request, want waf.Result) {
|
||||||
t *testing.T, crs *coreruleset.CoreRuleSet, r request, want coreruleset.Result,
|
|
||||||
) {
|
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
if got := inspect(t, crs, r); !reflect.DeepEqual(got, want) {
|
if got := inspect(t, crs, r); !reflect.DeepEqual(got, want) {
|
||||||
@@ -110,29 +107,28 @@ func wantResult(
|
|||||||
|
|
||||||
// matched is the result of a request that the rules ids match, each of
|
// matched is the result of a request that the rules ids match, each of
|
||||||
// them a critical one, which adds 5 to the score.
|
// them a critical one, which adds 5 to the score.
|
||||||
func matched(ids ...int) coreruleset.Result {
|
func matched(ids ...int) waf.Result {
|
||||||
const critical = 5
|
const critical = 5
|
||||||
|
|
||||||
return coreruleset.Result{RuleIDs: ids, Score: critical * len(ids)}
|
return waf.Result{RuleIDs: ids, Score: critical * len(ids)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// atDefaults returns the Core Rule Set as sww runs it by default.
|
// atDefaults returns the Core Rule Set as sww runs it by default.
|
||||||
func atDefaults(t *testing.T) *coreruleset.CoreRuleSet {
|
func atDefaults(t *testing.T) *waf.CoreRuleSet {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
return newCoreRuleSet(t, 1, defaultDisabledRules...)
|
return newCoreRuleSet(t, 1, defaultDisabledRules...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// wantChange checks that crs lets through passes, a gitea request one of
|
// wantChange checks that crs lets through passes, a request one of the
|
||||||
// the eight changes is for, and still finds result in refused, a request
|
// nine changes is for, and still finds result in refused, a request like
|
||||||
// like it that the change is not for.
|
// it that the change is not for.
|
||||||
func wantChange(
|
func wantChange(
|
||||||
t *testing.T, crs *coreruleset.CoreRuleSet, passes, refused request,
|
t *testing.T, crs *waf.CoreRuleSet, passes, refused request, result waf.Result,
|
||||||
result coreruleset.Result,
|
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
wantResult(t, crs, passes, coreruleset.Result{})
|
wantResult(t, crs, passes, waf.Result{})
|
||||||
wantResult(t, crs, refused, result)
|
wantResult(t, crs, refused, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,12 +163,12 @@ func TestExpectAndContentEncodingAreAllowed(t *testing.T) {
|
|||||||
|
|
||||||
wantResult(t, crs,
|
wantResult(t, crs,
|
||||||
request{http.MethodPost, push, []string{pushType, length, "Expect: 100-continue"}},
|
request{http.MethodPost, push, []string{pushType, length, "Expect: 100-continue"}},
|
||||||
coreruleset.Result{})
|
waf.Result{})
|
||||||
wantResult(t, crs,
|
wantResult(t, crs,
|
||||||
request{http.MethodPost, fetch, []string{
|
request{http.MethodPost, fetch, []string{
|
||||||
fetchType, length, "Content-Encoding: gzip",
|
fetchType, length, "Content-Encoding: gzip",
|
||||||
}},
|
}},
|
||||||
coreruleset.Result{})
|
waf.Result{})
|
||||||
|
|
||||||
// Every other header on the Core Rule Set's list stays refused.
|
// Every other header on the Core Rule Set's list stays refused.
|
||||||
for _, header := range []string{
|
for _, header := range []string{
|
||||||
@@ -201,7 +197,7 @@ func TestTransferEncodingIsRead(t *testing.T) {
|
|||||||
"Content-Type: application/x-git-receive-pack-request",
|
"Content-Type: application/x-git-receive-pack-request",
|
||||||
"Transfer-Encoding: chunked",
|
"Transfer-Encoding: chunked",
|
||||||
}},
|
}},
|
||||||
coreruleset.Result{})
|
waf.Result{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMoreParametersThanCorazaKeepsIsAMatch(t *testing.T) {
|
func TestMoreParametersThanCorazaKeepsIsAMatch(t *testing.T) {
|
||||||
@@ -255,7 +251,7 @@ func TestParametersGiteaSendsNamesInSkipTheListsOfFilesPathsAndCommands(t *testi
|
|||||||
for _, value := range []struct {
|
for _, value := range []struct {
|
||||||
name string
|
name string
|
||||||
// result is what a parameter that is not one of gitea's gets.
|
// result is what a parameter that is not one of gitea's gets.
|
||||||
result coreruleset.Result
|
result waf.Result
|
||||||
}{
|
}{
|
||||||
// A file on the list of system files.
|
// A file on the list of system files.
|
||||||
{".gitignore", matched(930120)},
|
{".gitignore", matched(930120)},
|
||||||
@@ -276,7 +272,7 @@ func TestParametersGiteaSendsNamesInSkipTheListsOfFilesPathsAndCommands(t *testi
|
|||||||
wantChange(t, crs, get("/?path=|cat%20/etc/passwd"), get("/?q=|cat%20/etc/passwd"),
|
wantChange(t, crs, get("/?path=|cat%20/etc/passwd"), get("/?q=|cat%20/etc/passwd"),
|
||||||
matched(930120, 932160))
|
matched(930120, 932160))
|
||||||
wantResult(t, crs, get("/?path=../../etc/passwd"),
|
wantResult(t, crs, get("/?path=../../etc/passwd"),
|
||||||
coreruleset.Result{RuleIDs: []int{930100, 930110}, Score: 20})
|
waf.Result{RuleIDs: []int{930100, 930110}, Score: 20})
|
||||||
wantResult(t, crs, get("/?path=1'%20OR%20'1'='1"), matched(942100))
|
wantResult(t, crs, get("/?path=1'%20OR%20'1'='1"), matched(942100))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +342,7 @@ func TestEmptyHeaderIsRead(t *testing.T) {
|
|||||||
|
|
||||||
// An empty User-Agent is a notice, which adds 2.
|
// An empty User-Agent is a notice, which adds 2.
|
||||||
wantResult(t, atDefaults(t), get("/", "User-Agent: "),
|
wantResult(t, atDefaults(t), get("/", "User-Agent: "),
|
||||||
coreruleset.Result{RuleIDs: []int{920330}, Score: 2})
|
waf.Result{RuleIDs: []int{920330}, Score: 2})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParanoiaLevel(t *testing.T) {
|
func TestParanoiaLevel(t *testing.T) {
|
||||||
@@ -355,7 +351,7 @@ func TestParanoiaLevel(t *testing.T) {
|
|||||||
// Accept-Charset is refused from paranoia level 2.
|
// Accept-Charset is refused from paranoia level 2.
|
||||||
r := get("/", "Accept-Charset: utf-8")
|
r := get("/", "Accept-Charset: utf-8")
|
||||||
|
|
||||||
wantResult(t, newCoreRuleSet(t, 1), r, coreruleset.Result{})
|
wantResult(t, newCoreRuleSet(t, 1), r, waf.Result{})
|
||||||
wantResult(t, newCoreRuleSet(t, 2), r, matched(920451))
|
wantResult(t, newCoreRuleSet(t, 2), r, matched(920451))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,8 +363,8 @@ func TestEachDisabledRuleIsSwitchedOff(t *testing.T) {
|
|||||||
r := request{http.MethodTrace, "/", []string{"Host: 192.0.2.1"}}
|
r := request{http.MethodTrace, "/", []string{"Host: 192.0.2.1"}}
|
||||||
|
|
||||||
wantResult(t, newCoreRuleSet(t, 1), r,
|
wantResult(t, newCoreRuleSet(t, 1), r,
|
||||||
coreruleset.Result{RuleIDs: []int{911100, 920350}, Score: 8})
|
waf.Result{RuleIDs: []int{911100, 920350}, Score: 8})
|
||||||
wantResult(t, newCoreRuleSet(t, 1, 920350, 911100), r, coreruleset.Result{})
|
wantResult(t, newCoreRuleSet(t, 1, 920350, 911100), r, waf.Result{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImagePushThatReusesALayerIsNotCheckedForCommandNames(t *testing.T) {
|
func TestImagePushThatReusesALayerIsNotCheckedForCommandNames(t *testing.T) {
|
||||||
@@ -388,8 +384,8 @@ func TestImagePushThatReusesALayerIsNotCheckedForCommandNames(t *testing.T) {
|
|||||||
|
|
||||||
// withExclusions returns the Core Rule Set at the defaults, with the
|
// withExclusions returns the Core Rule Set at the defaults, with the
|
||||||
// exclusions file at path.
|
// exclusions file at path.
|
||||||
func withExclusions(path string) (*coreruleset.CoreRuleSet, error) {
|
func withExclusions(path string) (*waf.CoreRuleSet, error) {
|
||||||
return coreruleset.New(coreruleset.Params{
|
return waf.New(waf.Params{
|
||||||
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, ExclusionsFile: path,
|
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, ExclusionsFile: path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -427,7 +423,7 @@ func TestExclusionsFileIsLoadedBeforeTheRules(t *testing.T) {
|
|||||||
func TestRuleSwitchedOffAndNamedInTheExclusionsFileIsOff(t *testing.T) {
|
func TestRuleSwitchedOffAndNamedInTheExclusionsFileIsOff(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
crs, err := coreruleset.New(coreruleset.Params{
|
crs, err := waf.New(waf.Params{
|
||||||
ParanoiaLevel: 1, DisabledRules: []int{920500},
|
ParanoiaLevel: 1, DisabledRules: []int{920500},
|
||||||
ExclusionsFile: exclusionsFile(t, backupFileExclusion),
|
ExclusionsFile: exclusionsFile(t, backupFileExclusion),
|
||||||
})
|
})
|
||||||
@@ -435,7 +431,7 @@ func TestRuleSwitchedOffAndNamedInTheExclusionsFileIsOff(t *testing.T) {
|
|||||||
t.Fatalf("load the exclusions: %v", err)
|
t.Fatalf("load the exclusions: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wantResult(t, crs, get("/notes.txt~"), coreruleset.Result{})
|
wantResult(t, crs, get("/notes.txt~"), waf.Result{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExclusionsFileMayNameAnyNumberInAComment(t *testing.T) {
|
func TestExclusionsFileMayNameAnyNumberInAComment(t *testing.T) {
|
||||||
@@ -555,6 +551,260 @@ func TestOrdinaryGiteaRequestsPassAndAttacksAreRefused(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wpLogin is WordPress's sign-in path.
|
||||||
|
const wpLogin = "/wp-login.php"
|
||||||
|
|
||||||
|
// recordedRequest is a line of a file of recorded requests in testdata.
|
||||||
|
type recordedRequest struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Target string `json:"target"`
|
||||||
|
Headers []string `json:"headers"`
|
||||||
|
Body string `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// wordpressRequests returns the recorded ordinary WordPress requests in
|
||||||
|
// testdata, each with its body.
|
||||||
|
func wordpressRequests(t *testing.T) []recordedRequest {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
text, err := os.ReadFile(filepath.Join("testdata", "wordpress-requests.txt"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var requests []recordedRequest
|
||||||
|
|
||||||
|
for line := range strings.Lines(string(text)) {
|
||||||
|
if strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var r recordedRequest
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(line), &r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%q: %v", line, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
requests = append(requests, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return requests
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingBodiesUpTo64K returns the Core Rule Set as sww runs it by default,
|
||||||
|
// but reading bodies up to the largest SWW_WAF_BODY_LIMIT.
|
||||||
|
func readingBodiesUpTo64K(t *testing.T) *waf.CoreRuleSet {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
crs, err := waf.New(waf.Params{
|
||||||
|
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: 64<<10 - 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("load the Core Rule Set: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return crs
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrdinaryWordPressRequestsPassAndAttacksAreRefused(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const threshold = 5 // SWW_WAF_ANOMALY_THRESHOLD's default
|
||||||
|
|
||||||
|
defaults, bodies := atDefaults(t), readingBodiesUpTo64K(t)
|
||||||
|
|
||||||
|
for _, recorded := range wordpressRequests(t) {
|
||||||
|
r := request{recorded.Method, recorded.Target, recorded.Headers}
|
||||||
|
|
||||||
|
crsSets := []*waf.CoreRuleSet{defaults}
|
||||||
|
if recorded.Body != "" {
|
||||||
|
crsSets = append(crsSets, bodies)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, crs := range crsSets {
|
||||||
|
got, _ := inspectBody(t, crs, r, recorded.Body)
|
||||||
|
if got.Score >= threshold {
|
||||||
|
t.Errorf("%s %s %.200q refused: %+v", r.method, r.target, recorded.Body, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, attack := range []string{
|
||||||
|
"1'%20OR%20'1'='1",
|
||||||
|
"..%2F..%2Fwp-config.php",
|
||||||
|
"%3Cscript%3Ealert(1)%3C%2Fscript%3E",
|
||||||
|
} {
|
||||||
|
for _, target := range []string{
|
||||||
|
"/?id=" + attack,
|
||||||
|
wpLogin + "?id=" + attack,
|
||||||
|
"/wp-admin/admin-ajax.php?id=" + attack,
|
||||||
|
"/wp-json/wp/v2/posts?id=" + attack,
|
||||||
|
// In the fields whose searches and file names skip some rules.
|
||||||
|
"/?s=" + attack,
|
||||||
|
"/index.php?s=" + attack,
|
||||||
|
"/wp-admin/edit.php?s=" + attack,
|
||||||
|
"/wp-admin/upload.php?s=" + attack,
|
||||||
|
"/wp-admin/plugin-install.php?s=" + attack,
|
||||||
|
"/wp-json/wp/v2/search?search=" + attack,
|
||||||
|
"/wp-json/wp/v2/posts?search=" + attack,
|
||||||
|
"/wp-admin/plugin-editor.php?file=" + attack,
|
||||||
|
"/wp-admin/theme-editor.php?file=" + attack,
|
||||||
|
} {
|
||||||
|
if got := inspect(t, defaults, get(target)); got.Score < threshold {
|
||||||
|
t.Errorf("%s let through: %+v", target, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In a body field no exclusion names, on the paths with exclusions.
|
||||||
|
body := "id=" + attack
|
||||||
|
for _, target := range []string{
|
||||||
|
wpLogin,
|
||||||
|
"/wp-comments-post.php",
|
||||||
|
"/wp-admin/admin-ajax.php",
|
||||||
|
"/wp-admin/post.php",
|
||||||
|
"/wp-admin/options.php",
|
||||||
|
} {
|
||||||
|
got, _ := inspectBody(t, bodies,
|
||||||
|
request{http.MethodPost, target, []string{formData}}, body)
|
||||||
|
if got.Score < threshold {
|
||||||
|
t.Errorf("POST %s %q let through: %+v", target, body, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wordpressBlock is the comment that starts every block of WordPress's
|
||||||
|
// HTML, which rule 941180 matches.
|
||||||
|
const wordpressBlock = "<!-- wp:paragraph -->"
|
||||||
|
|
||||||
|
// wordpressOverride is the header with which the block editor saves.
|
||||||
|
const wordpressOverride = "X-HTTP-Method-Override: PUT"
|
||||||
|
|
||||||
|
// wordpressRESTAddresses returns the addresses of route on the REST API,
|
||||||
|
// one for each permalink setting.
|
||||||
|
func wordpressRESTAddresses(route string) []string {
|
||||||
|
return []string{
|
||||||
|
"/wp-json" + route,
|
||||||
|
"/index.php/wp-json" + route,
|
||||||
|
"/index.php?rest_route=" + route,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWordPressExclusionsFollowEveryRESTAddress(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
crs := readingBodiesUpTo64K(t)
|
||||||
|
content := `{"content":"` + wordpressBlock + `"}`
|
||||||
|
|
||||||
|
for _, route := range []string{
|
||||||
|
"/wp/v2/posts/1",
|
||||||
|
"/wp/v2/posts/1/autosaves",
|
||||||
|
"/wp/v2/pages/2",
|
||||||
|
"/wp/v2/templates/twentytwentyfive//index",
|
||||||
|
"/wp/v2/template-parts/twentytwentyfive//header",
|
||||||
|
} {
|
||||||
|
for _, address := range wordpressRESTAddresses(route) {
|
||||||
|
r := request{http.MethodPost, address, []string{jsonBody, wordpressOverride}}
|
||||||
|
wantBody(t, crs, r, content, waf.Result{}, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The routes that save something else keep the rules.
|
||||||
|
for _, route := range []string{
|
||||||
|
"/wp/v2/comments", "/wp/v2/users/1", "/wp/v2/settings",
|
||||||
|
} {
|
||||||
|
for _, address := range wordpressRESTAddresses(route) {
|
||||||
|
r := request{http.MethodPost, address, []string{jsonBody}}
|
||||||
|
wantBody(t, crs, r, content, matched(941180), content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WordPress follows a route in the query over one in the path.
|
||||||
|
r := request{
|
||||||
|
http.MethodPost, "/wp-json/wp/v2/posts/1?rest_route=/wp/v2/comments",
|
||||||
|
[]string{jsonBody},
|
||||||
|
}
|
||||||
|
wantBody(t, crs, r, content, matched(941180), content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWordPressSearchesAndFileNamesAreExcludedOnlyThere(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
crs := atDefaults(t)
|
||||||
|
|
||||||
|
wantChange(t, crs, get("/?s=python3"), get("/wp-admin/options.php?s=python3"),
|
||||||
|
matched(932260))
|
||||||
|
wantChange(t, crs, get("/?s=python3"), get("/?q=python3"), matched(932260))
|
||||||
|
wantChange(t, crs, get("/index.php?s=ls+-la"), get("/index.php?q=ls+-la"),
|
||||||
|
matched(932250))
|
||||||
|
wantChange(t, crs, get("/wp-json/wp/v2/search?search=powershell"),
|
||||||
|
get("/wp-json/wp/v2/comments?search=powershell"), matched(932120))
|
||||||
|
wantChange(t, crs, get("/index.php?rest_route=/wp/v2/search&search=powershell"),
|
||||||
|
get("/index.php?rest_route=/wp/v2/comments&search=powershell"), matched(932120))
|
||||||
|
wantChange(t, crs,
|
||||||
|
get("/wp-admin/plugin-editor.php?file=akismet%2Fviews%2Fconfig.php"),
|
||||||
|
get("/wp-admin/options.php?file=akismet%2Fviews%2Fconfig.php"), matched(930120))
|
||||||
|
wantChange(t, crs, get("/wp-admin/theme-editor.php?file=docker-compose.yml"),
|
||||||
|
get("/wp-admin/theme-editor.php?theme=docker-compose.yml"), matched(932260))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWordPressBodyFieldsAreCheckedInTheQuery(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
crs := atDefaults(t)
|
||||||
|
|
||||||
|
wantResult(t, crs, get(wpLogin+"?pwd=%2Fetc%2Fhosts"), matched(930120))
|
||||||
|
wantResult(t, crs, get(wpLogin+"?PWD=%2Fetc%2Fhosts"), matched(930120))
|
||||||
|
wantResult(t, crs, get("/wp-admin/admin-ajax.php?content=ls+-la"), matched(932250))
|
||||||
|
wantResult(t, crs, get("/wp-admin/admin-ajax.php?newcontent=%3Cstyle%3E"),
|
||||||
|
matched(941100, 941160))
|
||||||
|
wantResult(t, crs,
|
||||||
|
get("/wp-json/wp/v2/posts/1?json.content="+url.QueryEscape(wordpressBlock)),
|
||||||
|
matched(941180))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWordPressExclusionsAreNarrow(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const (
|
||||||
|
save = "/wp-json/wp/v2/posts/1"
|
||||||
|
offREST = "/api/posts/1"
|
||||||
|
length = "Content-Length: 2"
|
||||||
|
)
|
||||||
|
|
||||||
|
crs := readingBodiesUpTo64K(t)
|
||||||
|
saving := request{http.MethodPost, save, []string{jsonBody, wordpressOverride}}
|
||||||
|
|
||||||
|
content := `{"content":"` + wordpressBlock + `"}`
|
||||||
|
wantBody(t, crs, saving, content, waf.Result{}, content)
|
||||||
|
|
||||||
|
// The other fields of the post keep the rule, and so does the same field
|
||||||
|
// off the REST API.
|
||||||
|
title := `{"title":"` + wordpressBlock + `"}`
|
||||||
|
wantBody(t, crs, saving, title, matched(941180), title)
|
||||||
|
wantBody(t, crs, request{http.MethodPost, offREST, []string{jsonBody}}, content,
|
||||||
|
matched(941180), content)
|
||||||
|
|
||||||
|
// The header X-HTTP-Method-Override is refused off the REST API.
|
||||||
|
defaults := atDefaults(t)
|
||||||
|
wantResult(t, defaults,
|
||||||
|
request{http.MethodPost, save, []string{jsonBody, length, wordpressOverride}},
|
||||||
|
waf.Result{})
|
||||||
|
wantResult(t, defaults,
|
||||||
|
request{http.MethodPost, offREST, []string{jsonBody, length, wordpressOverride}},
|
||||||
|
matched(920450))
|
||||||
|
|
||||||
|
// Signing in: pwd alone skips the list of system files.
|
||||||
|
signIn := request{http.MethodPost, wpLogin, []string{formData}}
|
||||||
|
|
||||||
|
body := "log=a&pwd=b%20%2Fetc%2Fhosts"
|
||||||
|
wantBody(t, crs, signIn, body, waf.Result{}, body)
|
||||||
|
|
||||||
|
body = "log=b%20%2Fetc%2Fhosts&pwd=a"
|
||||||
|
wantBody(t, crs, signIn, body, matched(930120), body)
|
||||||
|
}
|
||||||
|
|
||||||
// bodyLimit is SWW_WAF_BODY_LIMIT in the tests that read bodies.
|
// bodyLimit is SWW_WAF_BODY_LIMIT in the tests that read bodies.
|
||||||
const bodyLimit = 8 << 10
|
const bodyLimit = 8 << 10
|
||||||
|
|
||||||
@@ -571,10 +821,10 @@ const injection = "1' OR '1'='1"
|
|||||||
|
|
||||||
// readingBodies returns the Core Rule Set as sww runs it by
|
// readingBodies returns the Core Rule Set as sww runs it by
|
||||||
// default, but reading bodies up to bodyLimit.
|
// default, but reading bodies up to bodyLimit.
|
||||||
func readingBodies(t *testing.T) *coreruleset.CoreRuleSet {
|
func readingBodies(t *testing.T) *waf.CoreRuleSet {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
crs, err := coreruleset.New(coreruleset.Params{
|
crs, err := waf.New(waf.Params{
|
||||||
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: bodyLimit,
|
ParanoiaLevel: 1, DisabledRules: defaultDisabledRules, BodyLimit: bodyLimit,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -608,8 +858,7 @@ func padded(head, tail string, n int) string {
|
|||||||
// wantBody checks what crs finds in r with body, and that what it read of
|
// wantBody checks what crs finds in r with body, and that what it read of
|
||||||
// body is read.
|
// body is read.
|
||||||
func wantBody(
|
func wantBody(
|
||||||
t *testing.T, crs *coreruleset.CoreRuleSet, r request, body string,
|
t *testing.T, crs *waf.CoreRuleSet, r request, body string, want waf.Result,
|
||||||
want coreruleset.Result,
|
|
||||||
read string,
|
read string,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
@@ -633,7 +882,7 @@ func TestBodiesAreReadOnlyWhileBodyLimitIsSet(t *testing.T) {
|
|||||||
{jsonBody, `{"q":"` + injection + `"}`},
|
{jsonBody, `{"q":"` + injection + `"}`},
|
||||||
{xmlBody, "<q>" + injection + "</q>"},
|
{xmlBody, "<q>" + injection + "</q>"},
|
||||||
} {
|
} {
|
||||||
wantBody(t, off, post(tc.header), tc.body, coreruleset.Result{}, "")
|
wantBody(t, off, post(tc.header), tc.body, waf.Result{}, "")
|
||||||
wantBody(t, on, post(tc.header), tc.body, matched(942100), tc.body)
|
wantBody(t, on, post(tc.header), tc.body, matched(942100), tc.body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -656,7 +905,7 @@ func TestFormDataAndMultipartAreReadUpToTheLimit(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
wantBody(t, crs, post(tc.header), tc.attackFirst, matched(942100),
|
wantBody(t, crs, post(tc.header), tc.attackFirst, matched(942100),
|
||||||
tc.attackFirst[:bodyLimit+1])
|
tc.attackFirst[:bodyLimit+1])
|
||||||
wantBody(t, crs, post(tc.header), tc.attackLast, coreruleset.Result{},
|
wantBody(t, crs, post(tc.header), tc.attackLast, waf.Result{},
|
||||||
tc.attackLast[:bodyLimit+1])
|
tc.attackLast[:bodyLimit+1])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,7 +915,7 @@ func TestFormDataAndMultipartAreReadUpToTheLimit(t *testing.T) {
|
|||||||
wantBody(t, crs, post(formData), atLimit, matched(930120, 932160), atLimit)
|
wantBody(t, crs, post(formData), atLimit, matched(930120, 932160), atLimit)
|
||||||
|
|
||||||
pastLimit := padded("pad=", "&q=/etc/passwd", bodyLimit+1)
|
pastLimit := padded("pad=", "&q=/etc/passwd", bodyLimit+1)
|
||||||
wantBody(t, crs, post(formData), pastLimit, coreruleset.Result{}, pastLimit)
|
wantBody(t, crs, post(formData), pastLimit, waf.Result{}, pastLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJSONAndXMLAreReadOnlyWhenNoLargerThanTheLimit(t *testing.T) {
|
func TestJSONAndXMLAreReadOnlyWhenNoLargerThanTheLimit(t *testing.T) {
|
||||||
@@ -682,7 +931,7 @@ func TestJSONAndXMLAreReadOnlyWhenNoLargerThanTheLimit(t *testing.T) {
|
|||||||
wantBody(t, crs, post(tc.header), fits, matched(942100), fits)
|
wantBody(t, crs, post(tc.header), fits, matched(942100), fits)
|
||||||
|
|
||||||
larger := padded(tc.head, tc.tail, bodyLimit+1)
|
larger := padded(tc.head, tc.tail, bodyLimit+1)
|
||||||
wantBody(t, crs, post(tc.header), larger, coreruleset.Result{}, larger)
|
wantBody(t, crs, post(tc.header), larger, waf.Result{}, larger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -700,7 +949,7 @@ func TestOtherBodiesAreNotRead(t *testing.T) {
|
|||||||
"Content-Type: text/plain",
|
"Content-Type: text/plain",
|
||||||
"Content-Type: application/x-git-receive-pack-request",
|
"Content-Type: application/x-git-receive-pack-request",
|
||||||
} {
|
} {
|
||||||
wantBody(t, crs, post(header), body, coreruleset.Result{}, "")
|
wantBody(t, crs, post(header), body, waf.Result{}, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,8 +977,8 @@ func TestContentEncodingIsRefusedOnTheKindsOfBodyTheCoreRuleSetReads(t *testing.
|
|||||||
// It is allowed on a body of any other kind, and on every body while no
|
// It is allowed on a body of any other kind, and on every body while no
|
||||||
// body is read.
|
// body is read.
|
||||||
fetch := "Content-Type: application/x-git-upload-pack-request"
|
fetch := "Content-Type: application/x-git-upload-pack-request"
|
||||||
wantBody(t, crs, post(fetch, gzip), "a", coreruleset.Result{}, "")
|
wantBody(t, crs, post(fetch, gzip), "a", waf.Result{}, "")
|
||||||
wantBody(t, atDefaults(t), post(formData, gzip), "a", coreruleset.Result{}, "")
|
wantBody(t, atDefaults(t), post(formData, gzip), "a", waf.Result{}, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParametersGiteaSendsNamesInAreLeftOutAmongFormFieldsToo(t *testing.T) {
|
func TestParametersGiteaSendsNamesInAreLeftOutAmongFormFieldsToo(t *testing.T) {
|
||||||
@@ -740,18 +989,18 @@ func TestParametersGiteaSendsNamesInAreLeftOutAmongFormFieldsToo(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
body string
|
body string
|
||||||
want coreruleset.Result
|
want waf.Result
|
||||||
}{
|
}{
|
||||||
{"path=.gitignore", coreruleset.Result{}},
|
{"path=.gitignore", waf.Result{}},
|
||||||
{"q=.gitignore", matched(930120)},
|
{"q=.gitignore", matched(930120)},
|
||||||
{"redirect_uri=" + local, coreruleset.Result{}},
|
{"redirect_uri=" + local, waf.Result{}},
|
||||||
{"next=" + local, matched(931100, 934110)},
|
{"next=" + local, matched(931100, 934110)},
|
||||||
} {
|
} {
|
||||||
wantBody(t, crs, post(formData), tc.body, tc.want, tc.body)
|
wantBody(t, crs, post(formData), tc.body, tc.want, tc.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := field("path", ".gitignore") + end
|
body := field("path", ".gitignore") + end
|
||||||
wantBody(t, crs, post(multipart), body, coreruleset.Result{}, body)
|
wantBody(t, crs, post(multipart), body, waf.Result{}, body)
|
||||||
|
|
||||||
body = field("q", ".gitignore") + end
|
body = field("q", ".gitignore") + end
|
||||||
wantBody(t, crs, post(multipart), body, matched(930120), body)
|
wantBody(t, crs, post(multipart), body, matched(930120), body)
|
||||||
@@ -875,7 +1124,7 @@ func TestCorazaWritesNoFile(t *testing.T) {
|
|||||||
func TestBodyLimitOf1GLoads(t *testing.T) {
|
func TestBodyLimitOf1GLoads(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
_, err := coreruleset.New(coreruleset.Params{ParanoiaLevel: 1, BodyLimit: 1 << 30})
|
_, err := waf.New(waf.Params{ParanoiaLevel: 1, BodyLimit: 1 << 30})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("load the Core Rule Set reading bodies up to 1G: %v", err)
|
t.Errorf("load the Core Rule Set reading bodies up to 1G: %v", err)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
# The ninth change: on WordPress's paths, some fields skip the rules that refused
|
||||||
|
# ordinary WordPress requests there. Each exclusion runs with the request, before
|
||||||
|
# the rules it switches off, so this file is loaded before the Core Rule Set's
|
||||||
|
# rules. Each comment names a request the rule refused. An exclusion on a field
|
||||||
|
# of a body applies only when the query has no parameter of that name, so it
|
||||||
|
# matters only while SWW_WAF_BODY_LIMIT is set.
|
||||||
|
|
||||||
|
# WordPress sends a call to its REST API to one of three addresses, by its
|
||||||
|
# permalink setting:
|
||||||
|
# /wp-json/wp/v2/posts/1
|
||||||
|
# /index.php/wp-json/wp/v2/posts/1
|
||||||
|
# /index.php?rest_route=/wp/v2/posts/1
|
||||||
|
# These two rules put the route, here /wp/v2/posts/1, in tx.rest_route for the
|
||||||
|
# exclusions below. A call that names a route in both its path and its query
|
||||||
|
# gets none of them, since WordPress follows the query.
|
||||||
|
SecRule &ARGS_GET:rest_route "@eq 0" "id:900705,phase:1,pass,nolog,chain"
|
||||||
|
SecRule REQUEST_FILENAME "@rx ^/(?:index\.php/)?wp-json(/.*)$" \
|
||||||
|
"capture,setvar:tx.rest_route=%{tx.1}"
|
||||||
|
SecRule REQUEST_FILENAME "@streq /index.php" "id:900706,phase:1,pass,nolog,chain"
|
||||||
|
SecRule ARGS_GET:rest_route "@rx ^(/.*)$" "capture,setvar:tx.rest_route=%{tx.1}"
|
||||||
|
|
||||||
|
# The block editor saves a post with POST and the header X-HTTP-Method-Override:
|
||||||
|
# PUT, which the Core Rule Set refused (920450). So does saving a user's editor
|
||||||
|
# preferences.
|
||||||
|
SecRule TX:rest_route "@beginsWith /" \
|
||||||
|
"id:900700,phase:1,pass,nolog,\
|
||||||
|
ctl:ruleRemoveTargetById=920450;REQUEST_HEADERS_NAMES:X-HTTP-Method-Override"
|
||||||
|
|
||||||
|
# The block editor and the site editor send HTML in the JSON field content, which
|
||||||
|
# skips these rules when saving or autosaving a post, a page, a template or a
|
||||||
|
# template part:
|
||||||
|
# 930120: cat /etc/hosts
|
||||||
|
# 932230: a code block with a shell pipeline and an SQL query
|
||||||
|
# 932250: the same code block
|
||||||
|
# 934100: console.log('ok')
|
||||||
|
# 941100: <iframe src="..." onload="...">
|
||||||
|
# 941110: <script>
|
||||||
|
# 941120: onload=
|
||||||
|
# 941160: <img src=
|
||||||
|
# 941180: <!-- wp:paragraph -->, the comment that starts every block
|
||||||
|
# 941390: console.log(
|
||||||
|
# 942190: how to select a table from the catalog
|
||||||
|
# 942270: how to select a table from the catalog
|
||||||
|
SecRule TX:rest_route \
|
||||||
|
"@rx ^/wp/v2/(?:(?:posts|pages)(?:/[0-9]+(?:/autosaves)?)?|template(?:s|-parts)(?:/[^/]+//[^/]+(?:/autosaves)?)?)$" \
|
||||||
|
"id:900701,phase:1,pass,nolog,chain"
|
||||||
|
SecRule &ARGS_GET:json.content "@eq 0" \
|
||||||
|
"ctl:ruleRemoveTargetById=930120;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=932230;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=932250;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=934100;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941100;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941110;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941120;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941160;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941180;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=941390;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=942190;ARGS:json.content,\
|
||||||
|
ctl:ruleRemoveTargetById=942270;ARGS:json.content"
|
||||||
|
|
||||||
|
# A reply to a comment from the list of comments, in content:
|
||||||
|
# 932125: ls -la, in the reply's text
|
||||||
|
# 932230: ls -la, in the reply's text
|
||||||
|
# 932250: ls -la, in the reply's text
|
||||||
|
SecRule REQUEST_FILENAME "@streq /wp-admin/admin-ajax.php" \
|
||||||
|
"id:900702,phase:1,pass,nolog,chain"
|
||||||
|
SecRule &ARGS_GET:content "@eq 0" \
|
||||||
|
"ctl:ruleRemoveTargetById=932125;ARGS:content,\
|
||||||
|
ctl:ruleRemoveTargetById=932230;ARGS:content,\
|
||||||
|
ctl:ruleRemoveTargetById=932250;ARGS:content"
|
||||||
|
|
||||||
|
# Saving a plugin's or a theme's file from its file editor sends the file in
|
||||||
|
# newcontent, which skips these rules, each of which refused saving the plugin
|
||||||
|
# Hello Dolly's hello.php. Some of them refused only the whole file:
|
||||||
|
# 932140: if ( 'en_' !== substr(
|
||||||
|
# 932235: the whole file
|
||||||
|
# 933100: the whole file
|
||||||
|
# 933160: if ( 'en_' !== substr(
|
||||||
|
# 933210: $lyrics = explode(
|
||||||
|
# 941100: <style type='text/css'>
|
||||||
|
# 941160: <style type='text/css'>
|
||||||
|
# 941190: the whole file
|
||||||
|
# 942151: if ( 'en_' !== substr(
|
||||||
|
# 942540: Dolly'll never go away again";
|
||||||
|
SecRule REQUEST_FILENAME "@streq /wp-admin/admin-ajax.php" \
|
||||||
|
"id:900703,phase:1,pass,nolog,chain"
|
||||||
|
SecRule &ARGS_GET:newcontent "@eq 0" \
|
||||||
|
"ctl:ruleRemoveTargetById=932140;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=932235;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=933100;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=933160;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=933210;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=941100;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=941160;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=941190;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=942151;ARGS:newcontent,\
|
||||||
|
ctl:ruleRemoveTargetById=942540;ARGS:newcontent"
|
||||||
|
|
||||||
|
# Signing in, in pwd, where a password holds any characters:
|
||||||
|
# 930120: a password ending in /etc/hosts
|
||||||
|
SecRule REQUEST_FILENAME "@streq /wp-login.php" \
|
||||||
|
"id:900704,phase:1,pass,nolog,chain"
|
||||||
|
SecRule &ARGS_GET:pwd "@eq 0" "ctl:ruleRemoveTargetById=930120;ARGS:pwd"
|
||||||
|
|
||||||
|
# WordPress's searches for posts, media and plugins send the text searched for
|
||||||
|
# in s, which skips these rules there:
|
||||||
|
# 932120: powershell
|
||||||
|
# 932250: ls -la
|
||||||
|
# 932260: python3
|
||||||
|
SecRule REQUEST_FILENAME \
|
||||||
|
"@rx ^/(?:index\.php|wp-admin/(?:edit|upload|plugin-install)\.php)?$" \
|
||||||
|
"id:900707,phase:1,pass,nolog,\
|
||||||
|
ctl:ruleRemoveTargetById=932120;ARGS:s,\
|
||||||
|
ctl:ruleRemoveTargetById=932250;ARGS:s,\
|
||||||
|
ctl:ruleRemoveTargetById=932260;ARGS:s"
|
||||||
|
|
||||||
|
# The REST API's searches of posts send it in search, which skips the same rules
|
||||||
|
# there.
|
||||||
|
SecRule TX:rest_route "@rx ^/wp/v2/(?:search|posts)$" \
|
||||||
|
"id:900708,phase:1,pass,nolog,\
|
||||||
|
ctl:ruleRemoveTargetById=932120;ARGS:search,\
|
||||||
|
ctl:ruleRemoveTargetById=932250;ARGS:search,\
|
||||||
|
ctl:ruleRemoveTargetById=932260;ARGS:search"
|
||||||
|
|
||||||
|
# The plugin and theme file editors name the file open in file, which skips
|
||||||
|
# these rules there:
|
||||||
|
# 930120: akismet/views/config.php
|
||||||
|
# 932160: bin/install.sh
|
||||||
|
# 932260: docker-compose.yml
|
||||||
|
SecRule REQUEST_FILENAME "@rx ^/wp-admin/(?:plugin|theme)-editor\.php$" \
|
||||||
|
"id:900709,phase:1,pass,nolog,\
|
||||||
|
ctl:ruleRemoveTargetById=930120;ARGS:file,\
|
||||||
|
ctl:ruleRemoveTargetById=932160;ARGS:file,\
|
||||||
|
ctl:ruleRemoveTargetById=932260;ARGS:file"
|
||||||
Reference in new issue
Block a user