Find the WAF score of a blocked request
Read which internal rules a refused request matched, and what each threat family scored, from Real-Time Events or the GraphQL API.
You can read which internal rules matched a request that Web Application Firewall (WAF) refused, and what each threat family scored.
The decision leaves nothing in the response, so it is looked up afterwards. The x-azion-request-id header on the refusal is what ties it to its event. For the model behind the score, refer to Scoring and modes.
Select the interface you will use. The prerequisites and the lookup below follow that choice.
Prerequisites
- A workload bound to a firewall that applies a WAF rule set in
Blockingmode. Refer to WAF quickstart. - The domain of that workload, which has the form
<id>.map.azionedge.net.
- Access to Azion Console. To sign in, refer to How to access Azion Console.
Capture the request ID
A refused request receives 400, and it never reaches an origin. Nothing in that response names WAF, the rule that matched, or the score, so the request ID is the only value that finds the event.
To provoke a refusal on your own workload, send an injection-shaped request:
WAF refuses it:
Record x-azion-request-id. No x-azion-waf-* header exists, in this response or any other, so a refusal is not distinguishable from another 400 by headers alone.
The body is Azion’s default error page, headed Bad Request. A visitor who reports a refusal can read the same value from the Request ID row of its Error Details block.
Find the event in Real-Time Events
Real-Time Events holds one row per request, and that row carries the WAF decision.
To open the event in Azion Console:
Access Azion Console > Real-Time Events.
In the time range dropdown, select a range that contains the request.
In the Search field, enter the query below, with the domain of your workload in host:
The event opens with its WAF fields, among them WAF Block and WAF Learning.
A second query reaches the same rows from the other side, since a refusal is a 400 whose upstream status is 0:
The two queries return similar results, with small variations between them.
Read the match and the score
wafMatch and wafScore carry the decision. Both are strings holding one entry per match, separated by commas, and both read - on a request WAF did not act on.
wafMatch is shaped <index>:<ruleId>:<zone>:<varName>. In 0:1009:ARGS:q,1:1013:ARGS:q, the internal rules 1009 and 1013 each matched the q argument in the ARGS zone. Those two, rather than a single injection rule, are what 1' OR '1'='1 fires. For what each id detects, refer to WAF Rule Sets.
wafScore is shaped <index>:$<family>:<score>, and it is one score per threat family, never one number for the request. In 0:$SQL:18,1:$XSS:32, the SQL injection family scores 18 and the cross-site scripting family scores 32. A family blocks when its score reaches the threshold of the sensitivity level set for it: both families above are set to medium, whose threshold is 16. The thresholds are listed in WAF Rule Sets.
No source states an upper bound for a score, so a score carries no percentage reading. An internal rule that belongs to no scored family reports wafScore as a bare family name, such as $OTHERS.
The remaining fields narrow the reading. wafBlock reads 1 when the request was refused. wafLearning reads 1 when the rule ran in Logging mode, which records the match and serves the request. wafAttackFamily and wafAttackAction summarize the same event as $SQL,$XSS and $BLOCK. Azion Console renders these values under labels, among them WAF Block and WAF Learning.
wafTotalProcessed and wafTotalBlocked read 0 on every per-request row, including a row for a request that was refused. They are aggregate counters, so they answer nothing about one request.