Nemesida WAF Community Edition provides the base web application security against OWASP class attacks based on the signature method. Nemesida WAF Community Edition has its own signatures, detects attacks on web applications with a minimum number of false positives, is updated from the FreeBSD and Linux repository, installed and configured in a few minutes.
Nemesida WAF features:
- quick and easy start;
- installation and configuration in 10 minutes;
- minimum false positives;
- installation and update from the repository;
- the ability to connect to an already installed Nginx, starting from version 1.16;
- convenient web interface, the ability to integrate with SIEM systems.
The main limitation of the Community Edition affects the operation of data normalization mechanism (e.g. Base64/HTML Entity/UTF-16 decoding) and Nemesida AI machine learning subsystem, which enables more accurate and ultra-low false positives detection of attacks on web applications (including exploitation of zero-day vulnerabilities). Nemesida WAF Scanner is also unavailable.
To visualize the difference between signature-based analysis and machine learning, you can use the free WAF Bypass Tool, which assesses the security level of a web application.
The tool sends over 2000 requests with various payloads to a WAF-protected web application and collects statistics, which it displays as a table of results.
The tables above clearly show how the use of machine learning increases the accuracy of attack detection. Using only the signature method for detecting attacks allows you to block 46.62% of attacks, and using machine learning increases this figure to 99.66%.
In addition, Nemesida WAF Community Edition modifies the content of attack messages sent to the Nemesida WAF API:
- the
vhost
field is set toexample.com
; - the
referer
field is set toNemesida WAF Community Edition
; - the non-empty
other_headers
field is set toNemesida WAF Community Edition
; - the
WAF ID
field is set toCOMMUNITYEDITION
.
# apt install apt-transport-https gnupg2 curl
# apt update && apt upgrade
# apt install apt-transport-https gnupg2 curl
Nginx setup
If Nginx is compiled from source code, you need to add the --with-compat --with-threads --with-pcre
parameters when executing configure
to activate dynamic module support.
Install Nginx:
# apt update && apt upgrade # apt install nginx
Install Nginx:
# apt update && apt upgrade # apt install nginx
# freebsd-update fetch # freebsd-update install # pkg upgrade -y
Bringing the file /etc/sysctl.conf
to the form:
... kern.ipc.somaxconn=16384 ...
Run the command to apply the changes before restarting the server:
# sysctl kern.ipc.somaxconn=16384
Bringing the file /etc/rc.conf
to the form:
... nginx_enable="YES" ...
Install the package:
# pkg install -y nginx # service nginx start
Installing Nemesida WAF Community Edition
In the case of measures aimed at configuring the OS to ensure its security (for example, based on recommendations CIS Benchmarks), before installing the package, you must remove the security flags
rw
,nosuid
,noexec
,nodev
for the/tmp
directory where temporary files used during installation are stored.
The dynamic module is available for:
- Nginx stable from
1.16
; - Nginx mainline from
1.19
; - Nginx Plus from
R26
.
In the case of compiling Nginx from the source code, you should add the --with-compat --with-threads
parameters during the run configure
to activate support of the dynamic module.
Set the operating system ID:
# rm -f /etc/machine-id # /bin/systemd-machine-id-setup
# apt install nwaf-dyn-1.24
where 1.24 is the version of the installed Nginx. For example, package of the dynamic module nwaf-dyn-1.24 is intended for work with Nginx version 1.24 and nwaf-dyn-plus-rX (where X is the number of release, started with R26) is intended for work with the last version of Nginx Plus (for example: nwaf-dyn-plus-r26).
During the installation of the module, the following PIP packages are additionally installed:
cython pandas requests psutil scikit-learn schedule simple-crypt fuzzywuzzy levmatch python-Levenshtein unidecode fsspec func_timeout url-normalize netaddr pymemcache logutils openapi-schema-validator strict-rfc3339 rfc3339-validator isodate jsonref fastapi uvicorn[standard] gunicorn pydantic python-multipart
# apt install nwaf-dyn-1.24
where 1.24 is the version of the installed Nginx. For example, package of the dynamic module nwaf-dyn-1.24 is intended for work with Nginx version 1.24 and nwaf-dyn-plus-rX (where X is the number of release, started with R26) is intended for work with the last version of Nginx Plus (for example: nwaf-dyn-plus-r26).
During the installation of the module, the following PIP packages are additionally installed:
cython pandas requests psutil scikit-learn schedule simple-crypt fuzzywuzzy levmatch python-Levenshtein unidecode fsspec func_timeout url-normalize netaddr pymemcache logutils openapi-schema-validator strict-rfc3339 rfc3339-validator isodate jsonref fastapi uvicorn[standard] gunicorn pydantic python-multipart
Configure the SELinux policy or deactivate it with the command:
# setenforce 0
then bring the file /etc/selinux/config
to the form:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
During the installation of the module, the following PIP packages are additionally installed:
cython pandas requests psutil scikit-learn schedule simple-crypt fuzzywuzzy levmatch python-Levenshtein unidecode fsspec func_timeout url-normalize netaddr pymemcache logutils openapi-schema-validator strict-rfc3339 rfc3339-validator isodate jsonref fastapi uvicorn[standard] gunicorn pydantic python-multipart
Update package list:
# freebsd-update fetch # freebsd-update install # pkg upgrade -y
Bringing the file /etc/rc.conf
to the form:
... dbus_enable="YES" rabbitmq_enable="YES" ...
Install the packages:
# pkg install -y wget memcached dbus gnutls curl gcc lapack Atlas-devel openblas openssl bash # service dbus start # pkg install -y python310 py310-setuptools py310-cython py310-wheel cmake rust sudo # pkg install -y rabbitmq rabbitmq-c # service rabbitmq start
# curl "https://nemesida-security.com/repo/nw/freebsd/12/nwaf-dyn-1.24-5.1-1568.pkg" --output nwaf-dyn-1.24-5.1-1568.pkg # pkg install -y nwaf-dyn-1.24-5.1-1568.pkg
where 1.24
is the version of the installed Nginx, and 5.1-1568
is the version of the nwaf-dyn package.
During the installation of the module, the following PIP packages are additionally installed:
cython pandas requests psutil scikit-learn schedule simple-crypt fuzzywuzzy levmatch python-Levenshtein unidecode fsspec func_timeout url-normalize netaddr pymemcache logutils openapi-schema-validator strict-rfc3339 rfc3339-validator isodate jsonref fastapi uvicorn[standard] gunicorn pydantic python-multipart
/etc/nginx/nginx.conf
to the form:
load_module /etc/nginx/modules/ngx_http_waf_module.so; ... worker_processes auto; ... http { ... ## # Nemesida WAF ## ## Request body is too large fix client_body_buffer_size 25M; include /etc/nginx/nwaf/conf/global/*.conf; ... }
nginx: [emerg] module "/etc/nginx/modules/ngx_http_waf_module.so" version 1017010 instead of 1024000 in /etc/nginx/nginx.conf:1
The error occurs when the versions of the installed dynamic module Nemesida WAF and Nginx do not match. In this case, 1017010
is the version of Nginx 1.17.10, for which the nwaf-dyn module was compiled, and 1024000
is Nginx 1.24.0 installed on the server. The dynamic module package nwaf-dyn-1.24 is designed to work with Nginx version 1.24, and nwaf-dyn-plus-r26 is designed to work with NGINX Plus R26.
Make the necessary changes to the configuration file /etc/nginx/nwaf/conf/global/nwaf.conf
:
Restart the server and test:
# systemctl restart nginx rabbitmq-server memcached nwaf_update api_firewall # systemctl status nginx rabbitmq-server memcached nwaf_update api_firewall
The
api_firewall
service is not available for the non-commercial version, so it can be ignored or disabled:# systemctl disable api_firewall
The service nwaf_update
is responsible for obtaining signatures of the Nemesida WAF software. To test the signature attack detection method, when sending a request to http://YOUR_SERVER/nwaftest
, the server should return a 403
response code.
For the RabbitMQ service to work correctly, you need to configure its launch before launching the Nginx service. To do this, edit the file /lib/systemd/system/rabbitmq-server.service
by adding at the end of the Unit
section string Before=nginx.service
.
Example:
[Unit] Description=RabbitMQ Messaging Server After=network.target epmd@.socket Wants=network.target epmd@.socket Before=nginx.service
After making changes, apply them by running the command:
# systemctl daemon-reload
After configuring the module, it is necessary to check the information about errors, which is contained in the module’s event logs /var/log/nginx/error.log
.
After Nemesida WAF installation you can install Nemesida WAF API and Nemesida WAF Cabinet, which is intended to visualise and classify the information about attacks and identified vulnerabilities.
Using Nemesida WAF in reverse proxy mode
Setting up a web server with Nginx and Nemesida WAF in reverse proxy mode will allow to use it as an intermediate server.
Nemesida WAF Community Edition supports a custom set of rules for detecting attacks: personal signatures (RL
), as well as signature exceptions (WL
).
Zones and additional conditions
During the creation of RL
or WL
rules special parameters can be used:
- zones:
URL
,ARGS
,BODY
,HEADERS
,Cookie
,User-Agent
,Content-Type
, etc.; - conditions of using the rule (additional condition, specification of the zone):
$URL
,$ARGS
,$BODY
,$HEADERS
,$Cookie
,$User-Agent
, etc.
Using zones and additional conditions allows to concretize maximally the creating rule. Additional conditions are set by adding prefix $
(for example: "Z:...|$URL:..."
).
An example of using the rule with zone and additional condition: WL ... "Z:ARGS|$URL:/123";
– the rule will work, if the entry zone of the RL
rule will be ARGS
zone and URL will contain an entry /123
.
For the additional conditions zone URL
, it is allowed to specify only the occurrence of a path without a domain.
Example:
/index
/uploads/index.php
Several parameters (zones, additional conditions) in one rule must be separated with the character |
, the following principle of interaction will be used:
- zones interact using the logical principle
OR
, for example:Z:URL|ARGS
; - zones interact with additional conditions using the logical principle
AND
, for example:Z:URL|$ARGS:123
; - additional conditions interact using the logical principle
AND
, for example:Z:...|$ARGS:123|$BODY:123"
.
When used in the additional conditions |
as a regular character, it is necessary to make its single shielding. For example: $URL:abc\|d
– search for the occurrence of abc|d
.
Regular expressions in the additional conditions
It is possible to use regular expressions in the additional conditions. This requires to add to the additional condition postfix _X
(for example: "Z:...|$URL_X:\w+"
).
For use regular expression operators in a rule as regular characters (/
, .
, *
, ?
, !
, {
, }
, [
, ]
, (
, )
, ^
, $
, :
, \
, etc.), they must be double shielding.
Example:
$BODY_X:block\\|page
– search of an entryblock|page
;$BODY_X:data=\\(block-\\\a\\\-in-the-main\\)
– search of an entrydata=(block-\a\-in-the-main)
;$ACCEPT_X:image\\/webp\\\\\*
– search of an entryimage/webp\*
inAccept
headers.
For use in additional conditions the separator as a metacharacter of a regular expression it is necessary to shield it double.
Example:
The rule WL ... "Z:...|$URL_X:/(a\\|b)/";
will bring to URL
which contains /a/
or /b/
.
User-defined signature creation
The user-defined rules of detecting attack signs must be placed in the main configuration file Nemesida WAF (/etc/nginx/nwaf/conf/global/nwaf.conf
). They must be determined by the RL
parameter, must have ID
ranging from 50000 to 99999 and take the following form:
RL ID:50000 "P:select from" "SC:SQL:12" "Z:ARGS";
RL ID:50001 domain=example.com "P:select from" "SC:SQL:12" "Z:ARGS";
RL ID:50002 domain=.example.com "P:select from" "SC:SQL:12" "Z:ARGS";
RL ID:50003 domain=*.example.com "P:select from" "SC:SQL:12" "Z:ARGS";
RL ID:50004 "PX:select\s+from" "SC:SQL:12" "Z:ARGS|$URL:/admin";
RL ID:50005 "P:select from" "SC:SQL:12" "Z:ARGS|$URL:/(admin\\|dev)";
Creating a signature exclusion rule
In case the inquiry falls under action of a signature, in addition to sending the incident to the Nemesida WAF API, the following line will be displayed in the error log of the Nginx software:
Nemesida WAF: the request xxx contains a rule id 1 in zone HEADERS, ...
or, if the request contains a signature with a maximum allowable digital indicator of significance (score
= 12):
Nemesida WAF: the request xxx blocked by rule id 1 in zone HEADERS, ...
where:
1
– attack signature ID;HEADERS
– signature entry zone.
To display absolutely all occurrences of signatures in the request (if there are occurrences), including those occurrences that did not lead to the subsequent blocking of the request, activate the nwaf_log_mr_all;
parameter, in the nwaf.conf
file Nemesida WAF.
The information about current signature list is on the page rlinfo.nemesida-security.com.
Switching the blocking rules to LM mode
Requests that fall under the LM
mode are recorded in the database, but are not blocked. When the rule is triggered, a message will be sent to the Nginx error log and to the Nemesida WAF API about switching the corresponding blocking rule to LM
mode, but the request will not be blocked. The rules for switching to the LM
mode must be defined by the LM
parameter, have the ID
of the corresponding blocking rule and take the following form:
Virtual patching
Nemesida WAF virtual patching protects websites from existing uncorrected vulnerabilities (including “zero day”), blocking attempts to exploit them, while not disrupting the operation of the web application. The application of virtual patching rules allows developers to focus on fixing vulnerabilities without the need for urgent code changes. Virtual patching allows you to block all attempts to exploit a known vulnerability on the fly, controlling the attack zone in a special way.