WEB Server - NGINX NAXSI 설치 및 설정 - CentOS 7





    이번 포스팅에서는 WAF는 무엇이고 NGINX에 NAXSI 설치 및 사용법에 대해서 알아보도록 하겠습니다.





    이전 글 :


    서버와 클라이언트 그리고 HTTP - https://server-talk.tistory.com/291


    WEB Server - NGINX 알아보기 - https://server-talk.tistory.com/297

    WEB Server - NGINX Comfile 설치하기 - https://server-talk.tistory.com/301

    WEB Server - NGINX 서비스 제어 - https://server-talk.tistory.com/302

    WEB Server - NGINX 구성파일 및 기본설정 - CentOS 7 - https://server-talk.tistory.com/303

    WEB Server - NGINX HTTP 설정 - CentOS 7 - https://server-talk.tistory.com/304








     웹방화벽(Web Application Firewall, WAF) 알아보기





    웹 방화벽(Web Application Firewall, WAF)은 웹 어플리케이션 보안에 특화된 소프트웨어 입니다  




    대규모 서버를 구성되어 있는 곳은 위 그림처럼 웹서버 상단에 네트워크 방화벽과 웹 방화벽을 구성하여 보안적인 위협을 방어하는 용도로 사용됩니다

    네트워크 방화벽은 IP 차단, DDOS, VPN 등등 주로 쓰이며 웹 방화벽(Web Application Firewall, WAF)은 웹 어플리케이션 보안에 특화된 소프트웨어로 주로 XXS(Cross Site Scripting), SQL Injection 등등 보안 위협을 방어하기 위해 사용됩니다





    하지만 오버 트래픽으로 인한 WAF에서의 바이패스나 알려지지 않은 취약점(Zero-Day Attack) 등등으로 웹서버의 공격이 성사되었을때 보안적으로 위험합니다 그리고 WAF 같은 경우 공개되지 않는 솔루션이라서 알려 않은 취약점이 발견될 경우 추가하는데 까다로우며, 개인 서버를 운영하시는 분이라면 WAF는 가격적인 부담은 만만치 않습니다









     NAXSI 무엇인가?



    KISA에서 제공하는 ModSecurity가 Apache 전용으로 사용 많이 사용되지만 Nginx에 적용 방법는 공식적으로 지원되지 않아 사용하지 않는 추세입니다 그러나 운영 중인 서버에 다른 WAF 를 올릴 경우 문제의 발생 여지가 있어 Nginx에 ModSecurity를 올리는 경우는 있지만 권장하지 않습니다


    NAXSI는 웹서버용 WAF 이며, NAXSI는 Nginx Anti XSS(Cross Site Scripting) & SQL Injection의 약자 입니다.


    NAXSI의 약자만 봐도 알듯이 Nginx 전용 WAF 입니다 그러므로 Nginx와 NAXSI의 조합은 Nginx와 최적화되어 가볍고 빠릅니다.


    특징으로는 기본적으로 웹사이트 취약점과 알려진 패턴들이 99%가 적되어 있고 읽기 쉬운 패턴으로 구성되어 특정 규칙을 추가하는 것은 어렵지 않다고 알려져 있습니다

    그리고 오픈소스로 무료입니다









     NAXSI 설치하기



    기존 포스팅에서 NGINX 설치를 따라하셨다면 외람되지만 지워주시고 진행바랍니다.




    1) Nginx 설치 및 가동에 필요한 패키지 설치


    [root@nginx ~]# yum -y install pcre-devel libxml2-devel zlib zlib-devel openssl openssl-devel gcc g++ cpp gcc-c++ libxslt libxslt-devel php-gd libgd-dev gd gd-devel perl perl-ExtUtils-Embed geoip-devel unzip wget curl-devel patch
    




    2) PCRE 압축해제


    pcre-8.44.tar.gz

    [root@nginx ~]# tar zxf pcre-8.44.tar.gz
    




    3) zlib 압축해제


    zlib-1.2.11.tar.gz


    [root@nginx ~]# tar zxf zlib-1.2.11.tar.gz
    




    4) openssl 압축해제


    openssl-1.1.1g.tar.gz


    [root@nginx ~]# tar zxf openssl-1.1.1g.tar.gz
    




    5) NAXSI 다운로드 및 압축해제



    NAXSI 다운로드


    NAXSI GitHub URL : https://github.com/nbs-system/naxsi


    다운로드 URL : https://github.com/nbs-system/naxsi/archive/master.zip



    [root@nginx ~]# unzip naxsi-master.zip
    



    6) Nginx 소스트리 구성



    옵션 추가--add-module=../naxsi-master/naxsi_src/ 



    [root@nginx ~]# tar zxf nginx-1.18.0.tar.gz
    [root@nginx ~]# cd nginx-1.18.0
    [root@nginx nginx-1.18.0]# ./configure \
    --prefix=/usr/local/nginx \
    --user=nobody \
    --group=nobody \
    --with-openssl=../openssl-1.1.1g \
    --with-zlib=../zlib-1.2.11 \
    --with-pcre=../pcre-8.44 \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_xslt_module \
    --with-http_image_filter_module \
    --with-http_geoip_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-http_perl_module \
    --with-http_degradation_module \
    --with-http_gunzip_module \
    --with-http_auth_request_module \
    --with-http_v2_module \
    --add-module=../naxsi-master/naxsi_src/
    


    7) Nginx 설치시작


    [root@nginx nginx-1.18.0]# make && make install
    




    10) NAXSI 핵심(Core) 규칙 복사


    [root@nginx ~]# cp ../naxsi-master/naxsi_config/naxsi_core.rules /usr/local/nginx/conf
    


    FILE : /usr/local/nginx/conf/naxsi_core.rules


    ##################################
    ## INTERNAL RULES IDS:1-999     ##
    ##################################
    #@MainRule "msg:weird request, unable to parse" id:1;
    #@MainRule "msg:request too big, stored on disk and not parsed" id:2;
    #@MainRule "msg:invalid hex encoding, null bytes" id:10;
    #@MainRule "msg:unknown content-type" id:11;
    #@MainRule "msg:invalid formatted url" id:12;
    #@MainRule "msg:invalid POST format" id:13;
    #@MainRule "msg:invalid POST boundary" id:14;
    #@MainRule "msg:invalid JSON" id:15;
    #@MainRule "msg:empty POST" id:16;
    #@MainRule "msg:libinjection_sql" id:17;
    #@MainRule "msg:libinjection_xss" id:18;
    
    ##################################
    ## SQL Injections IDs:1000-1099 ##
    ##################################
    MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop" "msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;
    MainRule "str:\"" "msg:double quote" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8,$XSS:8" id:1001;
    MainRule "str:0x" "msg:0x, possible hex encoding" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:2" id:1002;
    ## Hardcore rules
    MainRule "str:/*" "msg:mysql comment (/*)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1003;
    MainRule "str:*/" "msg:mysql comment (*/)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1004;
    MainRule "str:|" "msg:mysql keyword (|)"  "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005;
    MainRule "str:&&" "msg:mysql keyword (&&)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1006;
    ## end of hardcore rules
    MainRule "str:--" "msg:mysql comment (--)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1007;
    MainRule "str:;" "msg:semicolon" "mz:BODY|URL|ARGS" "s:$SQL:4,$XSS:8" id:1008;
    MainRule "str:=" "msg:equal sign in var, probable sql/xss" "mz:ARGS|BODY" "s:$SQL:2" id:1009;
    MainRule "str:(" "msg:open parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1010;
    MainRule "str:)" "msg:close parenthesis, probable sql/xss" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1011;
    MainRule "str:'" "msg:simple quote" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$SQL:4,$XSS:8" id:1013;
    MainRule "str:," "msg:comma" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1015;
    MainRule "str:#" "msg:mysql comment (#)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1016;
    MainRule "str:@@" "msg:double arobase (@@)" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1017;
    
    ###############################
    ## OBVIOUS RFI IDs:1100-1199 ##
    ###############################
    MainRule "str:http://" "msg:http:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1100;
    MainRule "str:https://" "msg:https:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1101;
    MainRule "str:ftp://" "msg:ftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1102;
    MainRule "str:php://" "msg:php:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1103;
    MainRule "str:sftp://" "msg:sftp:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1104;
    MainRule "str:zlib://" "msg:zlib:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1105;
    MainRule "str:data://" "msg:data:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1106;
    MainRule "str:glob://" "msg:glob:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1107;
    MainRule "str:phar://" "msg:phar:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1108;
    MainRule "str:file://" "msg:file:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1109;
    MainRule "str:gopher://" "msg:gopher:// scheme" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$RFI:8" id:1110;
    
    #######################################
    ## Directory traversal IDs:1200-1299 ##
    #######################################                                          
    MainRule "str:.." "msg:double dot" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1200;
    MainRule "str:/etc/passwd" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1202;
    MainRule "str:c:\\" "msg:obvious windows path" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1203;
    MainRule "str:cmd.exe" "msg:obvious probe" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1204;
    MainRule "str:\\" "msg:backslash" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:4" id:1205;
    #MainRule "str:/" "msg:slash in args" "mz:ARGS|BODY|$HEADERS_VAR:Cookie" "s:$TRAVERSAL:2" id:1206;
    
    ########################################
    ## Cross Site Scripting IDs:1300-1399 ##
    ########################################
    MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302;
    MainRule "str:>" "msg:html close tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1303;
    MainRule "str:[" "msg:open square backet ([), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1310;
    MainRule "str:]" "msg:close square bracket (]), possible js" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1311;
    MainRule "str:~" "msg:tilde (~) character" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$XSS:4" id:1312;
    MainRule "str:`"  "msg:grave accent (`)" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1314;
    MainRule "rx:%[23]."  "msg:double encoding" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1315;
    
    ####################################
    ## Evading tricks IDs: 1400-1500 ##
    ####################################
    MainRule "str:&#" "msg:utf7/8 encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1400;
    MainRule "str:%U" "msg:M$ encoding" "mz:ARGS|BODY|URL|$HEADERS_VAR:Cookie" "s:$EVADE:4" id:1401;
    
    #############################
    ## File uploads: 1500-1600 ##
    #############################
    MainRule "rx:\.ph|\.asp|\.ht" "msg:asp/php file upload" "mz:FILE_EXT" "s:$UPLOAD:8" id:1500;
    





    11) NAXSI 사이트 규칙 생성


    FILE : /usr/local/nginx/conf/naxsi.rules


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


    위 내용을 파일로 생성합니다






    12) NAXSI 규칙 적용



    위 그림과 같이 NAXSI 핵심 규칙은 HTTP 블록에 사이트 규칙은 SERVER 블록에 인클루드 하셔야 됩니다.


    user nobody;
    worker_processes 1;
    events {
        worker_connections 1024;
    }
    
    http {
        include mime.types;
        include /usr/local/nginx/conf/naxsi_core.rules;
        default_type application/octet-stream;
    
        access_log off;
    
        sendfile on;
        keepalive_timeout 65;
        tcp_nodelay on;
        gzip on;
        gzip_disable "MSIE [1-6].(?!.*SV1)";
    
        server {
           listen	192.168.85.177:80;
           server_name	server-talk.com;
           root	/home/server_talk/public_html;
    
            access_log  /usr/local/nginx/logs/server-talk.com.access.log;
            error_log   /usr/local/nginx/logs/server-talk.com.error.log;
    
    
           location / {
              include /usr/local/nginx/conf/naxsi.rules;
              index index.html index.htm;
              error_log  server-talk.com_naxsi_err.log;
           }
    
           error_page 500 502 503 504 /usr/local/nginx/html/50x.html;
    
           location = /usr/local/nginx/html/50x.html {
              root html;
           }
        }
    }
    


    위 코드와 같이 HTTP 블록은 naxsi.rules 파일을 SERVER 블록은 naxsi_core.rules 파일을 인클루드 하셔야 됩니다.





    13) NAXSI 규칙 적용 테스트 후 적용



    [root@nginx conf]# /usr/local/nginx/sbin/nginx -t
    nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
    nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
    [root@nginx conf]# /usr/local/nginx/sbin/nginx -s reload
    


    Posted by Server-talk 서버이야기