Saturday, May 09, 2026 AM03:21:24 HKT
This commit is contained in:
+202
@@ -0,0 +1,202 @@
|
||||
*Note: This process is intended to run on a fully up-to-date Debian Stretch, that follows [installation best practices](https://www.ssi.gouv.fr/guide/recommandations-de-securite-relatives-a-un-systeme-gnulinux/)*
|
||||
|
||||
### Build dependencies
|
||||
|
||||
- GCC
|
||||
- make
|
||||
- nginx :)
|
||||
- libpcre3-dev
|
||||
|
||||
### Get naxsi
|
||||
|
||||
You can download naxsi from the releases page [here](https://github.com/wargio/naxsi/releases)
|
||||
Get the latest release source code and the corresponding signature file :
|
||||
|
||||
```shell
|
||||
usr@008885ac189c:~$ export NAXSI_VER=1.3
|
||||
usr@008885ac189c:~$ wget https://github.com/wargio/naxsi/releases/download/$NAXSI_VER/naxsi-$NAXSI_VER-src-with-deps.tar.gz -O naxsi-$NAXSI_VER-src-with-deps.tar.gz
|
||||
```
|
||||
|
||||
### Get Nginx
|
||||
|
||||
Next, you need to get the source code for the nginx version you are running (in this example, we are using the nginx from the debian stretch repository) :
|
||||
|
||||
```shell
|
||||
usr@008885ac189c:~$ export NGINX_VER=X.YY.Z
|
||||
usr@008885ac189c:~$ wget https://nginx.org/download/nginx-$NGINX_VER.tar.gz
|
||||
usr@008885ac189c:~$ wget https://nginx.org/download/nginx-$NGINX_VER.tar.gz.asc
|
||||
usr@008885ac189c:~$ gpg --recv-key 520A9993A1C052F8
|
||||
usr@008885ac189c:~$ gpg --verify nginx-$NGINX_VER.tar.gz.asc
|
||||
usr@008885ac189c:~$ rm nginx-$NGINX_VER.tar.gz.asc
|
||||
```
|
||||
|
||||
If the signature fails, check that both files have been correctly downloaded and are not corrupted.
|
||||
|
||||
### Build naxsi as a dynamic extension
|
||||
|
||||
First, extract the source code :
|
||||
```shell
|
||||
usr@008885ac189c:~$ mkdir -p naxsi-$NAXSI_VER
|
||||
usr@008885ac189c:~$ tar -C naxsi-$NAXSI_VER -xzf naxsi-$NAXSI_VER-src-with-deps.tar.gz
|
||||
usr@008885ac189c:~$ tar vxf nginx-$NGINX_VER.tar.gz
|
||||
usr@008885ac189c:~$ cd nginx-$NGINX_VER
|
||||
usr@008885ac189c:~/nginx-X.YY.Z$ ./configure --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/
|
||||
usr@008885ac189c:~/nginx-X.YY.Z$ make modules
|
||||
```
|
||||
The resulting `ngx_http_naxsi_module.so` will be located in the `objs` directory.
|
||||
Copy it to your nginx server, in `/etc/nginx/modules/`.
|
||||
Also copy `naxsi_core.rules` to `/etc/nginx/`.
|
||||
|
||||
|
||||
### Build naxsi as a dynamic extension for nginx from your distribution package (i.e Ubuntu)
|
||||
|
||||
You need to build the module with the same flags as your NGINX server package was compiled for example via `apt-get source nginx`
|
||||
|
||||
Execute this to list them:
|
||||
```shell
|
||||
usr@008885ac189c:~$ nginx -V
|
||||
```
|
||||
Then pass them to `./configure`.
|
||||
|
||||
```shell
|
||||
usr@008885ac189c:~/nginx-X.YY.Z$ ./configure <FLAGS FROM ABOVE COMMAND> --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/
|
||||
usr@008885ac189c:~/nginx-X.YY.Z$ make modules
|
||||
```
|
||||
This will ensure module will be compatible with your nginx and will load properly.
|
||||
|
||||
|
||||
### Basic setup
|
||||
|
||||
#### Main configuration
|
||||
|
||||
You need to tell nginx to load the naxsi module and naxsi core rules (if you don't load them, naxsi will block every requests) :
|
||||
|
||||
```shell
|
||||
usr@008885ac189c:~$ cat /etc/nginx/nginx.conf
|
||||
...
|
||||
load_module /etc/nginx/modules/ngx_http_naxsi_module.so; # load naxsi
|
||||
|
||||
http {
|
||||
include /etc/nginx/naxsi_core.rules; # load naxsi core rules
|
||||
...
|
||||
}
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
Naxsi works on a per-location basis, meaning you can only enable it inside a location :
|
||||
```python
|
||||
server {
|
||||
...
|
||||
|
||||
location / { # naxsi is enabled, and in learning mode
|
||||
|
||||
SecRulesEnabled; #enable naxsi
|
||||
LearningMode; #enable learning mode
|
||||
LibInjectionSql; #enable libinjection support for SQLI
|
||||
LibInjectionXss; #enable libinjection support for XSS
|
||||
|
||||
DeniedUrl "/RequestDenied"; #the location where naxsi will redirect the request when it is blocked
|
||||
CheckRule "$SQL >= 8" BLOCK; #the action to take when the $SQL score is superior or equal to 8
|
||||
CheckRule "$RFI >= 8" BLOCK;
|
||||
CheckRule "$TRAVERSAL >= 5" BLOCK;
|
||||
CheckRule "$UPLOAD >= 5" BLOCK;
|
||||
CheckRule "$XSS >= 8" BLOCK;
|
||||
|
||||
|
||||
proxy_pass http://127.0.0.1;
|
||||
....
|
||||
}
|
||||
|
||||
location /admin { # naxsi is disabled
|
||||
|
||||
SecRulesDisabled; #optional, naxsi is disabled by default
|
||||
|
||||
allow 1.2.3.4;
|
||||
deny all;
|
||||
proxy_pass http://127.0.0.1;
|
||||
....
|
||||
}
|
||||
|
||||
location /vuln_page.php { # naxsi is enabled, and is *not* in learning mode
|
||||
|
||||
SecRulesEnabled;
|
||||
proxy_pass http://127.0.0.1;
|
||||
}
|
||||
|
||||
location /RequestDenied {
|
||||
internal;
|
||||
return 403;
|
||||
}
|
||||
...
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### Whitelist
|
||||
|
||||
As naxsi uses a whitelist approach, a lot of false positives may be generated, potentially dropping legitimate requests.
|
||||
To prevent this, whitelists must be written (either manually or with [nx-tool](https://github.com/nbs-system/nxtool-ng)).
|
||||
For example, if you have an e-commerce website that sells furniture, people will be likely to search for something like `table`. Unfortunately, `table` is also a SQL keyword, which will trigger naxsi.
|
||||
To prevent this, you can write a whitelist telling naxsi to allow the `table` keyword in the search form (assuming the search form in on `/search`) :
|
||||
|
||||
```python
|
||||
server {
|
||||
|
||||
location / {
|
||||
SecRulesEnabled; #enable naxsi
|
||||
LearningMode; #enable learning mode
|
||||
LibInjectionSql; #enable libinjection support for SQLI
|
||||
LibInjectionXss; #enable libinjection support for XSS
|
||||
|
||||
DeniedUrl "/RequestDenied"; #the location where naxsi will redirect the request when it is blocked
|
||||
CheckRule "$SQL >= 8" BLOCK; #the action to take when the $SQL score is superior or equal to 8
|
||||
CheckRule "$RFI >= 8" BLOCK;
|
||||
CheckRule "$TRAVERSAL >= 5" BLOCK;
|
||||
CheckRule "$UPLOAD >= 5" BLOCK;
|
||||
CheckRule "$XSS >= 8" BLOCK;
|
||||
|
||||
BasicRule wl:1000 "mz:$URL:/search|$ARGS_VAR:q";
|
||||
proxy_pass http://127.0.0.1;
|
||||
....
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
See [here](whitelists-bnf.md) and [here](whitelists-examples.md) for more informations about whitelists.
|
||||
|
||||
#### Blacklist
|
||||
|
||||
You can also create blacklist with naxsi, allowing you to drop requests even when in learning mode.
|
||||
Let's imagine a PHP script (`/vuln_page.php`) vulnerable to an unquoted SQLI in the `id` parameter, a typical exploitation would look like this :
|
||||
```
|
||||
GET /vuln_page.php?id=1'+or+1=1/*
|
||||
```
|
||||
You can use naxsi to virtually patch this vulnerabilty by adding a blacklist denying every requests on `/vuln_page.php` where the `id` parameter contains anything other than a number (in this example, the blacklist will only apply to the `/` location, you can use `MainRule` and put it outside in the `http` block to make it global):
|
||||
|
||||
```python
|
||||
server {
|
||||
|
||||
location / {
|
||||
SecRulesEnabled; #enable naxsi
|
||||
LearningMode; #enable learning mode
|
||||
LibInjectionSql; #enable libinjection support for SQLI
|
||||
LibInjectionXss; #enable libinjection support for XSS
|
||||
|
||||
DeniedUrl "/RequestDenied"; #the location where naxsi will redirect the request when it is blocked
|
||||
CheckRule "$SQL >= 8" BLOCK; #the action to take when the $SQL score is superior or equal to 8
|
||||
CheckRule "$RFI >= 8" BLOCK;
|
||||
CheckRule "$TRAVERSAL >= 5" BLOCK;
|
||||
CheckRule "$UPLOAD >= 5" BLOCK;
|
||||
CheckRule "$XSS >= 8" BLOCK;
|
||||
|
||||
BasicRule id:4242 "mz:$URL:/vuln_page.php|$ARGS_VAR:id" "rx:[^\d]+" "s:DROP" "msg:blacklist for SQLI in /vuln_page.php";
|
||||
proxy_pass http://127.0.0.1;
|
||||
....
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user