Saturday, May 09, 2026 AM03:21:24 HKT
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
|
||||
**NOTE**
|
||||
|
||||
This is the legacy wiki page.
|
||||
Everything here should be considered obsolete.
|
||||
|
||||
If you find anything here (that is not in *current* wiki),
|
||||
please notify us via issues or help us moving it to current wiki.
|
||||
|
||||
|
||||
|
||||
* [fail2ban](olds-A-fail2ban-profile-for-Naxsi.md)
|
||||
* [naxsilogs](olds-naxsilogs.md)
|
||||
* [naxsivsobfuscated](olds-naxsivsobfuscated.md)
|
||||
* [deniedurl](olds-deniedurl.md)
|
||||
* [Knownbugs](olds-Knownbugs.md)
|
||||
* [rulessyntax](olds-rulessyntax.md)
|
||||
* [whitelists](olds-whitelists.md)
|
||||
* [basicsetup](olds-basicsetup.md)
|
||||
* [Security-Advisories](olds-Security-Advisories.md)
|
||||
* [libinjection](olds-libinjection.md)
|
||||
* [dynamicmodifiers](olds-dynamicmodifiers.md)
|
||||
* [installation](olds-installation.md)
|
||||
* [Philosophy](olds-Philosophy.md)
|
||||
* [faq](olds-faq.md)
|
||||
* [Home](olds-Home.md)
|
||||
* [naxsivsappscan](olds-naxsivsappscan.md)
|
||||
* [embedded_rules](olds-embedded_rules.md)
|
||||
* [testing-and-stuff](olds-testing-and-stuff.md)
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
Welcome to naxsi wiki !
|
||||
* [[Understand naxsi's philosophy & design|philosophy]] (READ FIRST)
|
||||
|
||||
### Tutorials
|
||||
* [[Installing Naxsi|installation]]
|
||||
* [[Basic setup|BasicSetup]]
|
||||
* [[Naxsi on steroids (lua/ngx/* scripting)|dynamicmodifiers]]
|
||||
* [[FAQ|FAQ]]
|
||||
|
||||
### Understanding Naxsi
|
||||
* [[Internal and core rules|embedded_rules]]
|
||||
* [[Understand Naxsi Whitelists|Whitelists]]
|
||||
* [[Understanding naxsi's rules syntax|RulesSyntax]]
|
||||
* [[Understanding Naxsi exceptions|NaxsiLogs]]
|
||||
* [[DeniedUrl & post_action|DeniedUrl]]
|
||||
* [[Libinjection integration|Libinjection]]
|
||||
|
||||
|
||||
### Learning tools
|
||||
* [nxapi]( https://github.com/nbs-system/naxsi/tree/master/nxapi )
|
||||
|
||||
### Extras
|
||||
* [[Naxsi behaviour against obfuscated/complex payloads|naxsivsobfuscated]]
|
||||
* [[Naxsi behaviour against web app scanner|naxsivsappscan]]
|
||||
* [[A fail2ban profile for Naxsi|A-fail2ban-profile-for-Naxsi]]
|
||||
* [[How to create an AppArmor profile for Naxsi|How-to-create-an-Apparmor-profile-for-Naxsi]]
|
||||
* [[Unit tests, code coverage…|testing-and-stuff]]
|
||||
|
||||
### Issues
|
||||
* [[Naxsi known bugs and limitations|Knownbugs]]
|
||||
@@ -0,0 +1,7 @@
|
||||
Naxsi core :
|
||||
|
||||
* Naxsi only parses GET/POST/PUT requests.
|
||||
* Naxsi supports a restricted kind of body content-type parsing : application/x-www-form-urlencoded, multipart/form-data, application/json. Other content-types are not supported.
|
||||
* Naxsi does not support parsing of a file buffered to disk by nginx: [client_body_buffer_size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size)
|
||||
* You can't use `|` caracter in your matchzone regular expressions.
|
||||
* HTTPv2 is currently not supported: [issue #227](https://github.com/nbs-system/naxsi/issues/227 )
|
||||
@@ -0,0 +1,24 @@
|
||||
## Naxsi overview
|
||||
|
||||
Technically, *naxsi* is a third party [nginx]( https://nginx.org ) module, available as a package for many UNIX-like platforms. This module, by default, reads a small subset of [simple rules]( https://github.com/nbs-system/naxsi/blob/master/naxsi_config/naxsi_core.rules ) containing known patterns involved in websites vulnerabilities and exploitation. For example, `<`, `|` or `drop` are not supposed to be part of a URI.
|
||||
|
||||
Being very simple, those patterns may match legitimate queries, it is naxsi's administrator duty to add specific rules that will [[whitelist|whitelists]] those legitimate behaviours. The administrator can either add whitelists manually by analysing nginx's error log, or (recommended) start the project by an intensive auto-learning phase that will automatically generate whitelisting rules regarding website's behaviour.
|
||||
|
||||
In short, Naxsi behaves like a *DROP-by-default* firewall, the only job needed is to add required ACCEPT rules for the target website to work properly.
|
||||
|
||||
## Naxsi expected usage
|
||||
|
||||
As Naxsi relies on whitelists to avoid false positives (even more than with a "classic" WAF), it comes with a tool called [nxapi]( https://github.com/nbs-system/naxsi/tree/master/nxapi ) that helps the administrator to create the appropriate whitelists for an application.
|
||||
If you are using common web applications 'out of the box', you might as well find pre-generated whitelists [here]( https://github.com/nbs-system/naxsi-rules )
|
||||
|
||||
## Naxsi Pro's and Con's
|
||||
Naxsi relies on a positive model, which has multiple advantages, but comes with some extra constraints :
|
||||
|
||||
#### Pros
|
||||
* **Fast** : Minimalist, Lightweight runtime processing
|
||||
* **Resilient** : Signature-less design allows improved resilience against [[obfuscated / complex attacks|NaxsiVSObfuscated]]
|
||||
* **Update independent** : Signature-less design allows sustainable security, even without updates
|
||||
|
||||
#### Con's
|
||||
* **Configuration** : Positive approach requires a heavier whitelisting process than negative model
|
||||
* **Not Idiot Proof** : As naxsi behaves like a network firewall, if you are setting up too laxist rules, your web application will not be protected correctly.
|
||||
@@ -0,0 +1,44 @@
|
||||
# Security Advisories
|
||||
_Because nobody's perfect and coding while drunk is dangerous !_
|
||||
|
||||
## Reporting Vulnerabilities and Security Issues
|
||||
|
||||
[As stated on the project's homepage](https://github.com/nbs-system/naxsi#security-issues), you can send me an email directly. Or, you can use the [issues](https://github.com/nbs-system/naxsi/issues)
|
||||
|
||||
## NO-CVE: [Medium-Low] Potential bypass on SQL keywords for IIS/ASP
|
||||
* Rated : Medium-Low
|
||||
* Date : 26 March 2013
|
||||
* Affected : All
|
||||
* Fixed in : 0.50-1 [r565 (on Google code)](https://code.google.com/p/naxsi/source/detail?r=565)
|
||||
* Discovered by : Safe3
|
||||
* References : [http://seclists.org/bugtraq/2013/Mar/133](http://seclists.org/bugtraq/2013/Mar/133)
|
||||
|
||||
Naxsi does not suppress/decode incorrectly url-encoded characters. On the other hand, IIS/ASP will treat "s%e%l%e%c%t" as "select", while naxsi will still see it as "s%e%l%e%c%t", thus rendering SQL keywords rule ineffective. Only the SQL-keywords rule is affected, thus the exploitation window is limited to quote-less, two-fields (max) SQL injections.
|
||||
|
||||
## CVE-2012-3380: [Medium] Potential file disclosure in naxsi's nx_extract
|
||||
* Rated: Medium
|
||||
* Date 18 May 2012
|
||||
* Affected: 0.46
|
||||
* Fixed in: 0.46-1
|
||||
* Discovered by : Naxsi dev team
|
||||
* References: [oss-security](http://seclists.org/oss-sec/2012/q3/12) [Secunia](https://secunia.com/advisories/49811) [Securelist](https://www.securelist.com/en/advisories/49811)
|
||||
|
||||
Local includes in nx_extract are not properly filtered, allowing a remote attacker to disclose files local to nx_extract.
|
||||
More details [https://code.google.com/p/naxsi/source/detail?r=307](https://code.google.com/p/naxsi/source/detail?r=307)
|
||||
|
||||
## NO-CVE: [Low] SQL Injection in naxsi's nx_intercept
|
||||
* Rated: Low
|
||||
* Date: 2 Apr 2012
|
||||
* Affected: 0.44
|
||||
* Fixed in: 0.44-1
|
||||
* Discovered by : Naxsi dev team
|
||||
|
||||
Ironically, an SQL Injection is present in naxsi's new python learning daemon (nx_intercept.py). The vulnerability is rated as low, as:
|
||||
* Learning daemon is usually restricted to trusted IPs
|
||||
* No sensitive data are present into database, as it is only used to store exceptions.
|
||||
The vulnerabilty only affects the nx_intercept python daemon, not the naxsi's core. Vulnerable code is:
|
||||
```python
|
||||
if md5 is not None and ip is not None:
|
||||
cursor.execute("INSERT INTO http_monitor (peer_ip, md5) VALUES ('%s', '%s')" % (ip, md5))
|
||||
return
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
### Initial setup
|
||||
|
||||
Let's take the first step to use : setting up learning mode for your website!
|
||||
This page assumes you already know how to properly configure *nginx* without Naxsi and get it working.
|
||||
|
||||
```nginx
|
||||
#/etc/nginx/nginx.conf :
|
||||
user www-data;
|
||||
worker_processes 1;
|
||||
worker_rlimit_core 500M;
|
||||
working_directory /tmp/;
|
||||
error_log /var/log/nginx/error.log;
|
||||
pid /var/run/nginx.pid;
|
||||
events {
|
||||
worker_connections 1024;
|
||||
use epoll;
|
||||
# multi_accept on;
|
||||
}
|
||||
http {
|
||||
include /etc/nginx/naxsi_core.rules;
|
||||
include /etc/nginx/mime.types;
|
||||
server_names_hash_bucket_size 128;
|
||||
access_log /var/log/nginx/access.log;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
tcp_nodelay on;
|
||||
gzip on;
|
||||
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
|
||||
include /etc/nginx/sites-enabled/*;
|
||||
}
|
||||
```
|
||||
|
||||
Notice the inclusion of the `/etc/nginx/naxsi_core.rules` file. This is the only thing you need to add to your existing `http {}` section if you already have a configuration. The [naxsi_core.rules]( https://github.com/wargio/naxsi/blob/main/naxsi_rules/naxsi_core.rules ) file is provided, and contains Naxsi core rules. As you might notice, these are not signatures, in the classic WAF sense, but simple "score rules", for example:
|
||||
|
||||
```
|
||||
MainRule "str:\"" "msg:double quote" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001;
|
||||
```
|
||||
|
||||
You can see more about rules syntax byt taking a look at the [[rules syntac documentation|rulessyntax]]
|
||||
Now, let's have a look at my /etc/nginx/site-enabled/default :
|
||||
|
||||
```nginx
|
||||
server {
|
||||
proxy_set_header Proxy-Connection "";
|
||||
listen *:80;
|
||||
access_log /tmp/nginx_access.log;
|
||||
error_log /tmp/nginx_error.log debug;
|
||||
location / {
|
||||
include /etc/nginx/naxsi.rules;
|
||||
proxy_pass http://x.x.x.x/;
|
||||
proxy_set_header Host www.mysite.com;
|
||||
}
|
||||
location /RequestDenied {
|
||||
return 418;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The naxsi's configuration itself is in the file `/etc/nginx/naxsi.rules`:
|
||||
|
||||
```ini
|
||||
LearningMode; # Enables learning mode
|
||||
SecRulesEnabled;
|
||||
#SecRulesDisabled;
|
||||
DeniedUrl "/RequestDenied";
|
||||
|
||||
## check rules
|
||||
CheckRule "$SQL >= 8" BLOCK;
|
||||
CheckRule "$RFI >= 8" BLOCK;
|
||||
CheckRule "$TRAVERSAL >= 4" BLOCK;
|
||||
CheckRule "$EVADE >= 4" BLOCK;
|
||||
CheckRule "$XSS >= 8" BLOCK;
|
||||
```
|
||||
|
||||
With the following setup :
|
||||
* Naxsi will be enabled
|
||||
* Naxsi will not block any requests (while LearningMode is active)
|
||||
* To-be-blocked requests will generate event logs in your location's error.log file
|
||||
|
||||
If you issue a request to `http://127.0.0.1/?a=<`, you'll get something like this in your logs:
|
||||
|
||||
```
|
||||
2013/05/30 20:09:43 [error] 8404#0:*3 NAXSI_FMT: ip=127.0.0.1&server=127.0.0.1&uri=/&learning=0&vers=0.50&total_processed=3&total_blocked=1&zone0=ARGS&id0=1302&var_name0=a, client: 127.0.0.1, server: , request: "GET /?a=< HTTP/1.0", host: "127.0.0.1"
|
||||
```
|
||||
|
||||
Once you get this kind of lines in your error log, you have naxsi running in LearningMode, congrats! You can now move on to [[generating whitelists|whitelists]]!
|
||||
@@ -0,0 +1,19 @@
|
||||
**DeniedUrl** is used to indicate a location where blocked requests will be redirected (internally).
|
||||
|
||||
In version before 0.49, by default, naxsi forwards blocked request there while in learning mode. Upon "real" request termination, using nginx's [post_action]( http://wiki.nginx.org/HttpCoreModule#post_action ) mechanism.
|
||||
|
||||
This was due to usage of `nx_intercept`, which could intercept learning traffic in live.
|
||||
|
||||
As the request might be modified during redirect (url & arguments), extra http headers `orig_url` (original url), `orig_args` (original GET args) and `naxsi_sig` (NAXSI_FMT) are added.
|
||||
|
||||
If $naxsi_flag_post_action is set to "1", naxsi will perform post_action (while in learning) even in versions '''> 0.49'''.
|
||||
|
||||
|
||||
The headers that are forwarded to the location denied page are :
|
||||
|
||||
```
|
||||
./naxsi_runtime.c: #define NAXSI_HEADER_ORIG_URL "x-orig_url"
|
||||
./naxsi_runtime.c: #define NAXSI_HEADER_ORIG_ARGS "x-orig_args"
|
||||
./naxsi_runtime.c: #define NAXSI_HEADER_NAXSI_SIG "x-naxsi_sig"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
### naxsi dynamic configuration (aka nginx vars)
|
||||
|
||||
Since [0.49]( https://github.com/wargio/naxsi/tree/0.49 ), naxsi supports a limited set of boolean variables that can be set to `0` or `1` to override or modify its behaviour.
|
||||
|
||||
* `naxsi_flag_learning` can override Naxsi learning flag.
|
||||
* `naxsi_flag_post_action` may be used to disable `post_action` in learning mode.
|
||||
* `naxsi_flag_enable` could override naxsi's `SecRulesEnabled`.
|
||||
* `naxsi_extensive_log` can force naxsi to log the `CONTENT` of variable matching rules (see notes at bottom).
|
||||
|
||||
### Gentle reminder
|
||||
It is important to know that naxsi operates at the `REWRITE` phase of nginx. Thus, setting those variables directly in the location where Naxsi is present is ineffective (as naxsi will be called before variable set is effective).
|
||||
|
||||
This is correct:
|
||||
|
||||
```nginx
|
||||
set $naxsi_flag_enable 0;
|
||||
location / {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
But this is wrong:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
set $naxsi_flag_learning 1;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
With that said, you can use the power of nginx, lua, etc. to change naxsi's behaviour. The presence of these variables will enable/disable learning mode, naxsi itself or force extensive logging. You can thus do things naxsi is usually not able to, like modifying its behaviour according to (nginx) variables set at run-time :
|
||||
|
||||
```nginx
|
||||
# Disable naxsi if client ip is 127.0.0.1
|
||||
if ($remote_addr = "127.0.0.1") {
|
||||
set $naxsi_flag_enable 0;
|
||||
}
|
||||
```
|
||||
|
||||
Those variables can as well be set from lua scripts (see nginx's [mod_lua]( https://github.com/openresty/lua-nginx-module#readme )).
|
||||
|
||||
### naxsi_flag_learning
|
||||
|
||||
If the `naxsi_flag_learning` variable is present, this value will override naxsi's current static configuration regarding learning mode.
|
||||
|
||||
```nginx
|
||||
if ($remote_addr = "1.2.3.4") {
|
||||
set $naxsi_flag_learning 1;
|
||||
}
|
||||
location / {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### naxsi_flag_post_action
|
||||
|
||||
The [post_action]( http://wiki.nginx.org/HttpCoreModule#post_action ) option can be used by naxsi to literally forward a request to the `DeniedUrl` location. It is on by default until [naxsi 0.50]( https://github.com/wargio/naxsi/tree/0.50 ) (a souvenir from `nx_intercept`) and is off by default since [naxsi 0.51]( https://github.com/wargio/naxsi/tree/0.51 ).
|
||||
|
||||
### naxsi_flag_enable
|
||||
If the `naxsi_flag_enable` variable is present and set to `0`, naxsi will be disabled in this request. This allows you to partially disable naxsi in specific conditions. To completely disable naxsi for "trusted" users :
|
||||
|
||||
```nginx
|
||||
set $naxsi_flag_enable 0;
|
||||
location / {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### naxsi_extensive_log
|
||||
If present and set to `1`, this variable will force naxsi to log the CONTENT of variable matching rules.
|
||||
Because of a potential impact on performance, use this with caution. Naxsi will log those to nginx’s error_log, ie:
|
||||
|
||||
```
|
||||
NAXSI_EXLOG: ip=%V&server=%V&uri=%V&id=%d&zone=%s&var_name=%V&content=%V
|
||||
```
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
# Internal rules
|
||||
|
||||
Since its [0.53 release]( https://github.com/wargio/naxsi/tree/0.53 ), naxsi comes with a predefined set of rules with the following id:
|
||||
|
||||
- `1` - "weird request" : This a generic exception used for improperly formatted requests.
|
||||
- `2` - "big request" : Request is too big and has been buffered to disk by nginx.
|
||||
- `10` - "uncommon hex encoding" : Encoding suggests this might be an escape attempt.
|
||||
- `11` - "uncommon content-type" : Content-type of BODY is unknown / cannot be parsed.
|
||||
- `12` - "uncommon URL" : URL is malformed
|
||||
- `13` - "uncommon post format" : malformed boundary or content-disposition
|
||||
- `14` - "uncommon post boundary" : BODY boundary line is malformed, or boundary breaks RFC
|
||||
- `15` - invalid JSON - gets parsed when application/json is detected (experimental as of summer 2014)
|
||||
- `16` - "empty body" : POST with empty BODY, available since [naxsi 0.53-1]( https://github.com/wargio/naxsi/tree/0.53 ), was merged with `id:11` before.
|
||||
- `17` - "Libinjection SQL" : Libinjection SQL detection was triggered.
|
||||
- `18` - "Libinjection XSS" : Libinjection XSS detection was triggered.
|
||||
|
||||
|
||||
## naxsi-core.rules
|
||||
|
||||
Naxsi ships with a [basic core-rule-set]( https://github.com/wargio/naxsi/blob/main/naxsi_rules/naxsi_core.rules )
|
||||
that protects against common attacks. Those Core-Rules should always be loaded.
|
||||
|
||||
- [SQL-Injections]( https://www.owasp.org/index.php/SQL_Injection ) (1000-1099)
|
||||
- Obvious [Remote File Inclusions]( https://www.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion ) (1100-1199)
|
||||
- [Directory Traversal]( https://www.owasp.org/index.php/Path_Traversal ) (1200-1299)
|
||||
- [Cross Site Scripting]( https://www.owasp.org/index.php/XSS ) (1300-1399)
|
||||
- [Basic Evading tricks]( https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet ) (1400-1500)
|
||||
- [File uploads]( https://www.owasp.org/index.php/Unrestricted_File_Upload ) (1500-1600)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
## Naxsi blocks all requests but no IDs are written
|
||||
|
||||
If you see lines like :
|
||||
```
|
||||
2013/09/03 00:11:45 [error] 14913#0: *1 NAXSI_FMT: ip=127.0.0.1&server=localhost&uri=/&learning=1&vers=0.50&total_processed=1&total_blocked=1, client: 127.0.0.1, server: , request: "GET / HTTP/1.0", host: "localhost"
|
||||
```
|
||||
|
||||
It's usually because you forgot to include naxsi rules in your `http {}` block. Try adding `include /etc/nginx/naxsi_core.rules;` to it.
|
||||
|
||||
## I compiled naxsi from source, I enabled NAXSI, but it doesn't seem to filter requests?
|
||||
|
||||
Did you put naxsi directives first in your location configuration and `./configure`?
|
||||
You **MUST** put naxsi's directives first in your location configuration. Please check as well your configuration at both `http {}` and `location {}` levels.
|
||||
|
||||
## How to limit learning mode to some specific IPs/Users/locations?
|
||||
|
||||
Naxsi supports [[DynamicModifiers]] to change behaviour at runtime.
|
||||
You can as well rely on nginx's [HttpAllowModule]( http://wiki.nginx.org/HttpAccessModule ).
|
||||
You could also set different vhosts (with associated locations) up, and define some to have `learningmode`, and others without.
|
||||
|
||||
## How to test that naxsi is working?
|
||||
|
||||
Setup your RequestDenied as follow :
|
||||
|
||||
```nginx
|
||||
location /RequestDenied {
|
||||
return 500;
|
||||
}
|
||||
```
|
||||
|
||||
Check that `learningMode` is disabled, that `naxsi_core.rules` is included, and issue a request like `http:/.../?a=<>`. You should get a 500 from nginx, and get an entry in your nginx error log, starting with `NAXSI_FMT:`.
|
||||
|
||||
## I downloaded / installed packages from X, but I don't have this feature / new learning tools?
|
||||
Naxsi is a young and evolving project and distributions cannot always keep up. Use the source luke, as documented [[here|installation]].
|
||||
|
||||
## Why do you keep radically changing learning tools?
|
||||
Because it's a not-that-easy problem, and we haven't found a satisfying solution yet. If you have ideas about how we could do it better, please tell us!
|
||||
|
||||
## Can I run naxsi on Windows
|
||||
No one tried that yet, but feel free to go down the [rabbit hole]( http://nginx-win.ecsds.eu/ )
|
||||
@@ -0,0 +1,82 @@
|
||||
You can install nginx+naxsi either from packages (available from official repositories on debian, freebsd, netbsd) or directly from source.
|
||||
As Nginx does not yet support runtime module loading, lot of people will choose compiling from source to avoid package maintainers delay.
|
||||
|
||||
## Installation From Packages
|
||||
|
||||
Packages are available for NetBSD, FreeBSD and Debian, from distribution's repositories.
|
||||
Naxsi project does not create/publish such packages.
|
||||
|
||||
## Installation From Source
|
||||
|
||||
Naxsi should be working with all Nginx versions superior to 0.8.X.
|
||||
To install it from source, we need to fetch both nginx and naxsi sources.
|
||||
|
||||
#### Import Source Signing Keys
|
||||
Import [Nginx signing keys]( http://nginx.org/en/pgp_keys.html ) and [naxsi's one](https://pgp.mit.edu/pks/lookup?op=get&search=0x251A28DE2685AED4).
|
||||
|
||||
_note_ : Signed releases of naxsi started at [0.54rc3]( https://github.com/nbs-system/naxsi/tree/0.54rc3 ).
|
||||
|
||||
```shell
|
||||
gpg --keyserver pgp.mit.edu --recv-keys 0x251A28DE2685AED4 7BD9BF62 A1C052F8
|
||||
```
|
||||
|
||||
#### Download Sources
|
||||
Note: replace `TAG_NAME` with the [tagged release](https://github.com/nbs-system/naxsi/tags) you want.
|
||||
|
||||
```shell
|
||||
wget http://nginx.org/download/nginx-x.x.xx.tar.gz
|
||||
wget http://nginx.org/download/nginx-x.x.xx.tar.gz.asc
|
||||
wget https://github.com/nbs-system/naxsi/archive/TAG_NAME.tar.gz
|
||||
wget https://github.com/nbs-system/naxsi/releases/download/TAG_NAME/TAG_NAME.tar.gz.asc
|
||||
```
|
||||
|
||||
#### Verify Sources
|
||||
|
||||
```shell
|
||||
gpg --verify nginx-*.tar.gz.asc nginx-*.tar.gz
|
||||
gpg --verify TAG_NAME.tar.gz.asc TAG_NAME.tar.gz
|
||||
```
|
||||
|
||||
Both source verifications should present you a message that says:
|
||||
|
||||
```
|
||||
> gpg: Good signature from ...
|
||||
```
|
||||
|
||||
#### Unpack Sources
|
||||
If both sources verify, then it is safe to unpack and proceed to compilation.
|
||||
|
||||
```shell
|
||||
tar -xvzf nginx-*.tar.gz
|
||||
tar -xvzf TAG_NAME.tar.gz
|
||||
```
|
||||
|
||||
#### Compiling
|
||||
Install `libpcre` (and `libssl` if you want https, along with `zlib` for gzip support) with your favorite package manager, naxsi relies on it for regex.
|
||||
|
||||
```shell
|
||||
cd nginx-*
|
||||
./configure --add-module=../naxsi-x.xx/naxsi_src/ [add/remove your favorite/usual options]
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
My personal "building" options being here :
|
||||
|
||||
```shell
|
||||
./configure --conf-path=/etc/nginx/nginx.conf --add-module=../naxsi-x.xx/naxsi_src/ \
|
||||
--error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body \
|
||||
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log \
|
||||
--http-proxy-temp-path=/var/lib/nginx/proxy --lock-path=/var/lock/nginx.lock \
|
||||
--pid-path=/var/run/nginx.pid --with-http_ssl_module \
|
||||
--without-mail_pop3_module --without-mail_smtp_module \
|
||||
--without-mail_imap_module --without-http_uwsgi_module \
|
||||
--without-http_scgi_module --with-ipv6 --prefix=/usr
|
||||
```
|
||||
|
||||
# IMPORTANT
|
||||
|
||||
You need to remember this :
|
||||
NGINX will decide the order of modules according the order of the module's directive in nginx's `./configure`. So, no matter what (except you really know what you are doing) put naxsi first in your `./configure`.
|
||||
|
||||
If you don't do so, you might run into various problems, from random / unpredictable behaviours to non-effective WAF.
|
||||
@@ -0,0 +1,22 @@
|
||||
Libinjection is being integrated into naxsi, starting at 0.54rc0
|
||||
|
||||
* https://github.com/nbs-system/naxsi/releases/tag/0.54rc0
|
||||
|
||||
We are looking for people to test it and provide feedback on it.
|
||||
|
||||
Usage :
|
||||
|
||||
* By default, Libinjection (sql/xss) is disabled, it needs to be enabled at location level using one of these directives : LibInjectionSql / LibInjectionXss (or libinjection_sql / libinjection_xss in nginx style).
|
||||
* It can as well be dynamically enabled / disabled using :
|
||||
```
|
||||
set $naxsi_libinjection_xss 0|1;
|
||||
set $naxsi_libinjection_sql 0|1;
|
||||
```
|
||||
* When triggered, libinjection sql/xss will trigger internal rules :
|
||||
* libinjection_sql, with internal ID of 17, will increase $LIBINJECTION_SQL of 8
|
||||
* libinjection_xss, with internal ID of 18, will increase $LIBINJECTION_XSS of 8
|
||||
|
||||
* If you want to add action uppon trigger, write your CheckRules on those scores ;) (as for other rules, LOG/BLOCK/DROP is allowed!)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
### NAXSI_FMT
|
||||
|
||||
NAXSI_FMT are the lines you can see in your error.log :
|
||||
|
||||
```
|
||||
2013/11/10 07:36:19 [error] 8278#0: *5932 NAXSI_FMT: ip=X.X.X.X&server=Y.Y.Y.Y&uri=/phpMyAdmin-2.8.2/scripts/setup.php&learning=0&vers=0.52&total_processed=472&total_blocked=204&block=0&cscore0=$UWA&score0=8&zone0=HEADERS&id0=42000227&var_name0=user-agent, client: X.X.X.X, server: blog.memze.ro, request: "GET /phpMyAdmin-2.8.2/scripts/setup.php HTTP/1.1", host: "X.X.X.X"
|
||||
```
|
||||
|
||||
Here, client `X.X.X.X` request to server `Y.Y.Y.Y` did trigger the rule `42000227` in the var named `user-agent` in the`HEADERS` zone. `id X` might seem obscure, but you can see the meaning in [naxsi_core.rules]( https://github.com/nbs-system/naxsi/blob/master/naxsi_config/naxsi_core.rules ):
|
||||
|
||||
```
|
||||
MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302;
|
||||
```
|
||||
|
||||
NAXSI_FMT is composed of different items :
|
||||
|
||||
- `ip` : Client's ip
|
||||
- `server` : Requested Hostname (as seen in http header `Host`)
|
||||
- `uri`: Requested URI (without arguments, stops at `?`)
|
||||
- `learning`: tells if naxsi was in learning mode (0/1)
|
||||
- `vers` : Naxsi version, only since [0.51]( https://github.com/nbs-system/naxsi/tree/0.51 )
|
||||
- `total_processed`: Total number of requests processed by nginx's worker
|
||||
- `total_blocked`: Total number of requests blocked by (naxsi) nginx's worker
|
||||
- `zoneN`: Zone in which match happened (see "Zones" in the table below)
|
||||
- `idN`: The rule id that matched
|
||||
- `var_name`: Variable name in which match happened (optional)
|
||||
|
||||
Several groups of zone, id, var_name can be present in a single line.
|
||||
|
||||
Existing zones can be are the following:
|
||||
|
||||
- `ARGS`: GET args
|
||||
- `$ARGS_VAR `: named GET argument
|
||||
- `$ARGS_VAR_X`: regex matching the name of a GET argument
|
||||
- `HEADERS `: HTTP Headers
|
||||
- `$HEADERS_VAR ` : named HTTP header
|
||||
- `$HEADERS_VAR_X`: regex matching a named HTTP header
|
||||
- `BODY `: POST args (and RAW_BODY)
|
||||
- `$BODY_VAR `: named POST argument
|
||||
- `$BODY_VAR_X`: regex matching the name of a POST argument
|
||||
- `URL`: The URL (before '?')
|
||||
- `$URL`: The specified URL
|
||||
- `$URL_X`: regex matching the URL (before '?')
|
||||
- `FILE_EXT`: Filename (in a multipart POST containing a file)
|
||||
|
||||
A zone can be suffixed with "|NAME", meaning the rule matched in the name of the variable, not its content.
|
||||
|
||||
As well, several scores can be present since [0.53]( https://github.com/nbs-system/naxsi/tree/0.53 ):
|
||||
|
||||
```ini
|
||||
cscoreX=[score_tag]
|
||||
scoreX=[score_value]
|
||||
```
|
||||
|
||||
### NAXSI_EXLOG
|
||||
|
||||
NAXSI_EXLOG is a complement to [[naxsilogs]]. Along with exceptions, it contains actual content of the matched request. While NAXSI_FMT only contains IDs and location of exception, NAXSI_EXLOG provides actual content, allowing you to easily decide if it's a false positive or not.
|
||||
|
||||
Learning tools uses this at his advantage. Extensive log is enabled by adding the following line in your server {} section but **out** of your location.
|
||||
|
||||
```javascript
|
||||
set $naxsi_extensive_log 1;
|
||||
```
|
||||
|
||||
This feature is provided by [[DynamicModifiers]].
|
||||
|
||||
```
|
||||
2013/05/30 20:47:05 [debug] 10804#0:*1 NAXSI_EXLOG: ip=127.0.0.1&server=127.0.0.1&uri=/&id=1302&zone=ARGS&var_name=a&content=a<>bcd
|
||||
2013/05/30 20:47:05 [error] 10804#0:*1 NAXSI_FMT: ip=127.0.0.1&server=127.0.0.1&uri=/&learning=0&vers=0.50&total_processed=1&total_blocked=1&zone0=ARGS&id0=1302&var_name0=a, client: 127.0.0.1, server: , request: "GET /?a=a<>bcd HTTP/1.0", host: "127.0.0.1"
|
||||
```
|
||||
|
||||
### Naxsi Internal IDs
|
||||
|
||||
"User defined" rules are supposed to have IDs > `1000`.
|
||||
|
||||
IDs inferior `1000` are reserved for [[naxsi internal rules|embedded_rules]], which are usually related to protocol sanity and things that cannot be expressed through regular expressions or string matches.
|
||||
|
||||
Think twice before whitelisting one of those IDs, as it might partially/totally disable naxsi.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Classical benchmark : Web Vuln Scanner vs WAF
|
||||
|
||||
Here we will present the results of (IBM) [AppScan]( https://www-03.ibm.com/software/products/en/appscan/ ) vs naxsi.
|
||||
|
||||
Why AppScan ? Because, it's one of the less worse commercial scanner available, because they offer a target/demo (read : highly vulnerable) website, and, unlike [Acunetix]( https://www.acunetix.com/ ), you can run full tests on the target website.
|
||||
|
||||
# Overall Results
|
||||
|
||||
As you will see bellow, AppScan is not able to find any vulnerabilities that it can exploit. The only vulnerabilities detected are probed with extremely simple patterns (read : nearly full ascii) that are not (and will not) be blocked by naxsi (to avoid false positives).
|
||||
|
||||
## Raw results
|
||||
|
||||
When running AppScan against [demo.testfire.net]( http://demo.testfire.net ) with naxsi (set-up as forward proxy for this purpose), the following vulnerabilities will appear:
|
||||
|
||||

|
||||
|
||||
I won't make an exhaustive diff list between naxsi and raw results since, as you can expect, original scan results have a LOT of vulnerabilities, as this website is designed to show all the vulnerabilities AppScan can detect/exploit.
|
||||
|
||||
Let's go through all the "remaining" bugs :
|
||||
|
||||
## Blind SQL Injections
|
||||
|
||||
The scan result shows at least 2 Blind SQL Injection remaining. Actually, the attack pattern used by AppScan is the following :
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
The first test pattern `listAccounts=0%2B0%2B0%2B1001160141` is decoded to `listAccounts=0+0+0+1001160141`, and the seconde one, `before=1234+and+7659%3D7659` to `before=1234 and 7659=7659`. Appscan is able to detect the vulnerability, but it will not be able to exploit it.
|
||||
|
||||
## Database Error Pattern
|
||||
|
||||
During the scan, AppScan was able to detect several "Database Error Pattern" (read : MSSQL/MySQL/... error messages in webpage)
|
||||
|
||||

|
||||
|
||||
The test pattern used by AppScan is `100116014WFXSSProbe`, it's a generic one to *trace back* injected data into a webpage. Here, the scanner is able to trigger the bug by entering a non-numeric value in a numeric field, making the page yield a SQL error message. Obviously, you cannot do anything here except blocking the scanner's pattern, which would be dumb and inefficient. Obviously, the injected characters won't allow any kind of exploitation of the vulnerability, only a probe.
|
||||
|
||||
## Other vulnerabilities
|
||||
|
||||
The other vulnerabilities reported by AppScan :
|
||||
|
||||
* Weak credentials : Because it's possible to login with admin/admin. No comment Out of scope for a WAF.
|
||||
* Session Reuse : When logging / logging off and logging in again, AppScan notices that the Cookie (session) doesn't change. (Out of scope for a WAF)
|
||||
* Weak Cookies : Sensitive information is stored in the user's cookie, enabling cookie theft if someone can access the user's workstation. (Out of scope for a WAF)
|
||||
* No account lock : An attacker can brute-force passwords. (Out of scope for a WAF, but nginx with req_limit might help you solving that !)
|
||||
* CSRF : This is more touchy, because it can be blocked by NAXSI, by adding a rule like `BasicRule "rx:http://demo.testfire.net/*" "mz:$HEADERS:Referer";`, but we didn't add it, because we wanted this scan to be really "out of the box" with no customization.
|
||||
@@ -0,0 +1,193 @@
|
||||
### Introduction/Disclaimer
|
||||
|
||||
First of all, and to prevent any trolls : We're **not** saying that naxsi is better than [mod_security]( https://modsecurity.org/ ). We think that mod_security is a great project and we have a huge respect for its team.
|
||||
|
||||
That being said, we will present you the results of the mod_security SQLi challenge. This challenge was organized by the mod_security people, and participants had to bypass mod_security to perform SQLi on various vulnerable web sites.
|
||||
|
||||
As you will see, none of the attack patterns used will bypass naxsi, because naxsi isn't clever and doesn't try to interpret stuff in requests, avoiding the risk of getting bypassed by obfuscated syntax.
|
||||
|
||||
Last but not least, the more uncommon a request is, the more chance they have to be blocked by naxsi.
|
||||
|
||||
Detailed information about the mod_security challenge can be found [here]( http://blog.spiderlabs.com/2011/07/modsecurity-sql-injection-challenge-lessons-learned.html )
|
||||
|
||||
#### Bypass #1 : Johannes Dahse
|
||||
|
||||
##### Payload
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user
|
||||
```
|
||||
|
||||
##### Decoded
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=0+div+1+union#foo*/*bar
|
||||
select#foo
|
||||
1,2,current_user
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
|
||||
* Multiple SQL keywords
|
||||
* SQL comments
|
||||
* Uncommon characters : `, #*`
|
||||
|
||||
#### Bypass #2 : Vladimir Vorontsov
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
FromDate=a1%27+or&ToDate=%3C%3Eamount+and%27
|
||||
```
|
||||
|
||||
##### Decoded
|
||||
|
||||
```
|
||||
FromDate=a1'+or&ToDate=<>amount+and'
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple quotes
|
||||
* `<>` Signs
|
||||
|
||||
#### Bypass #3 : PT Research
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
after=1 AND (select DCount(last(username)&after=1&after=1) from users where username='ad1min')&before=d
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple SQL keywords
|
||||
* Multiple parenthesis
|
||||
* Multiple quotes
|
||||
* Naxsi is immune to splitting attacks
|
||||
|
||||
#### Bypass #4 : Ahmad Maulana
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
ToDate=1'UNION/*!0SELECT user,2,3,4,5,6,7,8,9/*!0from/*!0mysql.user/*-
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple SQL keywords
|
||||
* SQL comments
|
||||
* Multiple quotes
|
||||
* Uncommon characters : `, !`
|
||||
|
||||
#### Bypass #5 : Travis Lee
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
Cookie: ASP.NET_SessionId=c0tx0o455d0b10ylsdr03m55; amSessionId=14408158863; amUserInfo=UserName=YWRtaW4=&
|
||||
Password=JyBvciAnMSc9JzEnLS0=; amUserId=1 union select username,password,3,4 from users
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple SQL keywords
|
||||
* Multiple commas
|
||||
* This one is really interesting, as mod_security was bypassed, not because of the pattern, but because of its location (Cookie Headers)
|
||||
|
||||
#### Bypass #6 : Roberto Salgado
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=-
|
||||
2%20div%201%20union%20all%23yeaah%0A%23yeah%20babc%0A%23fdsafdsafa%23fafsfaf%23%23yea%0A
|
||||
%23yeah%20babc%0A%23fdsafdsafa%23fafsfaf%23%23yeaah%0A%23yeah%20babc%0A%23fdsafdsafa%23f
|
||||
afsfaf%23%23yea%0A%23yeah%20babc%0A%23fdsafdsafa%23fafsfaf%23%23yeaah%0A%23yeah%20babc%0
|
||||
A%23fdsafdsafa%23fafsfaf%23%23yea...
|
||||
truncated
|
||||
...3fafsfaaf%23fafsfaaf%23fafsfaaf%23fafsfaaf%
|
||||
0Aselect%200x00,%200x41%20like/*!31337table_name*/,3%20from%20information_schema.tables%
|
||||
20limit%201
|
||||
```
|
||||
|
||||
##### Decoded
|
||||
|
||||
```
|
||||
2 div 1 union all#yeaah
|
||||
#yeah babc
|
||||
#fdsafdsafa#fafsfaf##yea
|
||||
#yeah babc
|
||||
#fdsafdsafa#fafsfaf##yeaah...
|
||||
truncated
|
||||
...
|
||||
like/*!31337table_name*/,3 from information_schema.tables...
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple SQL keywords
|
||||
* SQL comments
|
||||
* uncommon characters : `# , !`
|
||||
|
||||
#### Bypass #7 : Sqlmap Developers
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=%40%40new%20union%23sqlmapsqlmap...%0Aselect%201,2,database%23sqlmap%0A%28%29
|
||||
```
|
||||
|
||||
##### Decoded
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=@@new union#sqlmapsqlmap...
|
||||
select 1,2,database#sqlmap
|
||||
()
|
||||
```
|
||||
|
||||
###### Explanation
|
||||
* Multiple SQL keywords
|
||||
* Uncommon characters : `.. # , ()`
|
||||
|
||||
#### Bypass #8 : HackPlayers
|
||||
|
||||
###### Payload
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/artists.php?artist=-
|
||||
2%20div%201%20union%20all%23hack%0A%23hpys%20player%0A%23fabuloso%23great%0A%23hpys%20pl
|
||||
ayer%0A%23fabuloso%23modsec%0A%23hpys%20player%0A%23fabuloso%23great%0A%23hpys%20player%
|
||||
0A%23fabuloso%23modsec%0A%23h...
|
||||
truncated
|
||||
...23hpys%20player%0A%23fabuloso%23great%23%0A%23fabuloso%23great%23%0Aselect%200x00%2C%200
|
||||
x41%20not%20like%2F*%2100000table_name*%2F%2C3%20from%20information_schema.tables%20limi
|
||||
t%201
|
||||
```
|
||||
|
||||
##### Decoded
|
||||
|
||||
```
|
||||
-2 div 1 union all#hack
|
||||
#hpys player
|
||||
#fabuloso#great...
|
||||
truncated
|
||||
...
|
||||
select 0x00, 0x41 not like/*!00000table_name*/,3 from information_schema.tables limit 1
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
|
||||
* Multiple SQL keywords
|
||||
* SQL comments
|
||||
* Uncommon characters : `# , ! `
|
||||
|
||||
#### Bypass #9 : Georgi Geshev
|
||||
|
||||
##### Payload
|
||||
|
||||
```
|
||||
http://www.modsecurity.org/testphp.vulnweb.com/listproducts.php?artist=1%0bAND(SELECT%0b1%20FROM%20mysql.x)
|
||||
```
|
||||
|
||||
##### Explanation
|
||||
* Multiple SQL keywords
|
||||
|
||||
|
||||
### Final WORD
|
||||
All those tests where realized on a 'out of the box' naxsi, we I did no customization nor any modifications whatsoever.
|
||||
@@ -0,0 +1,127 @@
|
||||
Naxsi is using a simple key-value system for its rules. For example `MainRule "msg:this is a message" "str:searchstring" "mz:URL|BODY|ARGS" "s:$XSS:8" id:12345678990;` is a *main* rule with the *id* 12345678990, that search the string `searchstring` in the *url*, the *body* and the *arguments* of the request, and upon match, it will increase the `XSS` score by 8.
|
||||
|
||||
Everything must be quoted with double quotes, except the id part.
|
||||
|
||||
```
|
||||
|
||||
MainRule "msg:this is a message" "str:searchstring" "mz:URL|BODY" "s:$XSS:8" id:12345;
|
||||
| | | | | +-> UNIQUE ID
|
||||
| | | | |
|
||||
| | | | +-> SCORE
|
||||
| | | |
|
||||
| | | +-> MZ
|
||||
| | |
|
||||
| | +-> SearchString/RegEx
|
||||
| |
|
||||
| +-> MESSAGE
|
||||
|
|
||||
+-> RuleDesignator
|
||||
```
|
||||
|
||||
## Designator
|
||||
Either `MainRule` or `BasicRule`.
|
||||
|
||||
BasicRule and MainRule can be used either for rules or whitelist.
|
||||
The difference is the scope : BasicRule is valid in location {} context, while MainRule is valid at http {} context.
|
||||
|
||||
## Match Pattern (str:... rx:...)
|
||||
|
||||
**Match pattern** can be a regular expression or a string match:
|
||||
|
||||
* `rx:foo|bar` : will match `foo` or `bar`
|
||||
* `str:foo|bar` : will match `foo|bar`
|
||||
* `d:libinj_xss` : will match if libinjection says it's XSS (**>= 0.55rc2**)
|
||||
* `d:libinj_sql` : will match if libinjection says it's SQLi (**>= 0.55rc2**)
|
||||
|
||||
Using plain string match when possible is recommended, as it's way faster.
|
||||
All strings *must* be lowercase, since naxsi's matches are case insensitive.
|
||||
|
||||
## Human readable message (msg:...)
|
||||
|
||||
**msg** is a string describing the pattern. This is mostly used for analyzing and to have some human-understandable text.
|
||||
|
||||
|
||||
## Score section (s:...)
|
||||
|
||||
**s** is the score section. You can create "named" counters: `s:$FOOBAR:4` will increase counter `$FOOBAR` value by 4. One rule can increase several scores: `s:$FOO:4,$BAR:8` will increase both `$FOO` by `4` and `$BAR` by `8`. A rule can as well directly specifiy an action such a BLOCK (blocks the request in non-learning mode) or DROP (blocks the request **even** in learning mode)
|
||||
|
||||
## Match Zone (mz:...)
|
||||
|
||||
**mz** is the match zone, defining which part of the request will be inspected by the rule (or the whitelist, it works in the same way).
|
||||
|
||||
`mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie` means that pattern will be searched in the whole *body* (content and name of each var), as well as in **url** (before the '?') and in the get **arguments** (content and name of each var).
|
||||
|
||||
`$HEADERS_VAR:Cookie` means that the pattern will be as well applied to the HTTP header named `Cookie`. Filenames of file uploads can be check as well with the `FILE_EXT` zone.
|
||||
|
||||
See [Whitelists generation]( whitelists ), as same `mz:` usage applies. ie. `mz:$URL:/foo|$ARGS_VAR:arg42` will create a rule that will only be looked against GET argument `arg42` of request to URL `/foo`. (**fixed in >= 0.55rc2**)
|
||||
|
||||
You can as well use the `_X` (>= 0.52) equivalents, that allows you to create matchzone matching regular expressions, for example: `mz:$URL_X:^/foobar[0-9]+$` to match URLs such as `foobar1`, `foobar000`, etc. However, because of a known limitation, you can't use `|` character in your `_X` regular expressions, because it is used as a field separator by naxsi rule parsing.
|
||||
|
||||
Starting from naxsi **0.55rc0**, for unknown content-types, you can use the `RAW_BODY` match-zone. `RAW_BODY` rules looks like that:
|
||||
|
||||
```
|
||||
MainRule id:4241 s:DROP str:RANDOMTHINGS mz:RAW_BODY;
|
||||
```
|
||||
|
||||
Rules in the `RAW_BODY` zone will only applied when:
|
||||
- The *Content-type* is unknown (which means naxsi doesn't know how to properly parse the request)
|
||||
- `id 11` (which is the internal blocking rule for 'unknown content-type') is whitelisted.
|
||||
|
||||
Then, the full body (url decoded and with null-bytes replaced by '0') is passed to this set of rules.
|
||||
The full body is matched again the regexes or string matches.
|
||||
|
||||
Whitelists for `RAW_BODY` rules are actually written just like normal body rules, such as:
|
||||
|
||||
```
|
||||
BasicRule wl:4241 "mz:$URL:/rata|BODY";
|
||||
```
|
||||
|
||||
### Valid *mz*
|
||||
|
||||
- **URL** Full URI (server-path of a request)
|
||||
- **ARGS** Request-Arguments (all the things behind the `?` character in a GET-Request)
|
||||
- **BODY** Request-Data from a POST-Request
|
||||
- **HEADERS**
|
||||
- **$HEADERS_VAR:[value]** any HTTP-HEADERS-var that is available, eg
|
||||
- **$HEADERS_VAR:User-Agent**
|
||||
- **$HEADERS_VAR:Cookie**
|
||||
- **$HEADERS_VAR:Content-Type**
|
||||
- **$HEADERS_VAR:Connection**
|
||||
- **$HEADERS_VAR:Accept-Encoding**
|
||||
- **FILE_EXT** Filename (in a multipart POST containing a file)
|
||||
|
||||
For rules, each item of the match zone is considered inclusive **OR** (with the exception of $URL / $URL_X that **must** be satisfied if present in match-zone).
|
||||
|
||||
## ID (id:...)
|
||||
|
||||
**id** is the ID of the rule, that will be used in `NAXSI_FMT` or to whitelist it.
|
||||
|
||||
IDs inferior to `1000` are reserved for naxsi internal rules (protocol mismatch etc.)
|
||||
|
||||
## Negative Keyword (negative)
|
||||
|
||||
**negative** is a keyword that can be used to make a negative rule.
|
||||
Score is applied when the rule doesn't match :
|
||||
|
||||
```
|
||||
MainRule negative "rx:multipart/form-data|application/x-www-form-urlencoded" "msg:Content is neither mulipart/x-www-form.." "mz:$HEADERS_VAR:Content-type" "s:$EVADE:4" id:1402;
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
This will look for the string `Submit=Run` on the url `/script`, with the *POST* variable `Submit` present:
|
||||
```
|
||||
MainRule "msg:detection Submit=Run in POST" "str:Submit=Run" "mz:$URL:/script|$BODY_VAR:Submit" "s:$ATTACK" id: 1230001;
|
||||
```
|
||||
|
||||
This will look for accesses on the `/hidden.html` url:
|
||||
```
|
||||
MainRule "msg:detection URL-Access" "str:/hidden.html" "mz:URL" "s:$ATTACK" id:1230002;
|
||||
```
|
||||
|
||||
This will detect the string `jjoplmh` in the `cms` *GET* variable:
|
||||
```
|
||||
MainRule "str:jjoplmh" "msg:Possible Wordpress-Plugin-Backdoor detected" "mz:$ARGS_VAR:cms" "s:$UWA:8" id:42000347;
|
||||
```
|
||||
|
||||
naxsi_core.rules contains examples of rules. See as well mex's [[Doxi rules | https://bitbucket.org/lazy_dogtown/doxi-rules]] for more rules examples (doxi is third party rules that will focus on emerging threats).
|
||||
@@ -0,0 +1,21 @@
|
||||
# Unit Tests
|
||||
|
||||
Naxsi comes with [unit tests]( https://github.com/nbs-system/naxsi/tree/master/t ).
|
||||
This is very useful for people who wants to modify naxsi, build packages, test it on exotic setups, …
|
||||
We try to keep our [code coverage]( http://codecov.io/github/nbs-system/naxsi?branch=master ) as high as possible.
|
||||
|
||||
This is how you can run them:
|
||||
|
||||
1. Untar [nginx code source]( http://nginx.org/en/download.html ) in `/tmp/nginx/`.
|
||||
2. Setup naxsi for unit testing (from [naxsi_src]( https://github.com/nbs-system/naxsi/tree/master/naxsi_src )).
|
||||
* `make re` will compile naxsi to run from `/tmp/`
|
||||
* `make deploy ` will deploy a minimal naxsi in `/tmp/naxsi_ut/` (running on high port)
|
||||
* `make test` will run the unit tests
|
||||
3. It will give you a pass/fail result.
|
||||
4. Look at the resulting `/tmp/naxsicov.html/` to get a code coverage report.
|
||||
|
||||
If you're too lazy to run them, no worries, [travis-ci]( https://travis-ci.org/nbs-system/naxsi ) is running them for every pull-request that you'll submit!
|
||||
|
||||
## Coverity
|
||||
|
||||
[Coverity]( https://scan.coverity.com/projects/1883 ) is cool enough to allow open-source projects to use their cloud solutions for free. We do submit builds for every release. If you want to have access to detail results (ie. doing security assessment on naxsi), get in touch with us!
|
||||
@@ -0,0 +1,103 @@
|
||||
### BasicRule
|
||||
BasicRule(s) are present at the location's configuration level. It is (most of the time) used to create whitelists. BasicRule syntax is :
|
||||
|
||||

|
||||
|
||||
#### **wl:ID** (WhiteList)
|
||||
|
||||
Which rule ID(s) are whitelisted. Possible syntax are:
|
||||
|
||||

|
||||
|
||||
* `wl:0` : Whitelist all rules
|
||||
* `wl:42` : Whitelist rule `#42`
|
||||
* `wl:42,41,43` : Whitelist rules `42`, `41` and `43`
|
||||
* `wl:-42` : Whitelist all user rules (`>= 1000`), excepting rule `42`
|
||||
|
||||
|
||||
|
||||
#### **mz:** (MatchZones)
|
||||
|
||||

|
||||
|
||||
Specify the zones (see below) in which the exception is allowed. Existing Zones are the following :
|
||||
|
||||
- `ARGS`: GET args
|
||||
- `$ARGS_VAR `: named GET argument
|
||||
- `$ARGS_VAR_X`: regex matching the name of a GET argument
|
||||
- `HEADERS `: HTTP Headers
|
||||
- `$HEADERS_VAR ` : named HTTP header
|
||||
- `$HEADERS_VAR_X`: regex matching a named HTTP header
|
||||
- `BODY `: POST args (and RAW_BODY)
|
||||
- `$BODY_VAR `: named POST argument
|
||||
- `$BODY_VAR_X`: regex matching the name of a POST argument
|
||||
- `URL`: The URL (before '?')
|
||||
- `$URL`: The specified URL
|
||||
- `$URL_X`: regex matching the URL (before '?')
|
||||
- `FILE_EXT`: Filename (in a multipart POST containing a file)
|
||||
|
||||
### Whitelist Example
|
||||
|
||||
Totally disable rule #1000 for this location, matchzone is empty, so the whitelist always matches.
|
||||
|
||||
```
|
||||
BasicRule wl:1000;
|
||||
```
|
||||
|
||||
Disable rule #1000 on all url in GET argument named `foo`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR:foo";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in GET argument named `foo` for url `/bar`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR:foo|$URL:/bar";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET arguments for url `/bar`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$URL:/bar|ARGS";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET argument NAMES (only name, not content):
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:ARGS|NAME";
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
- A zone can be suffixed with `|NAME`, meaning the rule matched in the name of the variable, but not its content.
|
||||
- Both matchzone content and patterns (`rx:`/`str:`) must be in lower-case, as naxsi is case insensitive
|
||||
- `RAW_BODY` whitelists are written just as any `BODY` whitelist, see [[rulessyntax]]
|
||||
- A whitelist can't mix `_X` elements with `_VAR` or `$URL` items. ie:
|
||||
|
||||
```
|
||||
$URL_X:/foo|$ARGS_VAR:bar : WRONG
|
||||
$URL_X:^/foo$|$ARGS_VAR_X:^bar$ : GOOD
|
||||
```
|
||||
|
||||
### Regex Whitelist Examples
|
||||
|
||||
Available only in [naxsi 0.52]( https://github.com/nbs-system/naxsi/releases/tag/0.52 ) and later.
|
||||
|
||||
Disable rule `#1000` in all GET arguments containing `meh`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:meh";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in GET argument named `meh`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:^meh";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET arguments matching `meh_<number>`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:^meh_[0-9]+$"
|
||||
```
|
||||
@@ -0,0 +1,99 @@
|
||||
### BasicRule
|
||||
BasicRule(s) are present at the location's configuration level. It is (most of the time) used to create whitelists. BasicRule syntax is :
|
||||
|
||||
```
|
||||
BasicRule wl:ID [mz:[$URL:target_url]|[match_zone]|[$ARGS_VAR:varname]|[$BODY_VAR:varname]|[$HEADERS_VAR:varname]|[NAME]]
|
||||
```
|
||||
|
||||
#### **wl:ID** (WhiteList)
|
||||
|
||||
Which rule ID(s) are whitelisted. Possible syntax are:
|
||||
|
||||
* `wl:0` : Whitelist all rules
|
||||
* `wl:42` : Whitelist rule `#42`
|
||||
* `wl:42,41,43` : Whitelist rules `42`, `41` and `43`
|
||||
* `wl:-42` : Whitelist all user rules (`>= 1000`), excepting rule `42`
|
||||
|
||||
#### **mz:** (MatchZones)
|
||||
|
||||
Specify the zones (see below) in which the exception is allowed. Existing Zones are the following :
|
||||
|
||||
- `ARGS`: GET args
|
||||
- `$ARGS_VAR `: named GET argument
|
||||
- `$ARGS_VAR_X`: regex matching the name of a GET argument
|
||||
- `HEADERS `: HTTP Headers
|
||||
- `$HEADERS_VAR ` : named HTTP header
|
||||
- `$HEADERS_VAR_X`: regex matching a named HTTP header
|
||||
- `BODY `: POST args (and RAW_BODY)
|
||||
- `$BODY_VAR `: named POST argument
|
||||
- `$BODY_VAR_X`: regex matching the name of a POST argument
|
||||
- `URL`: The URL (before '?')
|
||||
- `$URL`: The specified URL
|
||||
- `$URL_X`: regex matching the URL (before '?')
|
||||
- `FILE_EXT`: Filename (in a multipart POST containing a file)
|
||||
|
||||
### Whitelist Example
|
||||
|
||||
Totally disable rule #1000 for this location, matchzone is empty, so the whitelist always matches.
|
||||
|
||||
```
|
||||
BasicRule wl:1000;
|
||||
```
|
||||
|
||||
Disable rule #1000 on all url in GET argument named `foo`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR:foo";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in GET argument named `foo` for url `/bar`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR:foo|$URL:/bar";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET arguments for url `/bar`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$URL:/bar|ARGS";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET argument NAMES (only name, not content):
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:ARGS|NAME";
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
- A zone can be suffixed with `|NAME`, meaning the rule matched in the name of the variable, but not its content.
|
||||
- Both matchzone content and patterns (`rx:`/`str:`) must be in lower-case, as naxsi is case insensitive
|
||||
- `RAW_BODY` whitelists are written just as any `BODY` whitelist, see [[rulessyntax]]
|
||||
- A whitelist can't mix `_X` elements with `_VAR` or `$URL` items. ie:
|
||||
|
||||
```
|
||||
$URL_X:/foo|$ARGS_VAR:bar : WRONG
|
||||
$URL_X:^/foo$|$ARGS_VAR_X:^bar$ : GOOD
|
||||
```
|
||||
|
||||
### Regex Whitelist Examples
|
||||
|
||||
Available only in [naxsi 0.52]( https://github.com/nbs-system/naxsi/releases/tag/0.52 ) and later.
|
||||
|
||||
Disable rule `#1000` in all GET arguments containing `meh`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:meh";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in GET argument named `meh`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:^meh";
|
||||
```
|
||||
|
||||
Disable rule `#1000` in all GET arguments matching `meh_<number>`:
|
||||
|
||||
```
|
||||
BasicRule wl:1000 "mz:$ARGS_VAR_X:^meh_[0-9]+$"
|
||||
```
|
||||
Reference in New Issue
Block a user