|
1 | 1 | # **Naxsi Logs**
|
2 | 2 |
|
3 |
| -This section describes the format of the logs and how to read them. |
| 3 | +Naxsi utilizes NGINX's `error_log` feature to produce logs; specifically, it offers two types of error logs that can be generated: one in **URL-encoded format** (which is the default option) and another in **JSON format**. |
| 4 | + |
| 5 | +These logs are `action log` and `extended log`. They include detailed information about the triggered rules, content identified, paths and request IDs for comprehensive security monitoring and analysis. |
| 6 | + |
| 7 | +> ⚠️ Warning |
| 8 | +> |
| 9 | +> Due to hardcoded limitations of NGINX (see `NGX_MAX_ERROR_STR` defined by `ngx_log.h` in the NGINX source code), these logs may be truncated if too long. |
| 10 | +> |
| 11 | +> It is strongly recommanded to increase the line limit to `8192` or higher by patching NGINX itself. |
| 12 | +> |
| 13 | +> Example of patch: `sed -i 's#NGX_MAX_ERROR_STR 2048#NGX_MAX_ERROR_STR 8192#g' src/core/ngx_log.h` |
| 14 | +
|
| 15 | +## Action Logs |
| 16 | + |
| 17 | +Action logs contains the following information: |
| 18 | + |
| 19 | +- `ip`: Client IP |
| 20 | +- `server`: Nginx server name |
| 21 | +- `uri`: Request URI |
| 22 | +- `config`: Configuration of naxsi for the applied rule, this can be one of the following values: |
| 23 | + - `learning` [Learning Mode active](directives.md#learningmode), i.e. The [action taken is `LOG`](directives.md#checkrule) and the **request was NOT dropped**. |
| 24 | + - `learning-drop` [Learning Mode active](directives.md#learningmode) but request was dropped, i.e. [The action taken is `DROP`](directives.md#checkrule). |
| 25 | + - `drop` The request was dropped, i.e. [The action taken is `DROP`](directives.md#checkrule). |
| 26 | + - `block` The request was dropped, i.e. [The action taken is `BLOCK`](directives.md#checkrule). |
| 27 | + - `ignore` The request was supposed to be dropped/blocked, but it was ignored due to matching [`IgnoreIP`](directives.md#ignoreip) or [`IgnoreCIDR`](directives.md#ignorecidr), i.e. [The action taken is `LOG`](directives.md#checkrule). |
| 28 | +- `rid`: Request Identifier (matches the `request_id` NGINX value). |
| 29 | +- `id<N>`: Matched rule identifier |
| 30 | +- `cscore<N>`: Request score name (see [Check Rules](directives.md#checkrule)), for example `$SQL`. |
| 31 | +- `score<N>`: Request score value (see [Check Rules](directives.md#checkrule)), for example `8`. |
| 32 | +- `zone<N>`: Request [matchzone](matchzones.md), for example `URL`. |
| 33 | +- `var_name<N>`: Request variable name where the match has happen, for example `foo_bar[]`. |
| 34 | + |
| 35 | +> ℹ️ Info |
| 36 | +> |
| 37 | +> The `<N>` is a counter that always starts from `0` for each request and is used for listing all the matched rules and their info (`id`, `cscore`, etc..). |
| 38 | +> |
| 39 | +> For example, a request can have multiple matching rules and these will be logged by Naxsi as follows: |
| 40 | +> |
| 41 | +> The first rule (`<N>=0`) is logged as `id0=<id>`, `cscore0=<score name>`, `score0=<score count>`, `zone0=<matchzone>`, `var_name0=<var name>`; the second rule (`<N>=1`) is going to be `id1=<id>`, `cscore1=<score name>`, `score1=<score count>`, `zone1=<matchzone>`, `var_name1=<var name>`, the third (`<N>=2`), etc... |
| 42 | +> |
| 43 | +> If the rule score name is the same for multiple rules, the first `cscoreX` defined in the logs will contain the sum of the total score of multiple rules. |
| 44 | +
|
| 45 | +## Extended Logs |
| 46 | + |
| 47 | +Extended logs needs to be enabled by adding `set $naxsi_extensive_log 1;` or via the runtime modifier `naxsi_extensive_log` to the NGINX configuration and logs all the matches of a request: |
| 48 | + |
| 49 | +- `ip`: Client IP |
| 50 | +- `server`: Nginx server name |
| 51 | +- `rid`: Request Identifier (matches the `request_id` NGINX value). |
| 52 | +- `uri`: Request URI |
| 53 | +- `id`: Matched rule identifier |
| 54 | +- `zone`: Request [matchzone](matchzones.md), for example `URL`. |
| 55 | +- `var_name`: Request variable name where the match has happen, for example `foo_bar[]`. |
| 56 | +- `content`: The matched content, for example `malicious` (can be truncated if too long). |
| 57 | + |
| 58 | + |
| 59 | +*Action format logs* can be distinguished by *extended logs* the presence of `cscore` & `score` keywords; *Extended logs* are also the only ones having the `content` keyword. |
| 60 | + |
| 61 | +## URL Encoded logs |
| 62 | + |
| 63 | +**This is the default logging format for Naxsi**; These logs are always preceded by `NAXSI_FMT` (action logs) or `NAXSI_EXLOG` (extended logs) and the values of each logged info is `url-encoded`. |
| 64 | + |
| 65 | +Example: |
| 66 | + |
| 67 | +``` |
| 68 | +2024/12/26 12:27:44 [error] 3829059#0: *4 NAXSI_EXLOG: ip=127.0.0.1&server=localhost&rid=70d8cd8818e7e27a11d14df63c676227&uri=%2Fx%2Cy&id=1015&zone=URL&var_name=&content=%2Fx%2Cy, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 69 | +2024/12/26 12:27:44 [error] 3829059#0: *4 NAXSI_EXLOG: ip=127.0.0.1&server=localhost&rid=70d8cd8818e7e27a11d14df63c676227&uri=%2Fx%2Cy&id=1015&zone=ARGS&var_name=uuu&content=b%2Cc, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 70 | +2024/12/26 12:27:44 [error] 3829059#0: *4 NAXSI_FMT: ip=127.0.0.1&server=localhost&uri=%2Fx%2Cy&config=learning&rid=70d8cd8818e7e27a11d14df63c676227&cscore0=$SQL&score0=8&zone0=URL&id0=1015&var_name0=&zone1=ARGS&id1=1015&var_name1=uuu, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 71 | +``` |
| 72 | + |
| 73 | +## JSON logs |
| 74 | + |
| 75 | +This logs format needs to be enabled via `set $naxsi_json_log 1;` or via the runtime modifier `naxsi_json_log`. |
| 76 | + |
| 77 | +*Action logs* can be distinguished by *extended logs* the presence of `cscore` & `score` keywords; *Extended logs* are also the only ones having the `content` keyword. |
| 78 | + |
| 79 | +``` |
| 80 | +2024/12/26 12:28:37 [error] 3829158#0: *4 {"ip":"127.0.0.1","server":"localhost","rid":"1d27ac3c0b10bbb8783d109213f3f4cd","uri":"/x,y","id":1015,"zone":"URL","var_name":"","content":"/x,y"}, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 81 | +2024/12/26 12:28:37 [error] 3829158#0: *4 {"ip":"127.0.0.1","server":"localhost","rid":"1d27ac3c0b10bbb8783d109213f3f4cd","uri":"/x,y","id":1015,"zone":"ARGS","var_name":"uuu","content":"b,c"}, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 82 | +2024/12/26 12:28:37 [error] 3829158#0: *4 {"ip":"127.0.0.1","server":"localhost","uri":"/x,y","config":"block","rid":"1d27ac3c0b10bbb8783d109213f3f4cd","cscore0":"$SQL","score0":8,"zone0":"URL","id0":1015,"var_name0":"","zone1":"ARGS","id1":1015,"var_name1":"uuu"}, client: 127.0.0.1, server: localhost, request: "GET /x,y?uuu=b,c HTTP/1.1", host: "localhost" |
| 83 | +``` |
| 84 | + |
| 85 | +Here is an example of how the previous JSON logs appears when formatted by utilities such as `jq`: |
| 86 | + |
| 87 | +```json |
| 88 | +// Action Log |
| 89 | +{ |
| 90 | + "ip": "127.0.0.1", |
| 91 | + "server": "localhost", |
| 92 | + "uri": "/x,y", |
| 93 | + "config": "block", |
| 94 | + "rid": "1d27ac3c0b10bbb8783d109213f3f4cd", |
| 95 | + "cscore0": "$SQL", |
| 96 | + "score0": 8, |
| 97 | + "zone0": "URL", |
| 98 | + "id0": 1015, |
| 99 | + "var_name0": "", |
| 100 | + "zone1": "ARGS", |
| 101 | + "id1": 1015, |
| 102 | + "var_name1": "uuu" |
| 103 | +} |
| 104 | + |
| 105 | +// Extended Log |
| 106 | +{ |
| 107 | + "ip": "127.0.0.1", |
| 108 | + "server": "localhost", |
| 109 | + "rid": "1d27ac3c0b10bbb8783d109213f3f4cd", |
| 110 | + "uri": "/x,y", |
| 111 | + "id": 1015, |
| 112 | + "zone": "URL", |
| 113 | + "var_name": "", |
| 114 | + "content": "/x,y" |
| 115 | +} |
| 116 | +``` |
0 commit comments