203 lines
7.0 KiB
Markdown
203 lines
7.0 KiB
Markdown
*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;
|
|
....
|
|
|
|
}
|
|
|
|
}
|
|
```
|