*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 --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; .... } } ```