NAXSI Open-Source WAF

NAXSI Open-Source WAF

Andrea Covello
by Andrea Covello
time to read: 15 minutes

WAF or Web Application Firewall is a fancy marketing name to describe technology that existed long before this term became common. In fact the technology behind WAF used to be called full application reverse-proxy and basically allows to forward, inspect and sanitize (or block) protocol requests to an application server.


Those servers are most of the time critical assets or positioned in critical zones and therefore needs an added layer of security. Beware that a WAF is not a magic thing that will solve all your problem in publishing a web application you always should apply to following security rules:

WAF implementation in the security design makes also sense when all of the above rules have been followed, because it adds another layer of defense. Experience teaches us that there is never enough defense when it comes to web application security.

Why using a WAF?

Usually you better have a WAF instance in place if you have to deal with a situation reflecting one or a combination of the following security issues regarding a web application:

Maybe you’ll find anther one, but you get the point by now. Virtual patching is also a term used in such cases to describe one of the main feature of WAF: It allows to virtually patch a vulnerable web application, blocking the attack before it happens on the application proxy gateway.

You may argue that such attack may also affect the gateway itself (we are inspecting and interpreting the application protocol, remember?) and yes, WAF life is a dangerous one.

WAF configuring and fine tuning is not to be underestimated, that is why I told you before there is no magic thing that will do all for you from the start and stay forever that way – Remember: Security is a process.

Blacklisting vs. Whitelisting

Talking about WAF we need to distinguish two major categories of modus operandi: The blacklist and the whitelist approach (also referred as positive and negative security model).

The blacklist approach tries to block all bad things based on blacklists done by you and/or pre-configured for you. The whitelist approach tries to define an allowed baseline of what is allowed to do with the wen application. As you may guess WAF can also take the hybrid approach to accomplish the following requirements:

There are several good commercial product out there (like Airlock and others) that fulfill almost all requirements, but I like to talk about the open source project NAXSI.

NAXSI Project

The NAXSI Project is not so known like the ModSecurity open source project, but has a very interesting approach and features.

NAXSI uses the small and performant reverse proxy engine of Nginx web server instead of the full blown Apache engine used by ModSecurity (and from a security point of view: the lesser code).

Following are the major feature of NAXSI:


Let’s do a quick installation with ubuntu sever 12.04 LTS. You may also install it from the sources following the Nginx prerequisites for reference. After you’ve installed the basic server with openssh, install NAXSI with:

 sudo apt-get install nginx-naxsi

Initial configuration

In the nginx configuration file (/etc/nginx/nginx.conf) uncomment this line to activate the basic rulesets:

# nginx-naxsi config
# Uncomment it if you installed nginx-naxsi
include /etc/nginx/naxsi_core.rules;

Note that this file is not an attack signature repository but rather a “score rules” set. Let’s configure NAXSI for our website To do so edit the Nginx configuration file in /etc/nginx/sites-enabled/default and add following entries in the server context:

