How to setup naxsi for nginx
2013-06-13 03:11
330 查看
This document describes the full process of configuring NAXSI.
Debian
FreeBSD
NetBSD
OpenBSD
However, beware, naxsi is a young & fast evolving project, building from latest source code release is recommended.
If you plan to do so, refer to source compilation.
If you're not, here is the way to go :
[install libpcre (and libssl if you want https, along with zlib for gzip support) libs with your favorite package
manager, naxsi relies on it for regex]
my personal "building" options being, here :
Important note for source compilation
You need to remember this if you are new to nginx : NGINX will decide the order of modules according the order of the module's directive in nginx's ./configure, take care not to have another similar module before.
www.nbs-system.com
So, let's have a look at the initial setup :
/etc/nginx/nginx.conf :
Notice the /etc/nginx/naxsi_core.rules include. This file is provided in the project (naxsi_config/), and it contains the rules. As you might have noticed, these are not signatures, in the classic WAF sense, but simple "score rules".
Now, let's have a look at my sites-enabled/default :
/etc/nginx/nbs.rules :
Learning Daemons will be able to parse those events to extract whitelists and reports. (see nx_util)
Whitelist generation : Main goal of the daemon. From naxsi catched exceptions, generate appropriate whitelists. Rules are presented in raw form, as well as in optimized form. For example, after some browsing I got the following
rules :
Statistics generation : You can get reports on source / types of attacks, as well as counts for each kind of exceptions :
The global idea, indeed, is to use the whitelists generated by naxsi, include them into your naxsi's configuration, and then reload nginx.
For advanced whitelists, such as user forms, please see AdvancedWhitelists section. Following section deals as well with user
forms in a more classic way.
Yes, fields with 'free' user input, such as registration forms, search boxes and so on are typically parts that you should take a great care of.
For example, my company's website contains a "contact" form with lastname, firstname, email adress, and a free text zone. I decided that I will allow simple/double quotes as well as coma and semi-coma in the last/first names fields, and included
as well parenthesis for the free text zone. So, I will simply fill the form and learnign daemons will generate the associated whitelists.
Once I've filled the forms, if I look at the generated whitelists, I will see that new exceptions have been generated :
Let's reload it, and have a look at the generated whitelists ! New rules have been generated, in the style :
Once I've did the same for the searchbox, my configuration is now over, and we can browse the site, and fill the forms without generating any new exception !
Then, you can "simply" define another location, where you don't enable NAXSI :
And the trick is done ;)
Actually, you can do something way smarter. As wordpress is affected by numerous vulnerabilities in the back-office, I still want to protect it, but without spending too much time on the configuration, so here is what I'm doing :
I'm enabling NAXSI, but I'm disabling all checks on BODY, as it's the painfull part (posting HTML and so on). In this way, I will still protect WP back-office from vulnerabilities that are exploited through GET requests.
Installing nginx + naxsi : From package
Packages of naxsi exist in official repositories for :Debian
FreeBSD
NetBSD
OpenBSD
However, beware, naxsi is a young & fast evolving project, building from latest source code release is recommended.
If you plan to do so, refer to source compilation.
Installing nginx + naxsi : From sources
Nginx doesn't support (by design) loadable modules. Extra modules must be added during compilation. Here we will install it from the source, but (if you're lucky) you might as well find nginx+naxsi already packaged in your favorite distribution.If you're not, here is the way to go :
wget http://nginx.org/download/nginx-x.x.xx.tar.gz wget http://naxsi.googlecode.com/files/naxsi-x.xx.tar.gz tar xvzf nginx-x.x.xx.tar.gz tar xvzf naxsi-x.xx.tar.gz cd nginx-x.x.xx/
[install libpcre (and libssl if you want https, along with zlib for gzip support) libs with your favorite package
manager, naxsi relies on it for regex]
./configure --add-module=../naxsi-x.xx/naxsi_src/ [add/remove your favorite/usual options] make make install
my personal "building" options being, here :
./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 note for source compilation
You need to remember this if you are new to nginx : NGINX will decide the order of modules according the order of the module's directive in nginx's ./configure, take care not to have another similar module before.
Initial setup
I want to configure NAXSI for my company's website :www.nbs-system.com
So, let's have a look at the initial setup :
/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 /etc/nginx/naxsi_core.rules include. This file is provided in the project (naxsi_config/), and it contains the rules. As you might have noticed, these are not signatures, in the classic WAF sense, but simple "score rules".
Now, let's have a look at my sites-enabled/default :
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/nbs.rules; proxy_pass http://194.213.124.111/; proxy_set_header Host www.nbs-system.com; } #This location is where, in learning mode, to-be-forbidden requests will be "copied" #In non-learning mode, it's where denied request will land, so feel free to do whatever you want, #return 418 I'm a teapot, forward to a custom webpage with #a captcha to help track false-positives (see contrib for that), #whatever you want to do ! location /RequestDenied { return 500; } }
/etc/nginx/nbs.rules :
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;
Starting the LearningMode phase
While browsing your site, events will be generated by naxsi. But, as you are in learning mode, the requests wont be blocked. Those events are outputed in nginx's error_log.Learning Daemons will be able to parse those events to extract whitelists and reports. (see nx_util)
Whitelist generation : Main goal of the daemon. From naxsi catched exceptions, generate appropriate whitelists. Rules are presented in raw form, as well as in optimized form. For example, after some browsing I got the following
rules :
########### Optimized Rules Suggestion ################## # total_count:59 (23.69%), peer_count:1 (100.0%) | parenthesis, probable sql/xss BasicRule wl:1011 "mz:$HEADERS_VAR:cookie"; # total_count:59 (23.69%), peer_count:1 (100.0%) | parenthesis, probable sql/xss BasicRule wl:1010 "mz:$HEADERS_VAR:cookie"; # total_count:59 (23.69%), peer_count:1 (100.0%) | mysql keyword (|) BasicRule wl:1005 "mz:$HEADERS_VAR:cookie"; # total_count:53 (21.29%), peer_count:1 (100.0%) | double encoding ! BasicRule wl:1315 "mz:$HEADERS_VAR:cookie";
Statistics generation : You can get reports on source / types of attacks, as well as counts for each kind of exceptions :
The global idea, indeed, is to use the whitelists generated by naxsi, include them into your naxsi's configuration, and then reload nginx.
For advanced whitelists, such as user forms, please see AdvancedWhitelists section. Following section deals as well with user
forms in a more classic way.
user forms
Now comes the "tricky" part of whitelists triggers : USER FORMS !Yes, fields with 'free' user input, such as registration forms, search boxes and so on are typically parts that you should take a great care of.
For example, my company's website contains a "contact" form with lastname, firstname, email adress, and a free text zone. I decided that I will allow simple/double quotes as well as coma and semi-coma in the last/first names fields, and included
as well parenthesis for the free text zone. So, I will simply fill the form and learnign daemons will generate the associated whitelists.
Once I've filled the forms, if I look at the generated whitelists, I will see that new exceptions have been generated :
rule 1007(--) authorized on url for argument 'cf2_field_1' of zone BODY rule 1010(() authorized on url for argument 'cf2_field_1' of zone BODY rule 1011()) authorized on url for argument 'cf2_field_1' of zone BODY rule 1013(') authorized on url for argument 'cf2_field_1' of zone BODY rule 1015(,) authorized on url for argument 'cf2_field_1' of zone BODY rule 1306(') authorized on url for argument 'cf2_field_1' of zone BODY rule 1308(() authorized on url for argument 'cf2_field_1' of zone BODY rule 1309()) authorized on url for argument 'cf2_field_1' of zone BODY rule 1007(--) authorized on url for argument 'cf2_field_2' of zone BODY rule 1013(') authorized on url for argument 'cf2_field_2' of zone BODY rule 1015(,) authorized on url for argument 'cf2_field_2' of zone BODY rule 1306(') authorized on url for argument 'cf2_field_2' of zone BODY rule 1007(--) authorized on url for argument 'cf2_field_3' of zone BODY rule 1013(') authorized on url for argument 'cf2_field_3' of zone BODY rule 1015(,) authorized on url for argument 'cf2_field_3' of zone BODY rule 1306(') authorized on url for argument 'cf2_field_3' of zone BODY rule 1007(--) authorized on url for argument 'cf2_field_4' of zone BODY rule 1007(--) authorized on url for argument 'cf2_field_5' of zone BODY rule 1007(--) authorized on url for argument 'cf2_field_7' of zone BODY rule 1010(() authorized on url for argument 'cf2_field_7' of zone BODY rule 1011()) authorized on url for argument 'cf2_field_7' of zone BODY rule 1013(') authorized on url for argument 'cf2_field_7' of zone BODY rule 1015(,) authorized on url for argument 'cf2_field_7' of zone BODY rule 1306(') authorized on url for argument 'cf2_field_7' of zone BODY rule 1308(() authorized on url for argument 'cf2_field_7' of zone BODY rule 1309()) authorized on url for argument 'cf2_field_7' of zone BODY rule 1007(--) authorized on url for argument 'cf_codeerr2' of zone BODY rule 1315() authorized on url for argument 'cf_codeerr2' of zone BODY rule 1315() authorized on url for argument 'cf_failure2' of zone BODY rule 1200(..) authorized on url for argument 'cf_working2' of zone BODY rule 1315() authorized on url for argument 'cf_working2' of zone BODY
Let's reload it, and have a look at the generated whitelists ! New rules have been generated, in the style :
BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1010 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1011 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1013 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1015 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1306 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1308 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1309 "mz:$BODY_VAR:cf2_field_1" ; BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_2" ; BasicRule wl:1013 "mz:$BODY_VAR:cf2_field_2" ; BasicRule wl:1015 "mz:$BODY_VAR:cf2_field_2" ; BasicRule wl:1306 "mz:$BODY_VAR:cf2_field_2" ; BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_3" ; BasicRule wl:1013 "mz:$BODY_VAR:cf2_field_3" ; BasicRule wl:1015 "mz:$BODY_VAR:cf2_field_3" ; BasicRule wl:1306 "mz:$BODY_VAR:cf2_field_3" ; BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_4" ; BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_5" ; BasicRule wl:1007 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1010 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1011 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1013 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1015 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1306 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1308 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1309 "mz:$BODY_VAR:cf2_field_7" ; BasicRule wl:1007 "mz:$BODY_VAR:cf_codeerr2" ; BasicRule wl:1315 "mz:$BODY_VAR:cf_codeerr2" ; BasicRule wl:1315 "mz:$BODY_VAR:cf_failure2" ; BasicRule wl:1200 "mz:$BODY_VAR:cf_working2" ; BasicRule wl:1315 "mz:$BODY_VAR:cf_working2" ;
Once I've did the same for the searchbox, my configuration is now over, and we can browse the site, and fill the forms without generating any new exception !
Some side notes
Sometimes, you will want to partially disable naxsi for a part of the website. In the case of my company's website, I don't want to configure / enable naxsi for the wordpress back-office, as it's already protected by a .htaccess.Then, you can "simply" define another location, where you don't enable NAXSI :
location / { include /etc/nginx/nbs.rules; proxy_pass http://194.213.124.111/; proxy_set_header Host www.nbs-system.com; } location /wp-admin { proxy_pass https://194.213.124.111/; proxy_set_header Host www.nbs-system.com; }
And the trick is done ;)
Actually, you can do something way smarter. As wordpress is affected by numerous vulnerabilities in the back-office, I still want to protect it, but without spending too much time on the configuration, so here is what I'm doing :
location /wp-admin { include /etc/nginx/nbs.rules; BasicRule wl:0 mz:BODY; proxy_pass https://194.213.124.111; proxy_set_header Host www.nbs-system.com; }
I'm enabling NAXSI, but I'm disabling all checks on BODY, as it's the painfull part (posting HTML and so on). In this way, I will still protect WP back-office from vulnerabilities that are exploited through GET requests.
相关文章推荐
- How to Setup Cordova for Windows 7
- HOWTO django + celery + rabbitmq simple setup for testing purpose
- how to write a nginx module for http living stream
- How to setup build service for s…
- How to Cluster Magento, nginx and MySQL on Multiple Servers for High Availability
- How to setup linked servers for SQL Server and Oracle 64 bit client
- How to convert Java Key Store file to pem/key for nginx
- HOWTO install and setup Android NDK for Windows(Android NDK 开发环境安装和配置)
- How to setup and configure Sonar for Groovy projects
- how to setup c develop environment for windows
- 转自 https://www.digitalocean.com/community/articles/how-to-create-a-ssl-certificate-on-nginx-for-cent
- how to create an ssl certificate on nginx for ubuntu14.04
- (Step by Step)How to setup IP Phone Server(VoIP Server) for free.
- How to setup Windows Desktop wallet for Token Pay?
- HOWTO install and setup Android NDK for Windows(Android NDK 开发环境安装和配置)
- How to Setup OpenStack to use Local Disks for Instances
- How to download and install setuptools module for Python
- HOWTO install and setup Android NDK for Linux(Android NDK安装遇到的问题和解决方法)
- How to setup a new Organization and Set of Books for a Payables Responsibility
- [GUIDE] How to Setup Ubuntu 16.04 LTS Xenial Xerus for Compiling Android ROMs