Beranda Blog Store
Cyber Security

Memasang WAF ModSecurity dengan OWASP Core Rule Set di Nginx: Instalasi, Penyetelan, dan Menangani Positif Palsu

23 Agu 2026 Hartono 5 menit baca 8 Dilihat

Halo, Rekan ArtonLabs. Ini artikel penutup dari 21 tulisan teknis hari ini, dan sengaja kami tutup dengan lapisan pertahanan yang paling sering dipasang lalu dimatikan karena salah setel.

Web Application Firewall menyaring permintaan berbahaya sebelum sampai ke aplikasi: injeksi SQL, XSS, pemindaian otomatis, dan pola serangan umum lainnya. ModSecurity v3 dengan OWASP Core Rule Set adalah kombinasi open source yang paling mapan, dan bisa dipasang di Nginx pada Ubuntu 24.04. Prosesnya lebih panjang dari apt install karena modul Nginx-nya harus dibangun dari sumber, tetapi hasilnya layak. Tulisan ini memandu pemasangan, pengaktifan, dan bagian yang paling penting: menyetel agar ia tidak memblokir pengguna yang sah.

Daftar Isi

Gambaran: libmodsecurity, Konektor, dan CRS

Ada tiga bagian. libmodsecurity adalah mesin yang mengevaluasi aturan. Konektor Nginx (ModSecurity-nginx) adalah modul dinamis yang menghubungkan mesin itu ke Nginx, dan harus dibangun terhadap versi Nginx yang persis sama dengan yang terpasang. OWASP Core Rule Set adalah kumpulan aturannya; tanpa CRS, ModSecurity hanya mesin kosong. Pengembang VinzaPanel membungkus seluruh rangkaian ini ke dalam plugin WAF yang dipasang sekali klik; di sini kita lihat apa yang dilakukannya.

Membangun libmodsecurity

sudo apt update && sudo apt install -y 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-dev libpcre2-posix3 zlib1g-dev git
cd /opt && sudo git clone https://github.com/owasp-modsecurity/ModSecurity.git
cd ModSecurity
sudo git submodule init && sudo git submodule update
sudo ./build.sh
sudo ./configure
sudo make -j$(nproc)
sudo make install

Kompilasi memakan beberapa menit di VPS kecil. Hasilnya pustaka di /usr/local/modsecurity/. Kalau configure mengeluh kekurangan pustaka, pesannya biasanya menyebut nama paket yang kurang; pasang dan ulangi.

Membangun Modul Nginx

Modul harus dibangun terhadap sumber Nginx dengan versi yang sama persis dengan yang terpasang. Periksa dulu:

nginx -v            # misalnya nginx/1.26.3
cd /opt && sudo git clone https://github.com/owasp-modsecurity/ModSecurity-nginx.git
sudo wget https://nginx.org/download/nginx-1.26.3.tar.gz
sudo tar -xzf nginx-1.26.3.tar.gz && cd nginx-1.26.3
sudo ./configure --with-compat --add-dynamic-module=/opt/ModSecurity-nginx
sudo make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules-enabled/

Sesuaikan nomor versi dengan keluaran nginx -v Anda. --with-compat membuat modul kompatibel dengan binary Nginx dari paket. Setelah Nginx diperbarui ke versi baru oleh apt, modul ini harus dibangun ulang; itu harga dari modul dinamis pihak ketiga, dan alasan untuk menyematkan versi paket Nginx atau menjadwalkan pembangunan ulang.

Mengaktifkan di Nginx

sudo cp /opt/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsecurity.conf
sudo cp /opt/ModSecurity/unicode.mapping /etc/nginx/unicode.mapping

Di baris paling atas /etc/nginx/nginx.conf, sebelum blok events:

load_module /etc/nginx/modules-enabled/ngx_http_modsecurity_module.so;

Di /etc/nginx/modsecurity.conf, ubah SecRuleEngine DetectionOnly menjadi SecRuleEngine On saat Anda siap memblokir; untuk minggu pertama, biarkan DetectionOnly agar hanya mencatat. Lalu di blok server atau lokasi situs yang ingin dilindungi:

modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity.conf;

Memasang OWASP Core Rule Set

sudo git clone https://github.com/coreruleset/coreruleset.git /etc/nginx/owasp-crs
sudo cp /etc/nginx/owasp-crs/crs-setup.conf.example /etc/nginx/owasp-crs/crs-setup.conf

Tambahkan di akhir /etc/nginx/modsecurity.conf:

Include owasp-crs/crs-setup.conf
Include owasp-crs/rules/*.conf
sudo nginx -t && sudo systemctl reload nginx

CRS memakai model skor anomali: tiap aturan yang cocok menambah skor, dan permintaan diblokir kalau skornya melewati ambang. Ambang dan tingkat paranoia diatur di crs-setup.conf. Tingkat paranoia 1 (bawaan) menangkap serangan umum dengan positif palsu minimal; tingkat 2 sampai 4 makin ketat dan makin sering salah menangkap. Mulailah dari 1.

Menguji

curl -s -o /dev/null -w '%{http_code}\n' 'https://contoh.com/?q=/bin/bash'
curl -s -o /dev/null -w '%{http_code}\n' "https://contoh.com/?id=1' OR '1'='1"
sudo tail -f /var/log/modsec_audit.log

Dengan SecRuleEngine On, keduanya harus mendapat 403. Dengan DetectionOnly, permintaan lolos tetapi tercatat di log audit beserta aturan mana yang cocok. Log ini panjang dan rinci; nilainya justru di situ.

Menangani Positif Palsu

Ini bagian yang membedakan WAF yang berguna dari WAF yang dimatikan setelah seminggu. Jalankan dalam mode deteksi selama satu atau dua minggu pada lalu lintas nyata, lalu baca log: aturan mana yang sering cocok pada permintaan yang jelas sah? Biasanya editor teks kaya (isi HTML dianggap XSS), unggahan berkas, dan parameter yang berisi SQL atau kode secara sah, misalnya aplikasi untuk pengembang. Untuk tiap kasus, buat pengecualian yang sesempit mungkin di berkas sebelum aturan CRS dimuat:

# /etc/nginx/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
SecRule REQUEST_URI "@beginsWith /admin/artikel/" \
    "id:1001,phase:1,pass,nolog,ctl:ruleRemoveTargetById=941100;ARGS:isi"

Aturan itu mematikan satu aturan XSS tertentu hanya untuk parameter isi pada jalur admin artikel, bukan mematikan seluruh WAF untuk jalur itu. Catat setiap pengecualian beserta alasannya. Setelah log bersih dari positif palsu, naikkan ke SecRuleEngine On, dan terus pantau log audit seminggu sekali. Di VinzaPanel, tingkat paranoia dan ambang skor diatur dari halaman plugin WAF, dan log auditnya dibaca dari panel.

Aturan Sendiri

# memblokir user-agent pemindai yang sering muncul di log
SecRule REQUEST_HEADERS:User-Agent "@pmFromFile /etc/nginx/ua-blokir.txt"     "id:1002,phase:1,deny,status:403,log,msg:'UA pemindai'"

# batasi ukuran body untuk jalur API tertentu
SecRule REQUEST_URI "@beginsWith /api/"     "id:1003,phase:1,pass,ctl:requestBodyLimit=1048576"

Aturan kustom diberi id di luar rentang CRS (CRS memakai 900000 ke atas) dan ditaruh di berkas sebelum atau sesudah CRS sesuai kebutuhan. Jaga jumlahnya sedikit dan terdokumentasi; WAF yang penuh aturan buatan sendiri menjadi sulit dipahami oleh orang berikutnya.

Kinerja

Dengan CRS tingkat paranoia 1, beban tambahan per permintaan biasanya hanya beberapa milidetik, tidak terasa untuk aplikasi web biasa. Yang mahal adalah pemeriksaan body permintaan besar dan log audit yang mencatat segalanya. Batasi SecRequestBodyLimit sesuai kebutuhan, matikan pemeriksaan body untuk jalur unggahan berkas besar, dan atur SecAuditEngine RelevantOnly agar hanya permintaan yang cocok aturan yang dicatat. Rotasi modsec_audit.log dengan logrotate; tanpa itu ia tumbuh cepat di situs yang ramai.

Penutup

WAF bukan pengganti kode yang aman, dan CRS akan salah menangkap kalau langsung dinyalakan dalam mode blokir. Tetapi dipasang dengan sabar, mulai dari mode deteksi, tingkat paranoia rendah, dan pengecualian yang sempit, ModSecurity dengan CRS menghentikan sebagian besar serangan otomatis sebelum menyentuh aplikasi Anda, dan log auditnya memberi gambaran yang jujur tentang apa yang setiap hari mengetuk pintu.

Terima kasih sudah mengikuti rangkaian ini sampai akhir, Rekan ArtonLabs. Usulan topik untuk rangkaian berikutnya kami tunggu lewat halaman kontak.