Install OWASP ModSecurity with Nginx 1.26 on Ubuntu 24.04

Install OWASP ModSecurity dengan Nginx 1.26 di Ubuntu 24.04

  • Update system dan install pre-requirement dependencies
apt update && apt upgrade -y
apt install git unzip gcc make build-essential autoconf automake libtool libcurl4-openssl-dev liblua5.3-dev libfuzzy-dev ssdeep gettext pkg-config libgeoip-dev libyajl-dev doxygen libpcre2-16-0 libpcre2-dev libpcre2-posix3 zlib1g zlib1g-dev libpcre3 libpcre3-dev libssl-dev -y

    • Downlaod ModSecurity source code
    git clone https://github.com/owasp-modsecurity/ModSecurity.git
    cd ModSecurity
    git submodule init && git submodule update
    • Compile modsecurity
    • Abaikan peringatan fatal*:
    ./build.sh
    ./configure
    make && make install

    • Download ModSecurity nginx connector
    cd ~
    git clone https://github.com/SpiderLabs/ModSecurity-nginx.git
    • Install nginx 1.26.1 dari source code
    wget https://nginx.org/download/nginx-1.26.1.tar.gz
    tar xfzv nginx-1.26.1.tar.gz
    useradd -r -M -s /sbin/nologin -d /usr/local/nginx nginx
    
    cd nginx-1.26.1
    ./configure --user=nginx --group=nginx --with-pcre-jit --with-debug --with-compat --with-http_ssl_module --with-http_realip_module --add-dynamic-module=/root/ModSecurity-nginx --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log
    make && make install
    ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
    • Cek versi nginx
    nginx -V
    ---<output>---
    nginx version: nginx/1.26.1
    built by gcc 13.2.0 (Ubuntu 13.2.0-23ubuntu4) 
    built with OpenSSL 3.0.13 30 Jan 2024
    TLS SNI support enabled
    configure arguments: --user=nginx --group=nginx --with-pcre-jit --with-debug --with-compat 
    --with-http_ssl_module --with-http_realip_module --add-dynamic-module=/root/ModSecurity-nginx 
    --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log
    • Copy sample file konfigurasi modsecurity
    cp -R ~/ModSecurity/modsecurity.conf-recommended /usr/local/nginx/conf/modsecurity.conf
    cp -R ~/ModSecurity/unicode.mapping /usr/local/nginx/conf/
    • Backup file konfigurasi nginx
    • Buat directiry untuk nginx conf
    cp /usr/local/nginx/conf/nginx.conf{,.bak}
    echo > /usr/local/nginx/conf/nginx.conf
    
    mkdir -p /usr/local/nginx/conf/conf.d
    mkdir -p /usr/local/nginx/conf/sites-enabled
    • Edit file konfigurasi nginx dengan modsecurity
    cat <<EOF | tee /usr/local/nginx/conf/nginx.conf
    load_module modules/ngx_http_modsecurity_module.so;
    user  nginx;
    worker_processes  1;
    pid        /run/nginx.pid;
    events {
        worker_connections  1024;
    }
    http {
        include mime.types;
        include /usr/local/nginx/conf/site-enabled/*;
        include /usr/local/nginx/conf/conf.d/*.conf;
    
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        server {
            listen       80;
            server_name  nginx.example.com;
            modsecurity  on;
            modsecurity_rules_file  /usr/local/nginx/conf/modsecurity.conf;
            access_log  /var/log/nginx/access_sys-ops-id.log;
            error_log  /var/log/nginx/error_sys-ops-id.log;
            location / {
                root   html;
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }
    EOF
    • Buat folder nginx log
    mkdir -p /var/log/nginx

    • Buat file service nginx
    cat <<EOF | tee /etc/systemd/system/nginx.service
    [Unit]
    Description=The nginx HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Type=forking
    PIDFile=/run/nginx.pid
    ExecStartPre=/usr/bin/rm -f /run/nginx.pid
    ExecStartPre=/usr/sbin/nginx -t
    ExecStart=/usr/sbin/nginx
    ExecReload=/bin/kill -s HUP $MAINPID
    KillSignal=SIGQUIT
    TimeoutStopSec=5
    KillMode=mixed
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target
    EOF
    • Buat symbolic link untuk nginx
    • Reoad systemd dan aktifkan service nginx, pastikan service nginx running
    ln -s /usr/local/nginx/sbin/nginx /usr/sbin/
    systemctl daemon-reload
    systemctl enable --now nginx
    systemctl status nginx

    • Aktifkan ModSecurity pada Nginx
    sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /usr/local/nginx/conf/modsecurity.conf
    sed -i 's#/var/log/modsec_audit.log#/var/log/nginx/modsec_audit.log#' /usr/local/nginx/conf/modsecurity.conf

    • Install OWASP v4.3.0 rule set
    wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v4.3.0.zip
    unzip v4.3.0.zip
    mv coreruleset-4.3.0/ /usr/local/nginx/conf/owasp-crs
    
    cp /usr/local/nginx/conf/owasp-crs/crs-setup.conf{.example,}
    echo -e "Include owasp-crs/crs-setup.conf\nInclude owasp-crs/rules/*.conf" >> /usr/local/nginx/conf/modsecurity.conf
    • Verifikasi konfigurasi nginx, pastikan Syntax is OK
    • Restart service nginx
    nginx -t
    ---<output>---
    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
    
    systemctl restart nginx

    • Pengujian ModSecurity
    • Jalankan perintah berikut
    curl localhost/foo?username=1’%20or%20’1’%20=%20′
    ---<output>---
    <html>
    <head><title>403 Forbidden</title></head>
    <body>
    <center><h1>403 Forbidden</h1></center>
    <hr><center>nginx</center>
    </body>
    </html>
    • Cek log modsecurity
    tail -100 /var/log/nginx/modsec_audit.log
    ---<output>---
    ---TsghiwRH---A--
    [08/Jun/2024:08:26:01 +0000] 171783516113.855795 127.0.0.1 40840 127.0.0.1 80
    ---TsghiwRH---B--
    GET /foo?username=1’%20or%20’1’%20=%20′ HTTP/1.1
    Host: localhost
    User-Agent: curl/8.5.0
    Accept: */*
    
    ---TsghiwRH---D--
    
    ---TsghiwRH---E--
    <html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body>\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a
    
    ---TsghiwRH---F--
    HTTP/1.1 403
    Server: nginx
    Date: Sat, 08 Jun 2024 08:26:01 GMT
    Content-Length: 146
    Content-Type: text/html
    Connection: keep-alive
    
    ---TsghiwRH---H--
    ModSecurity: Warning. detected SQLi using libinjection. [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "46"] [id "942100"] [rev ""] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: s&sos found within ARGS:username: 1' or '1' = '"] [severity "2"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"] [hostname "127.0.0.1"] [uri "/foo"] [unique_id "171783516113.855795"] [ref "v18,21t:urlDecodeUni"]
    ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:BLOCKING_INBOUND_ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "222"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "0"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "127.0.0.1"] [uri "/foo"] [unique_id "171783516113.855795"] [ref ""]

        • Intergrasi dengan PHP dan virtualhost
        • Default konfigurasi nginx: /usr/local/nginx/conf/
        • Default root directory html nginx: /usr/local/nginx/html/
        • Install php dan php-fpm
        apt install php php-fpm -y
        • Buat directory untuk virtualhost domain lnmp.sys-ops.id.sideka.my.id di /var/www/lnmp.sys-ops.id.sideka.my.id dan download file web-test
        mkdir -p /var/www/lnmp.sys-ops.id.sideka.my.id
        git clone https://github.com/sideka-cloud/web-test.git
        cp -R web-test/* /var/www/lnmp.sys-ops.id.sideka.my.id/
        chown -R nginx:nginx /var/www/lnmp.sys-ops.id.sideka.my.id/
        • Buat file kongifurasi nginx untuk domain: lnmp.sys-ops.id.sideka.my.id
        nano /usr/local/nginx/conf/conf.d/lnmp.sys-ops.id.sideka.my.id.conf
        • Tambahkan baris berikut dibawah location / {
        • On = Enable , Off = Disable
               modsecurity  on;
               modsecurity_rules_file  /usr/local/nginx/conf/modsecurity.conf;
        server {
           listen 80;
           server_name lnmp.sys-ops.id.sideka.my.id;
           root /var/www/lnmp.sys-ops.id.sideka.my.id;
        
           location / {
               index index.php index.html index.htm;
               try_files $uri $uri/ /index.php?$args;
        
               modsecurity  on;
               modsecurity_rules_file  /usr/local/nginx/conf/modsecurity.conf;
           }
        
                 add_header Access-Control-Allow-Headers "ORIGIN, X-REQUESTED-WITH, CONTENT-TYPE";
                 add_header Access-Control-Allow-Origin "*";
                 add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
                 add_header X-Content-Type-Options "nosniff";
                 add_header X-Xss-Protection "1; mode=block";
                 add_header X-Frame-Options "SAMEORIGIN";
                 add_header Referrer-Policy strict-origin-when-cross-origin;
                 add_header Strict-Transport-Security "max-age=15552000; includeSubDomains;preload";
                 add_header Access-Control-Max-Age "60000";
                 add_header Permissions-Policy "microphone=(), geolocation=(self), fullscreen=()";
                 add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' http: https:; img-src 'self' data: https:; font-src 'self' data: https:; frame-src 'self' data: https: blob:";
        
                 proxy_hide_header X-Powered-By;
                 fastcgi_hide_header X-Powered-By;
                 server_tokens off;
        
                 gzip on;
                 gzip_proxied any;
                 gzip_types text/plain application/xml text/css text/js text/xml application/x-javascript text/javascript application/json application/xml+rss;
                 gzip_vary on;
        
                 location ~* /\.(?!well-known\/) {
                         deny all;
                 }
        
                 location ~\.(ini|log|conf|txt|bak|old)$ {
                         deny all;
                 }
        
           location ~ \.php$ {
              include /usr/local/nginx/conf/fastcgi_params;
              fastcgi_pass unix:/run/php/php8.3-fpm.sock;
              fastcgi_index index.php;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              include fastcgi_params;
              fastcgi_read_timeout 300;
              proxy_read_timeout 600;
           }
        }
        • Setting php-fpm
        • Edit file: /etc/php/8.3/fpm/pool.d/www.conf
        user = nginx
        group = nginx
        listen = /run/php/php8.3-fpm.sock
        listen.owner = nginx
        listen.group = nginx
        listen.allowed_clients = 127.0.0.1
        pm.max_children = 30
        pm.start_servers = 10
        pm.min_spare_servers = 10
        pm.max_spare_servers = 30
        pm.process_idle_timeout = 30s
        • Verifikasi konfigurasi nginx, pastikan OK dan tidak ada error
        nginx -t
        ---<output>---
        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
        • Restart nginx dan php-fpm
        systemctl restart nginx php8.3-fpm
        • Pengujian ModSecurity
        • http://ip_address_atau_domain/?id=1 and ‘c’=’c’
        • Cek log modsec_audit.log
        tail -100 /var/log/nginx/modsec_audit.log
        ---9DFdp0Ik---A--
        [08/Jun/2024:08:55:38 +0000] 17178369380.170957 114.142.173.21 56354 192.168.10.100 80
        ---9DFdp0Ik---B--
        GET /?id=1%20and%20%E2%80%98c%E2%80%99=%E2%80%99c%E2%80%99 HTTP/1.1
        Host: lnmp.sys-ops.id.sideka.my.id
        Connection: keep-alive
        Cache-Control: max-age=0
        Upgrade-Insecure-Requests: 1
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
        Accept-Encoding: gzip, deflate
        Accept-Language: en-US,en;q=0.9
        
        ---9DFdp0Ik---D--
        
        ---9DFdp0Ik---E--
        <html>\x0d\x0a<head><title>403 Forbidden</title></head>\x0d\x0a<body>\x0d\x0a<center><h1>403 Forbidden</h1></center>\x0d\x0a<hr><center>nginx</center>\x0d\x0a</body>\x0d\x0a</html>\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a<!-- a padding to disable MSIE and Chrome friendly error page -->\x0d\x0a
        
        ---9DFdp0Ik---F--
        HTTP/1.1 403
        Server: nginx
        Date: Sat, 08 Jun 2024 08:55:38 GMT
        Content-Length: 548
        Content-Type: text/html
        Connection: keep-alive
        
        ---9DFdp0Ik---H--
        ModSecurity: Warning. detected SQLi using libinjection. [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "46"] [id "942100"] [rev ""] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: 1&sos found within ARGS:id: 1 and 'c'='c'"] [severity "2"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-sqli"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/248/66"] [tag "PCI/6.5.2"] [hostname "192.168.10.100"] [uri "/"] [unique_id "17178369380.170957"] [ref "v9,21t:urlDecodeUni"]
        ModSecurity: Access denied with code 403 (phase 2). Matched "Operator `Ge' with parameter `5' against variable `TX:BLOCKING_INBOUND_ANOMALY_SCORE' (Value: `5' ) [file "/usr/local/nginx/conf/owasp-crs/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "222"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "0"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "192.168.10.100"] [uri "/"] [unique_id "17178369380.170957"] [ref ""]

        herdiana3389

        A system administrator with skills in system administration, virtualization, linux, windows, networking, cloud computing, container, etc.