Lewati ke konten

Shield Corev1.2.x

Aturan (Rules)

Rule adalah satu-satunya cara Shield mengenali serangan yang dikenal. Semuanya deterministik: rule cocok atau tidak cocok, tidak ada tebakan.

[
'id' => 'sensitive.env',
'category' => 'sensitive_file',
'matcher' => 'contains',
'value' => '/.env',
'severity' => 'critical',
'score' => 30,
'immediate_ban' => true,
]
Field Wajib Arti
id ya Pengenal unik. Dipakai di log dan untuk menimpa rule bawaan.
category ya Kelompok aturan, untuk pelaporan.
matcher ya Cara pencocokan. Lihat tabel di bawah.
value ya Yang dicari, tergantung matcher.
severity ya low, medium, high, atau critical.
score ya Kontribusi skor kalau cocok.
immediate_ban tidak true berarti ban tanpa_naik skor.
enabled tidak Default true.

Yang perlu diisi setiap rule adalah enam field pertama. Sisanya opsional.

Severity Arti
low Ancaman lemah, biasanya hanya menambah skor.
medium Perlu kombinasi dengan sinyal lain.
high Serius.
critical Menembus allowlist. Lihat catatan di bawah.

critical diperlakukan secara khusus di dua tempat:

  1. Allowlist tidak bisa menutupi rule critical.
  2. Ban yang sedang aktif tidak pernah diturunkan jadi challenge, bahkan kalau hanya critical yang cocok.

Jadi beri critical hanya untuk hal yang benar-benar jelas, misalnya /.env atau /.git/config.

Matcher Cocok kalau Contoh value
exact Path sama persis. /backup.zip
prefix Path diawali. /wp-json/gravitysmtp/
contains Path mengandung potongan tersebut. /.env
regex Path cocok pola. `~.(bak
query_contains Mengandung parameter query tertentu. ?act=
decoded_contains Cocok setelah URI di-decode berulang. /.env
body_contains Isi POST mengandung potongan. <script>alert
body_regex Isi POST cocok pola. ~union\s+select~i

Keduanya mencari hal yang sama, tapi dari sisi berbeda. contains bekerja pada URI apa adanya; decoded_contains bekerja pada bentuk yang sudah di-decode sejauh decode_depth.

Untuk file sensitif, hampir selalu butuh keduanya:

[
'id' => 'sensitive.env',
'matcher' => 'contains',
'value' => '/.env',
],
[
'id' => 'sensitive.env.decoded',
'matcher' => 'decoded_contains',
'value' => '/.env',
],

Kalau hanya salah satu, penyerang cukup menulis /%2e%65nv untuk lolosnya.

body_contains dan body_regex hanya dibaca kalau:

  • inspection.body.enabled bernilai true, dan
  • ukuran body tidak melewati inspection.body.max_bytes.

Kalau body tidak diperiksa, rule-nya dilewati tanpa penalty.

Tiga kelompok rule, dengan hitungan default:

Paket Jumlah Status
definitions() 37 Aktif
injectionDefinitions() 14 Aktif
wordpressDefinitions() 6 Nonaktif

Jadi 51 rule aktif secara default. WordPress dinonaktifkan karena hanya berguna untuk situs yang benar-benar berjalan di WordPress.

'rules' => [
'packs' => [
'injection' => true,
'wordpress' => false,
],
],

Tambahkan definisi Anda setelah paket bawaan, di konfigurasi yang Anda kirim ke ShieldConfig::fromArray():

'rules' => [
'packs' => [
'injection' => true,
'wordpress' => false,
],
'definitions' => [
[
'id' => 'custom.endpoint',
'category' => 'custom',
'matcher' => 'exact',
'value' => '/endpoint-rahasia',
'severity' => 'critical',
'score' => 30,
'immediate_ban' => true,
],
[
'id' => 'custom.backup',
'category' => 'custom',
'matcher' => 'regex',
'value' => '~/(backup|dump)\.(sql|zip|tar\.gz)$~i',
'severity' => 'high',
'score' => 20,
],
],
],

Tidak ada file terpisah, tidak ada registrasi. Apa pun yang ada di definitions akan ikut dipakai.

Kalau id Anda sama dengan id bawaan, definisi Anda yang menang. Ini caranya menurunkan skor atau mengubah tingkat keparahan tanpa kehilangan daftar rule:

[
// id sama dengan rule bawaan
'id' => 'sensitive.env',
'category' => 'sensitive_file',
'matcher' => 'contains',
'value' => '/.env',
'severity' => 'critical',
'score' => 30,
'immediate_ban' => true,
],

Untuk mematikan rule tanpa menghapus definisinya:

[
'id' => 'sensitive.env',
'enabled' => false,
],

Atau dari sisi repository, tanpa mengubah konfigurasi:

$rules = $rules->withDisabled('sensitive.env');

Untuk path tertentu, skip_paths lebih tepat daripada mematikan rule secara global:

'rules' => [
'skip_paths' => ['/api/webhook/payment'],
],

Endpoint yang memang menerima JSON atau XML akan selalu terlihat seperti serangan kalau body-nya diperiksa. Mematikan seluruh rule untuknya adalah terlalu besar; skip_paths hanya menutup satu jalur itu.

Rule regex divalidasi saat boot, dan validasinya tidak santai:

  • Pola diuji dengan payload 64 karakter berulang.
  • Kalau satu pencocokan memakan waktu lebih dari 50 milidetik, boot gagal.

Alasannya: users.agent Anda adalah input tidak tepercaya yang diproses di setiap request. Regex yang lambat pada input yang dibuat-buat adalah celah yang menguntungkan penyerang — disebut ReDoS.

Kalau boot gagal dengan pesan regex, polanya terlalu luas. Persempit:

// Terlalu luas — pencocokannya lambat
'value' => '~.*admin.*~i',
// Lebih baik — ada batasnya
'value' => '~^/admin/(?:[a-z0-9_-]{1,32})/?$~i',

Semua matcher bekerja pada URI dan body. Kalau Anda butuh menfilter bot AI, itu bukan urusan rule — itu urusan verifikasi crawler dan konfigurasi CDN Anda.

sensitive.env, bukan sensitive_env. Ini berlaku untuk ID bawaan maupun ID yang Anda buat sendiri, karena RuleRepository mencari berdasarkan nama persis.

Kalau tiga rule cocok dalam satu request, ketiganya contribute. Ini sebabnya satu request bisa langsung melewati strong_ban tanpa perlu banyak history.

Aturan yang baik adalah yang bisa dijelaskan

Section titled “Aturan yang baik adalah yang bisa dijelaskan”

Kalau Anda tidak bisa menjawab “kenapa rule ini ada” dalam satu kalimat, rule itu mungkin tidak perlu. Aturan yang tidak pernah cocok hanya menambah waktu pemrosesan.

Powered by PT Ganadev Multi Solusi