wargio / naxsi

NAXSI is an open-source, high performance, low rules maintenance WAF for NGINX
GNU General Public License v3.0
305 stars 38 forks source link

Does not validate the headers #129

Closed LegendaryVasya closed 9 months ago

LegendaryVasya commented 9 months ago

Hi. i have next simple+default setup of NAXSI v1.6 like reverse proxy on ubuntu 22.04 LTS

cat /etc/nginx/sites-available/default

location / {
             include /etc/nginx/naxsi.rules;
             proxy_pass http://127.0.0.1:1234/;
}

location /RequestDenied {
             return 403;
}
cat /etc/nginx/nginx.conf

load_module modules/ngx_http_naxsi_module.so;

http {
        include /etc/nginx/naxsi_core.rules;
}

In naxsi.rules i set

SecRulesEnabled; DeniedUrl "/RequestDenied";

CheckRule "$SQL >= 8" BLOCK; CheckRule "$RFI >= 8" BLOCK; CheckRule "$TRAVERSAL >= 4" BLOCK; СheckRule "$UPLOAD >= 4" BLOCK; CheckRule "$EVADE >= 4" BLOCK; CheckRule "$XSS >= 8" BLOCK;

i also try set $HEADERS. But NAXSI does not block malisious requests

Some example, i used wfuzz with payloads wordlist. wfuzz -w wordlist.txt -f output_fuzz_2,csv -H "Referer: FUZZ" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36" -p 127.0.0.1:8081 http://192.168.0.67/test?param=1

GET / HTTP/1.1
Host: 192.168.0.67
Accept: */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Referer: <script>alert(1)</script>
Connection: close

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Fri, 01 Mar 2024 22:04:20 GMT
Content-Type: text/html
Connection: close
Content-Length: 117
<html>

Filter does not work through all payloads in the header. Another example

GET /test?param=1 HTTP/1.1
Host: 192.168.0.67
Accept: */*
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36
Referer: &ltscript&gtalert(document.cookie);&ltscript&gtalert
Connection: close

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Fri, 01 Mar 2024 21:41:34 GMT
Content-Type: text/html
Connection: close
Content-Length: 129

But when using a payload in the URL or in the body, the filter is triggered

LegendaryVasya commented 9 months ago

I'm probably an idiot, but it's better to ask

wargio commented 9 months ago

could you try with some newer version of NGINX just to rule out that is a bug in naxsi?

wargio commented 9 months ago

add these and the checkrules.

   LibInjectionSql;
   LibInjectionXss;
   CheckRule "$SQL >= 8" BLOCK;
   CheckRule "$XSS >= 8" BLOCK;
wargio commented 9 months ago

Ok, i tested it on various versions. it's because you didn't enable the flags in the previous post.

test:


=== TEST 5 - regression on Referer
--- main_config
load_module $TEST_NGINX_NAXSI_MODULE_SO;
--- http_config
include $TEST_NGINX_NAXSI_RULES;
--- config
set $naxsi_json_log 1;
location / {
   SecRulesEnabled;
   LibInjectionSql;
   LibInjectionXss;
   DeniedUrl "/RequestDenied";

   CheckRule "$SQL >= 8" BLOCK;
   CheckRule "$RFI >= 8" BLOCK;
   CheckRule "$TRAVERSAL >= 5" BLOCK;
   CheckRule "$UPLOAD >= 5" BLOCK;
   CheckRule "$XSS >= 8" BLOCK;
   CheckRule "$UWA >= 8" DROP;
   CheckRule "$EVADE >= 8" BLOCK;
   CheckRule "$LOG >= 1" LOG;

   root $TEST_NGINX_SERVROOT/html/;
   index index.html index.htm;
   error_page 405 = $uri;
}
location /RequestDenied {
    return 412;
}
--- raw_request eval
"GET / HTTP/1.1\r
Host: 127.0.0.1\r
Accept: */*\r
Content-Type: application/x-www-form-urlencoded\r
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.107 Safari/537.36\r
Referer: <script>alert(1)</script>\r
Connection: close\r
Content-Length: 0\r
\r
\r
"
--- error_code: 412

With LibInjectionSql, LibInjectionXss, CheckRule "$XSS >= 8" BLOCK; & CheckRule "$SQL >= 8" BLOCK;

2024/03/02 12:42:02 [error] 256019#0: *1 {"ip":"127.0.0.1","server":"127.0.0.1","uri":"/","config":"block","rid":"856baa3d8989b53b2ef6fe1df81e5a58","cscore0":"$LIBINJECTION_XSS","score0":"8","zone0":"HEADERS","id0":"18","var_name0":"referer"}, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "127.0.0.1", referrer: "<script>alert(1)</script>"

Without those returns 200.

LegendaryVasya commented 9 months ago

Is that everything works only with the included library libinjection? I thought libinjection is addition not a main thing which implements safety

wargio commented 9 months ago

it like that because they might return a lot of FP. so it can be enabled/disabled at need. but yeah, i agree, they should be enabled by default.

LegendaryVasya commented 9 months ago

May i ask? Why do you not control all headers in default naxsi rules. As I understand, you parse all headers, but only check 'Cookies'. That is, why not determine basic validation by using regular expressions for each header (use HEADERS Instead of HEADERS_VAR) in the core rules?

wargio commented 9 months ago

the headers are checked depending on the rule you implement. specifically you had an xss which was checked only by libxss

LegendaryVasya commented 9 months ago

the headers are checked depending on the rule you implement. specifically you had an xss which was checked only by libxss

Nah, i am about, why not be made rules for each headers in naxsi_core.rules by default, use may be regex to reduce false positives or something else without use libinjection, because libinjection does not cover all possible payloads(only XSS or SQL)

wargio commented 9 months ago

because as for any waf, you will either have a high false positive rate or low positive rate.