server {
        proxy_set_header Proxy-Connection “”;    
        listen   80;

location / { # put your website IP here proxy_pass; # put your website FQDN here proxy_set_header Host; # Uncomment to enable naxsi on this location include /etc/nginx/naxsi.rules; } # Only for nginx-naxsi : process denied requests location /RequestDenied { # For example, return an HTTP error code return 418; } }

Now you should be able to start the nginx service that will bring up the NASXI with following command:

sudo service nginx start

Be sure to check for error messages on the console or in the error log found in /var/log/nginx/error.log and verify with sudo netstat -antup that nginx daemon is opening the configured port (tcp/80 in our case). The output should look like this:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address    Foreign Address   State       PID/Program name
tcp        0      0*         LISTEN      9865/nginx
tcp        0      0*         LISTEN      8484/sshd
tcp        0      0*         LISTEN      9627/0
tcp        0      0*         LISTEN      9062/1
tcp        0     32 x.y.z.52:22      x.y.z.36:49749    ESTABLISHED 9046/sshd: anco
udp        0      0*                     649/dhclient3

To test if it works, start a browser session and point it to the ip address of your test server (x.y.z.52:80) and you should see the website you configured ( in the config file above. To continue further testing make sure you will proxying all web request to the nginx-NAXSI WAF. To accomplish this you can ether use the web-proxy configuration setting in the browser or fake the testing website ip address in your system hostfile. I prefer to put the ip address in my hostfile:


Here are the location of the target hosts file (you need admin right to save changes):

OSHost Configuration File
Windows %SYSTEMROOT%\system32\drivers\etc\hosts
Linux /etc/hosts

Now we can browse to and be sure that our test NAXSI WAF will inspect the content and remember that by now the configuration is in learning mode; it will only report errors in the nginx error logs (/var/log/nginx/error.log) and not block any bad scored request.

How It Works

The naxsi_core.rules are responsible for scoring the HTTP input and looks like this (excerpt):

MainRule "str:;" "msg:; in stuff" "mz:BODY|URL|ARGS" "s:$SQL:4" id:1008;
MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302;
MainRule "str:&#" "msg: utf7/8 encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400;
MainRule "*|.asp*" "msg:asp/php file upload!" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500;

Insight this file is the logic configuration used to score the input; the result will be used in /etc/nginx/naxsi.rules to decide if such input may be allowed or not. The format is quite simple:

  1. Define what to look for: string (str:) or regular expression (rx:)
  2. Define message to report into logfiles (msg:)
  3. Put the rule a category (s:)
  4. Assign rule identifier (id:)
  5. Define where to look for (mz:) and short description below
mz entry Look in
URL URL path
ARGS HTTP argument
BODY HTML body entry
$HEADERS_VAR: HTTP header variable

Now let’s take a look on the second NAXSI config file /etc/nginx/naxsi.rules where the main NAXSI behavior is defined; this is how it looks like:

# config mode section
DeniedUrl "/RequestDenied";
# check rules section
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;

Here is an explanation of the contents:

  1. LearningMode – activates learning mode; in this mode requests aren’t blocked and white lists may be created.
  2. SecRulesEnabled or SecRulesDisabled – to activate or disable NAXSI for this location/section.
  3. DeniedURL – redirect URL for blocked requests; can be an HTTP error code (like 4xx or 5xx) or forward to an HTML site with code to help track false-positives.
  4. CheckRule – per-category check scores; the score we saw above will be evaluated here. If a request hits a score in the naxsi.core.rules, this score will be recorded and added to each category (SQL, XSS, EVADE, ...) if the overall score for any of the categories is reached (8 in SQL per default) the input is treated as bad.

When you use the whitelist (positive secure model) approach you’ll find also the white-list entries (BasicRule statement) in this config file:

# Whitelist '|', as it's used on the /report/ page, in argument 'd'
BasicRule wl:1005 "mz:$URL:/report/|$ARGS_VAR:d";
# Whitelist ',' on URL zone as it's massively used for URL rewritting !
BasicRule wl:1008 "mz:URL";

The entry above will result in disabling some part of the check rule in naxsi_core.rules allowing a specific behavior and eliminate false-positives. BasicRule could be more or less specific at your pace (and security needs).

Information Gathering

At this stage we have our test installation inspecting the HTTP flow and reporting bad things in the /var/log/nginx/error.log file, let’s take a look on how NAXSI error entry looks like:

> error.log <
2012/11/30 04:57:55 [error] 9866#0: *47 NAXSI_FMT: ip=x.y.z.36&server=x.y.z.52&uri=/testmiztot&total_processed=8589934625&total_blocked=679029381853280060&zone0=URL&id0=1999&var_name0=, client:x.y.z.36, server: localhost, request: "GET /testmiztot HTTP/1.1", host: "x.y.z.52"

As you can see it’s a special error message: it was generated on a “special” HTTP URL GET request and is not a really bad request. To test the functionality on the WAF I’ve created this test-rule in the /etc/nginx/naxsi_core.rules:

MainRule "str:testmiztot" "msg:foobar test pattern" "mz:URL" "s:$SQL:42" id:1999;

This rule will trigger whenever the testmiztot string is detected in the address part (mz:URL) of the HTTP GET request and score as 42 (s:$SQL:42) in the SQL category. This will be evaluated as bad because the SQL category limit is 8. The msg: text will be shown in the learning mode log used to generate the white-list baseline.


NAXSI is open source, high performance, low rules maintenance, and uses the very good Nginx reverse-proxy engine. Still, Naxsi is young, and there are known bugs. So test it, use it and see if it can help in your environment.

About the Author

Andrea Covello

Andrea Covello has been working in information security since the 1990s. His strengths are in engineering, specializing in Windows security, firewalling and advanced virtualization.


You want to test the security of your firewall?

Our experts will get in contact with you!

Enhancing Data Understanding

Enhancing Data Understanding

Rocco Gagliardi

Brain before post

Brain before post

Michèle Trebo

Dynamic Analysis of Android Apps

Dynamic Analysis of Android Apps

Ralph Meier

Security Testing

Security Testing

Tomaso Vasella

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here