Skip to content

Commit

Permalink
Add matchzone chapter (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio authored Dec 21, 2024
1 parent 7426314 commit 2ae25aa
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 7 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
![naxsi](logo.png)

## Documentation

Updated documentation is available [here](https://wargio.github.io/naxsi/).

## What is Naxsi?

NAXSI means [Nginx](http://nginx.org/) Anti [XSS](https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29) & [SQL Injection](https://www.owasp.org/index.php/SQL_injection).
Expand Down Expand Up @@ -37,10 +41,6 @@ It depends on `libpcre` for its regexp support, and is reported to work great on

The original project is **officially** abandoned (and has been archived the 8th Nov 2023), but you can fully ask for support here as i'm willing to keep the project working as last remaining developer.

## Documentation

You can find the main documentation [https://wargio.github.io/naxsi/](https://wargio.github.io/naxsi/)

## Build naxsi

**Be sure when you clone the repository to fetch all the submodules.**
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Contrary to most Web Application Firewalls, Naxsi doesn't rely on a signature ba
* **Rules**: [Understand the different types of rules you can create in Naxsi.](rules.md)
* **Internal Rules**: [The full list of internal rules that are hardcoded in Naxsi](internal_rules.md)
* **Whitelists**: [Learn how to use whitelisting features in Naxsi to allow specific traffic through Naxsi.](whitelist.md)
* **Matchzones**: [Describes how matchzones can be used to limit rules or whitelists.](matchzones.md) (**WIP**)
* **Matchzones**: [Describes how matchzones can be used to limit rules or whitelists.](matchzones.md)
* **Logs**: [Describes the format of the logs and how to read them.](logs.md) (**WIP**)
* **Packaging Naxsi**: [Build your own distro packages from sources.](packaging-naxsi.md)

Expand Down
215 changes: 214 additions & 1 deletion docs/matchzones.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,216 @@
# **Naxsi Matchzones**

This section describes how matchzones can be used to limit rules or whitelists.
**Matchzones**, denoted by the prefix `mz:`, are crucial components of **rules** and **whitelists**. They act like filters to define specific locations where a pattern should be searched or allowed.

Here's how they function differently based on the context:

- **Rules:** In this case, matchzones work with an **OR** logic (like `BODY` OR `HEADERS`). This means that as long as one of the specified conditions is met, the rule triggers.

- **Whitelists:** Here, matchzones operate under an **AND** logic (like `url` must be `/foo` AND must occur in `ARGS`). It requires that *both conditions* within a whitelist be satisfied before the pattern is allowed.

## Any Matchzone

This special matchzone designated by `ANY` allows to define **rules and whitelists which matches in any area of a request**.

For instance, the rule `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:ANY";` is equivalent of writing the following rules but in one line.

```
MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:ARGS|HEADERS|BODY|URL";
MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:RAW_BODY";
MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:FILE_EXT";
```

> 📣 Important
>
> This can be used also for whitelists, but it is possible to disable a rule by just not declaring any matchzone (see the [Whitelist matchzones notes](whitelist.md#matchzone)).
## Filter by HTTP Headers

HTTP headers let the client and the server pass additional information with a message in a request or response; Naxsi allows to filter rules and whitelists by headers as follows:

### Filter by Any HTTP header value

This Matchzone designated by `HEADERS` is specifically tailored to identify **only the content found within HTTP headers**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:HEADERS";` detects the occurrence of the string `malicious` exclusively within the HTTP headers values transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:HEADERS";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP header values.

### Filter by Any HTTP header name

This Matchzone designated by `HEADERS|NAME` is specifically tailored to identify **only the name of the header found within HTTP request**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8" "str:x-forward-to" "mz:HEADERS|NAME";` detects the occurrence of the string `X-Forward-To` exclusively within the HTTP headers names transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:HEADERS|NAME";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP header name.

### Filter by HTTP header name

This Matchzone designated by `$HEADERS_VAR:foo` and `$HEADERS_VAR_X:^foo$` is specifically tailored to identify **only the content found within an HTTP header named `foo`**.

- `$HEADERS_VAR:<string>` can be used to filter by header name (**case-insensitive**) via a string.
- `$HEADERS_VAR_X:<regex>` can be used to filter by header name (**case-insensitive**) via a regex.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:curl" "mz:$HEADERS_VAR:user-agent|$HEADERS_VAR:cookie";` detects the occurrence of the string `curl` exclusively within the value of the HTTP headers `User-Agent` and `Cookie` (**case-insensitive**).
- A whitelist entry like `BasicRule wl:12345 "mz:$HEADERS_VAR_X:^cookie$";` negates the match of any rule with id `12345` if the match occurs within the value of the HTTP header `Cookie` via regex.

> 📣 Important
>
> This can be mixed with `|NAME` to perform the filtering at argument name instead of value.
> Example: `mz:$HEADERS_VAR_X:^foo\d+$|NAME` matches only the HTTP header named `foo<number>`.
## Filter by GET query

HTTP GET requests can carry information, referred as queries, in the form of key=value pairs; Naxsi allows to filter rules and whitelists by these arguments as follows:

### Filter by Any GET query value

This Matchzone designated by `ARGS` is specifically tailored to identify **only the value found within HTTP GET query**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:ARGS";` detects the occurrence of the string `malicious` exclusively within the HTTP GET queries values transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:ARGS";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP GET queries values.

### Filter by Any GET query name

This Matchzone designated by `ARGS|NAME` is specifically tailored to identify **only the name of the GET query found within HTTP request**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8" "str:delete_action" "mz:ARGS|NAME";` detects the occurrence of the string `delete_action` exclusively within the HTTP GET queries names transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:ARGS|NAME";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP GET queries names.

### Filter by GET query value or name

This Matchzone designated by `$ARGS_VAR:foo` and `$ARGS_VAR_X:^foo$` is specifically tailored to identify **only the content found within an HTTP GET query named `foo`**.

- `$ARGS_VAR:<string>` can be used to filter by argument name (**case-insensitive**) via a string.
- `$ARGS_VAR_X:<regex>` can be used to filter by argument name (**case-insensitive**) via a regex.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:evil" "mz:$ARGS_VAR:foo|$ARGS_VAR:bar";` detects the occurrence of the string `evil` exclusively within the value of the GET queries `User-Agent` (**case-insensitive**).
- A whitelist entry like `BasicRule wl:12345 "mz:$ARGS_VAR_X:^cookie$";` negates the match of any rule with id `12345` if the match occurs within the value of the HTTP header `Cookie` via regex.

> 📣 Important
>
> This can be mixed with `|NAME` to perform the filtering at argument name instead of value.
> Example: `mz:$ARGS_VAR_X:^foo\d+$|NAME` matches only the GET query named `foo<number>`.
## Filter by POST Requests

HTTP POST requests carries information in the HTTP body; the request data can have multiple formats:

- `application/x-www-form-urlencoded` contains key=value pairs.
- `multipart/form-data` contains boundaries with the raw data.

Naxsi allows to filter these in rules and whitelists as follows:

### Filter by Any `application/x-www-form-urlencoded` Value

This Matchzone designated by `BODY` is specifically tailored to identify **only the value found within HTTP POST body**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:BODY";` detects the occurrence of the string `malicious` exclusively within the HTTP POST body values (key=value format) transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:BODY";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP POST body values.

### Filter by Any `application/x-www-form-urlencoded` Key

This Matchzone designated by `BODY|NAME` is specifically tailored to identify **only the name of the header found within HTTP request**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8" "str:delete_action" "mz:BODY|NAME";` detects the occurrence of the string `delete_action` exclusively within the HTTP POST arguments names transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:BODY|NAME";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP POST arguments names.

### Filter by Any `application/x-www-form-urlencoded` Key and Value

This Matchzone designated by `$BODY_VAR:foo` and `$BODY_VAR_X:^foo$` is specifically tailored to identify **only the content found within an HTTP POST body named `foo`**.

- `$BODY_VAR:<string>` can be used to filter by POST form name (**case-insensitive**) via a string.
- `$BODY_VAR_X:<regex>` can be used to filter by POST form name (**case-insensitive**) via a regex.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:malicious" "mz:$BODY_VAR:foo|$BODY_VAR:bar";` detects the occurrence of the string `malicious` exclusively within the value of the POST form keys `foo` and `body` (**case-insensitive**).
- A whitelist entry like `BasicRule wl:12345 "mz:$BODY_VAR_X:^foo$";` negates the match of any rule with id `12345` if the match occurs within the value of the POST form named `foo` via regex.

> 📣 Important
>
> This can be mixed with `|NAME` to perform the filtering at argument name instead of value.
> Example: `mz:$BODY_VAR_X:^foo\d+$|NAME` matches only the POST argument named `foo<number>`.
### Filter by Any `multipart/form-data` filename

This Matchzone designated by `FILE_EXT` is specifically tailored to match **only the filename found within HTTP multipart POST request**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:.php" "mz:FILE_EXT";` detects the occurrence of the string `.php` exclusively within the filename of the HTTP multipart POST request.
- A whitelist entry like `BasicRule wl:12345 "mz:FILE_EXT";` negates the match of any rule with id `12345` if the match itself occurs in the filename of the HTTP multipart POST request.

## Filter by HTTP Raw Body

This Matchzone designated by `RAW_BODY` is specifically tailored to match **any byte sequence in an unparsed HTTP body**.

For instance:

- A rule such as `BasicRule id:12345 "s:$EXECUTABLE:8" "rx:MZ\x90" "mz:RAW_BODY";` detects the occurrence of a byte sequence (Windows PE magic) within the HTTP body of the request.
- A whitelist entry like `BasicRule wl:12345 "mz:RAW_BODY";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP body of the request.

> 📣 Important
>
> This matchzone is internally converted as `BODY` zone, thus the `BasicRule wl:12345 "mz:BODY";` and `BasicRule wl:12345 "mz:RAW_BODY";` are equivalent.
## Filter by HTTP URL

Naxsi supports filtering by HTTP URL as follows:

### Filter by HTTP URL (global)

This Matchzone designated by `URL` is specifically tailored to identify **only the value found within HTTP URL**.

For instance:

- A rule such as `MainRule id:12345 "s:$FOO:8,$BAR:4" "str:/admin" "mz:URL";` detects the occurrence of the string `/admin` exclusively within the HTTP URL transmitted in a request.
- A whitelist entry like `BasicRule wl:12345 "mz:URL";` negates the match of any rule with id `12345` if the match itself occurs in the HTTP URL.

> 📣 Important
>
> This matchzone is globally applied, it is possible to restrict the matchzone to a specific URL or substring in the URL via `$URL` or `$URL_X` (see below).
### Filter by HTTP URL (restricted)

This Matchzone designated by `$URL:/foo` and `$URL_X:^/foo$` is specifically tailored to identify **only the URL containing the string `/foo`**.

- `$URL:<string>` can be used to filter by string (**case-insensitive**).
- `$URL_X:<regex>` can be used to filter by regex (**case-insensitive**).

These can be mixed with all the previous matchzones as follows:

In rules context, `$URL` or `$URL_X` *must* be satisfied if present. Any other condition is treated as *OR* (opposite to whitelists).

- The rule `BasicRule str:Y id:X "mz:ARGS|BODY";` is interpreted as _pattern 'Y' will be matched against *any* GET and POST arguements_
- The rule `BasicRule str:Y id:X "mz:ARGS|BODY|$URL:/foo";` is interpreted as _pattern 'Y' will be matched against *any* GET and POST arguements as long as URL is `/foo`_

In whitelist context, *all* conditions must be satisfied, so a whitelist like `BasicRule wl:X "mz:$ARGS_VAR:foo|$URL:/bar";` is interpreted as _id X is whitelisted in GET variable `foo` on URL `/bar`_

> ⚠️ Warning
>
> **You CANNOT mix `$URL_X:<regex>` and `$ARGS_VAR:<string>`, `$BODY_VAR:<string>` and `$HEADERS_VAR:<string>` in a rule or whitelist.**
>
> It is allowed instead to mix `$URL_X:<regex>` with `$ARGS_VAR_X:<regex>`, `$BODY_VAR_X:<regex>` and `$HEADERS_VAR_X:<regex>` and to mix `$URL:<string>` with `$ARGS_VAR:<string>`, `$BODY_VAR:<string>` and `$HEADERS_VAR:<string>`.
> ℹ️ Info
>
> It is allowed to mix `FILE_EXT` and `RAW_BODY` with `$URL_X:<regex>` and `$URL:<string>`.
# Go Back

[Table of Contents](index.md).
2 changes: 1 addition & 1 deletion docs/whitelist.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Examples:
## **Matchzone**

Matchzones defines where a whitelist should apply for each given **id**.
Matchzones defines where a whitelist should apply for each given **id**; these operate under an **AND** logic (like `url` must be `/foo` AND must occur in `ARGS`)

> 📣 Important
>
Expand Down

0 comments on commit 2ae25aa

Please sign in to comment.