Masalah umum YARA-L 2.0

Didukung di:

Dokumen ini ditujukan untuk engineer deteksi yang ingin men-debug logika aturan dan mengoptimalkan eksekusi YARA-L 2.0. Dokumen ini menjelaskan cara menangani perilaku mesin non-standar, seperti unnesting kolom, perluasan Cartesian product dalam agregasi, dan konsistensi tertunda pengayaan. Dengan mengikuti metode ini, Anda dapat mencegah error logika yang menyebabkan nilai hasil yang terlalu tinggi atau deteksi yang terlewat.

YARA-L 2.0 menggunakan model eksekusi yang memperluas kolom berulang menjadi baris peristiwa individual selama evaluasi. Karena transformasi ini terjadi di tingkat mesin, mereferensikan beberapa kolom berulang atau melakukan aritmetika pada jenis Unified Data Model (UDM) yang tidak ditandatangani memerlukan solusi sintaksis untuk menghindari error compiler, error runtime, atau set hasil yang salah. Dokumen ini menguraikan batasan teknis tersebut dan pola logika yang menyelesaikannya.

Sebelum memulai

Pastikan akun Anda memiliki hak teknis berikut sebelum menguji atau mengubah aturan YARA-L 2.0:

Peran IAM yang diperlukan

  • roles/chronicle.viewer (Security Operations Viewer): Untuk melihat aturan dan metadata deteksi yang ada.
  • roles/chronicle.editor (Security Operations Editor): Untuk mengubah logika aturan dan menyimpan perubahan.

Izin yang diperlukan

  • chronicle.rules.runTest: Diperlukan untuk menjalankan fitur Jalankan Pengujian pada data historis.

  • chronicle.detections.get: Untuk memeriksa output peristiwa yang tidak bertingkat di dasbor deteksi.

Terminologi utama

  • UDM (Unified Data Model): Skema yang dinormalisasi yang digunakan untuk menyusun semua telemetri keamanan yang diserap di seluruh platform.
  • Unnesting: Perluasan tingkat mesin dari satu peristiwa UDM yang berisi kolom berulang (array) menjadi beberapa baris. Setiap baris mewakili elemen unik dari array, yang dapat menyebabkan penggandaan baris selama evaluasi aturan.
  • T₀ (eksekusi awal): Eksekusi pertama aturan pada telemetri yang masuk. Hal ini terjadi selama fase "streaming", sering kali sebelum proses pengayaan latar belakang (seperti penyesuaian GeoIP atau ASN) diselesaikan.

Agregasi hasil dengan unnesting kolom berulang

Jika aturan merujuk ke kolom berulang dalam variabel peristiwa dengan beberapa elemen, setiap elemen akan dibagi menjadi baris peristiwa terpisah.

Misalnya, dua alamat IP di kolom berulang target.ip pada peristiwa $e dibagi menjadi dua instance $e, masing-masing dengan nilai target.ip yang berbeda.

rule outbound_ip_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $outbound_ip_count = count($e.target.ip) // yields 2.

  condition:
    $e
}

Data peristiwa: Sebelum dan setelah unnesting

Tabel di bagian ini menunjukkan cara satu peristiwa yang berisi array alamat IP diubah menjadi dua data yang berbeda.

Sebelum unnesting

Tabel berikut menunjukkan data peristiwa sebelum memisahkan kolom berulang:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps [192.0.2.20, 192.0.2.28]

Setelah unnesting

Tabel berikut menunjukkan data peristiwa setelah membatalkan pengelompokan kolom berulang:

metadata.id principal.application target.ip
aaaaaaaaa Google SecOps 192.0.2.20
aaaaaaaaa Google SecOps 192.0.2.28

Kolom berulang bertingkat (Cartesian product)

Jika aturan merujuk ke kolom berulang yang bertingkat dalam kolom lain, seperti security_results.action, unnesting terjadi di kedua tingkat (induk dan turunan) secara bersamaan. Hal ini menghasilkan Cartesian product dari semua elemen.

Dalam contoh berikut, peristiwa $e dengan dua nilai berulang pada security_results dan dua nilai berulang pada security_results.actions di-un-nest menjadi empat instance.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $security_action_count = count($e.security_results.actions) // yields 4.

  condition:
    $e
}

Data peristiwa sebelum unnesting bertingkat

Data asli menyimpan tindakan dalam struktur array bertingkat.

metadata.id principal.application security_results
aaaaaaaaa Google SecOps [ { actions: [ ALLOW, FAIL ] }, { actions: [ CHALLENGE, BLOCK ] } ]

Data peristiwa setelah unnesting bertingkat

Setelah perluasan, setiap tindakan unik akan menjadi barisnya sendiri, yang dapat menyebabkan jumlah yang tidak terduga dalam agregasi non-distinct.

metadata.id principal.application security_results.actions
aaaaaaaaa Google SecOps IZINKAN
aaaaaaaaa Google SecOps GAGAL
aaaaaaaaa Google SecOps TANTANGAN
aaaaaaaaa Google SecOps BLOKIR

Dampak pada kolom yang tidak terkait

Perilaku unnesting dalam evaluasi aturan ini dapat menghasilkan agregasi hasil yang tidak terduga saat aturan mereferensikan satu atau beberapa kolom berulang dengan kolom induk yang juga merupakan kolom berulang. Agregasi non-distinct seperti sum(), array(), dan count() tidak dapat memperhitungkan nilai duplikat di kolom lain pada peristiwa yang sama yang dihasilkan oleh perilaku unnesting.

Dalam contoh berikut, peristiwa $e memiliki satu nama host (google.com), tetapi hasilnya (hostnames) menggabungkan empat instance yang tidak bertingkat dari peristiwa $e yang sama, masing-masing dengan nilai principal.hostname duplikat. Hasil ini menghasilkan empat nama host (bukan satu) karena peng-unnest-an nilai berulang pada security_results.actions.

rule security_action_per_app {
  meta:

  events:
    $e.principal.application = $app

  match:
    $app over 10m

  outcome:
    $hostnames = array($e.principal.hostname) // yields 4.
    $security_action_count = count($e.security_results.action) // yields 4.

  condition:
    $e
}

Data peristiwa sebelum unnesting dengan kolom yang tidak terkait

Nama host adalah nilai tunggal, tetapi berada di samping hasil keamanan berulang.

metadata.id principal.application principal.hostname security_results
aaaaaaaaa Google SecOps google.com [ { action: [ ALLOW, FAIL ] }, { action: [ CHALLENGE, BLOCK ] } ]

Data peristiwa setelah unnesting dengan kolom yang tidak terkait

Nama host kini diduplikasi di empat baris, sehingga fungsi array() mengambilnya empat kali.

metadata.id principal.application principal.hostname security_results.action
aaaaaaaaa Google SecOps google.com IZINKAN
aaaaaaaaa Google SecOps google.com GAGAL
aaaaaaaaa Google SecOps google.com TANTANGAN
aaaaaaaaa Google SecOps google.com BLOKIR

Solusi untuk perilaku unnesting

Untuk memastikan nilai hasil Anda akurat saat unnesting terjadi, gunakan versi yang berbeda dari agregasi yang Anda pilih. Fungsi berikut mengabaikan baris duplikat yang dibuat oleh unnesting:

  • max()
  • min()
  • array_distinct()
  • count_distinct()

Agregasi hasil dengan beberapa variabel peristiwa

Jika aturan berisi beberapa variabel peristiwa, ada item terpisah dalam agregasi untuk setiap kombinasi peristiwa yang disertakan dalam deteksi. Misalnya, jika contoh aturan berikut dijalankan terhadap peristiwa yang tercantum:

events:
  $e1.field = $e2.field
  $e2.somefield = $ph

match:
  $ph over 1h

outcome:
   $some_outcome = sum(if($e1.otherfield = "value", 1, 0))

condition:
  $e1 and $e2
event1:
  // UDM event 1
  field="a"
  somefield="d"

event2:
  // UDM event 2
  field="b"
  somefield="d"

event3:
  // UDM event 3
  field="c"
  somefield="d"

Jumlah dihitung dari setiap kombinasi peristiwa, sehingga Anda dapat menggunakan kedua variabel peristiwa dalam penghitungan nilai hasil. Elemen berikut digunakan dalam penghitungan:

1: $e1 = event1, $e2 = event2
2: $e1 = event1, $e2 = event3
3: $e1 = event2, $e2 = event1
4: $e1 = event2, $e2 = event3
5: $e1 = event3, $e2 = event1
5: $e1 = event3, $e2 = event2

Hal ini menghasilkan potensi jumlah maksimum 6, meskipun $e2 hanya dapat sesuai dengan 3 peristiwa yang berbeda.

Hal ini memengaruhi jumlah, hitungan, dan array. Untuk count dan array, penggunaan count_distinct atau array_distinct dapat menyelesaikan masalah, tetapi tidak ada solusi untuk sum.

Tanda kurung di awal ekspresi

Memulai ekspresi dengan tanda kurung tidak didukung dan akan memicu error penguraian di editor aturan.

Sintaksis tidak valid

parsing: error with token: ")"
invalid operator in events predicate

Contoh berikut menghasilkan jenis error ini:

($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600 > 1

Variasi sintaksis yang valid

Variasi sintaksis berikut menampilkan hasil yang sama, tetapi dengan sintaksis yang valid:

$event.metadata.ingested_timestamp.seconds / 3600 -
$event.metadata.event_timestamp.seconds / 3600 > 1
    1 / 3600 * ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) > 1
    1 < ($event.metadata.ingested_timestamp.seconds -
$event.metadata.event_timestamp.seconds) / 3600

Array indeks dalam hasil memerlukan agregasi

Mengindeks array secara langsung dalam bagian outcome untuk kolom berulang tidak diizinkan. Hal ini memerlukan variabel placeholder sementara.

outcome:
  $principal_user_dept = $suspicious.principal.user.department[0]

Solusi

Ambil indeks array tertentu ke dalam variabel placeholder dalam bagian events, lalu referensikan placeholder tersebut dalam hasil Anda.

events:
  $principal_user_dept = $suspicious.principal.user.department[0]

outcome:
  $principal_user_department = $principal_user_dept

Kondisi OR dengan ketiadaan

Jika Anda menerapkan kondisi OR di antara dua variabel peristiwa yang terpisah dan jika aturan cocok dengan ketiadaan, aturan akan berhasil dikompilasi, tetapi dapat menghasilkan deteksi positif palsu.

Misalnya, sintaksis aturan berikut dapat mencocokkan peristiwa yang memiliki $event_a.field = "something" meskipun seharusnya tidak:

events:
     not ($event_a.field = "something" **or** $event_b.field = "something")
condition:
     $event_a and #event_b >= 0

Solusi

Pisahkan pemeriksaan ketiadaan menjadi blok-blok individual untuk setiap variabel guna mempertahankan integritas logika.

events:
  not ($event_a.field = "something")
  not ($event_b.field = "something")

condition:
  $event_a and #event_b >= 0

Aritmetika dengan kolom peristiwa yang tidak ditandatangani

Jika Anda menggunakan literal bilangan bulat dalam operasi aritmetika (+, -, *) atau modulo (%) dengan kolom UDM bilangan bulat tanpa tanda tangan, Anda akan mendapatkan error. Literal bilangan bulat standar ditetapkan secara default ke bilangan bulat 64-bit bertanda (INT64), yang tidak kompatibel dengan kolom UDM yang ditentukan sebagai bilangan bulat 64-bit tidak bertanda (UINT64), seperti network.received_bytes, network.sent_bytes, dan principal.file.size.

Batasan pengetikan yang ketat ini berlaku untuk bagian events dan outcome, termasuk di dalam agregasi sum() atau max() dan ekspresi pembagi. Pemeriksa sintaksis YARA-L memperlakukan bilangan bulat bertanda tangan dan tidak bertanda tangan sebagai jenis int generik. Akibatnya, aturan yang menggabungkan kolom UDM UINT64 dan literal bilangan bulat INT64 mungkin lulus validasi sintaksis waktu penyimpanan, tetapi gagal selama eksekusi aturan atau saat Anda mengklik Run Test. Jika gagal, aturan akan menghasilkan "Error Aturan" umum (cannot complete [arithmetic/mod] operation between unsigned and signed integer).

Misalnya, perbandingan events berikut lulus validasi sintaksis saat disimpan, tetapi gagal selama eksekusi karena $e.network.received_bytes (UINT64) dikalikan dengan literal bilangan bulat bertanda tangan 2 (INT64):

events:
  $total_bytes = $e.network.total_bytes
  $total_bytes = $e.network.received_bytes * 2

Solusi

Anda dapat mengatasi ketidakcocokan jenis ini menggunakan salah satu metode berikut:

  • Transmisi bilangan bulat eksplisit (cast.as_int() atau cast.as_uint()): Konversikan kolom UDM yang tidak ditandatangani menjadi bilangan bulat yang ditandatangani menggunakan cast.as_int(), atau konversikan literal bilangan bulat menjadi bilangan bulat yang tidak ditandatangani menggunakan cast.as_uint(). Gunakan metode ini saat Anda memerlukan hasil bilangan bulat atau saat menggunakan operator modulo (%), yang hanya menerima operand bilangan bulat.
  • Pemaksaan floating point: Memaksa konstanta bilangan bulat untuk berperilaku sebagai float menggunakan literal floating point, seperti 2.0 atau 100.0. Dalam ekspresi sederhana tanpa operator pembagian lain pada baris yang sama, Anda juga dapat menggunakan operasi pembagian, seperti (2/1). Dalam ekspresi yang sudah berisi operator pembagian (/), gunakan literal floating point atau cast.as_int(), bukan pemaksaan pembagian (N/1). Beberapa karakter / pada baris yang sama dapat ditafsirkan sebagai literal ekspresi reguler, sehingga menyebabkan error penguraian selama kompilasi atau merusak penyorotan sintaksis di Editor Aturan.

Solusi di bagian events

Gunakan cast.as_int(), literal floating point, atau pemaksaan pembagian untuk memperbaiki error di bagian events:

  • Gunakan cast.as_int():

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = cast.as_int($e.network.received_bytes) * 2
    
  • Gunakan literal floating point:

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = $e.network.received_bytes * 2.0
    
  • Gunakan pemaksaan pembagian:

    events:
      $total_bytes = $e.network.total_bytes
      $total_bytes = $e.network.received_bytes * (2/1)
    

Solusi di bagian outcome

Ekspresi outcome berikut disimpan tanpa error sintaksis, tetapi gagal saat runtime karena sum($e.network.sent_bytes) dan sum($e.network.received_bytes) menampilkan nilai UINT64 yang digabungkan dengan literal INT64 bertanda tangan 100 dan 1:

outcome:
  // Saves, but fails at runtime:
  $upload_ratio_pct = sum($e.network.sent_bytes) * 100 / (sum($e.network.received_bytes) + 1)

Tulis ulang ekspresi menggunakan literal floating point atau cast.as_int() agar ekspresi tersebut disimpan dan dijalankan tanpa error:

  • Gunakan literal floating point:

    outcome:
      $upload_ratio_pct = sum($e.network.sent_bytes) * 100.0 / (sum($e.network.received_bytes) + 1.0)
    
  • Gunakan cast.as_int():

    outcome:
      $upload_ratio_pct = sum(cast.as_int($e.network.sent_bytes)) * 100 / (sum(cast.as_int($e.network.received_bytes)) + 1)
    

Pengayaan GeoIP dan konsistensi tertunda

Sistem memprioritaskan kecepatan daripada akurasi langsung pada tahap pengayaan awal (Streaming dan Sensitif terhadap Latensi), yang dapat menyebabkan data hilang dan potensi positif palsu. Sistem akan terus memperkaya data di latar belakang, tetapi data mungkin tidak tersedia saat aturan dijalankan. Hal ini merupakan bagian dari proses konsistensi tertunda yang normal.

Untuk mencegah positif palsu yang disebabkan oleh jeda pengayaan, periksa secara eksplisit bahwa kolom tidak kosong sebelum mengevaluasi nilainya.

Misalnya, pertimbangkan peristiwa aturan ini:

$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

Aturan ini mengandalkan fakta bahwa peristiwa harus memiliki $e.principal.ip_geo_artifact.network.asn = "16509" DAN $e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom" yang keduanya merupakan kolom yang diperkaya. Jika pengayaan tidak selesai tepat waktu, aturan akan menghasilkan positif palsu.

Untuk menghindari hal ini, pemeriksaan yang lebih baik untuk aturan ini adalah:

$e.principal.ip_geo_artifact.network.asn != "" AND
$e.principal.ip_geo_artifact.network.asn = "16509" AND
$e.principal.ip_geo_artifact.location.country_or_region != "" AND
$e.principal.ip_geo_artifact.location.country_or_region = "United Kingdom"

Aturan ini menghilangkan kemungkinan peristiwa dipicu oleh IP dengan ASN 16509, tetapi berada di luar Inggris Raya. Hal ini meningkatkan presisi aturan secara keseluruhan.

Pelajari cara memecahkan masalah jeda pengayaan.

Pemecahan masalah

Bagian ini menguraikan ekspektasi performa dan memberikan perbaikan mandiri untuk masalah umum saat perilaku deteksi langsung berbeda dengan hasil pengujian.

Acara mendatang

Aturan banyak peristiwa dirancang untuk memproses peristiwa dalam urutan kronologis yang terkait dengan penyerapan. Jika Anda menentukan dan mengaktifkan aturan multi-peristiwa, aturan tersebut tidak akan membuat deteksi untuk peristiwa dengan stempel waktu mendatang, misalnya saat event.timestamp memiliki tanggal dan waktu yang ditetapkan setelah ingest.timestamp.

Jeda pengayaan

Google SecOps memprioritaskan kecepatan penyerapan untuk menampilkan pemberitahuan awal secepat mungkin. Namun, proses pengayaan latar belakang, seperti me-resolve metadata GeoIP, ASN, atau UDM, mengikuti model konsistensi tertunda.

Operasi awal (T₀)

Mesin live dapat mengevaluasi aturan sebelum pengayaan latar belakang selesai. Bergantung pada apakah logika Anda mengandalkan kolom yang diperkaya untuk deteksi atau pengecualian, hal ini dapat menyebabkan perbedaan sementara berikut:

  • Negatif palsu (jeda deteksi): Ini adalah hasil yang umum. Jika aturan bergantung pada kolom yang diperkaya untuk dipicu (misalnya, target.user.department == "Finance"), dan kolom tersebut adalah null, aturan tidak akan cocok selama eksekusi awal.

  • Positif palsu (pengecualian tidak diterapkan): Jika aturan Anda menggunakan kolom yang diperkaya untuk memfilter aktivitas yang diketahui baik (misalnya, NOT target.ip_geo_country == "US"), aturan tersebut dapat memicu positif palsu karena data "pengecualian" belum diterapkan.

Operasi penyesuaian

Operasi latar belakang ini mengevaluasi ulang data setelah jeda (misalnya, 4 jam atau 30 jam). Tindakan ini akan "menyelaraskan" status deteksi sebagai berikut:

  • Deteksi terlambat: Peristiwa yang merupakan "negatif palsu" di T₀ kini menghasilkan deteksi setelah pengayaan diselesaikan.

  • Koreksi: Positif palsu T₀ tetap ada dalam sistem, tetapi data yang diperkaya sepenuhnya terlihat di penampil UDM untuk triase manual.

Menjalankan perbedaan pengujian

Alat Jalankan Pengujian beroperasi pada data historis yang telah direkonsiliasi. Karena data telah diperkaya sepenuhnya saat Anda menjalankan pengujian manual, Anda dapat langsung melihat hasil "penyesuaian". Artinya, Anda tidak akan melihat negatif palsu T₀ atau positif palsu berbasis pengecualian yang terjadi selama proses awal langsung.

Perbaikan error

Gunakan tabel berikut untuk mengatasi perbedaan antara pemberitahuan langsung dan hasil pengujian.

Masalah Deskripsi Perbaikan yang dapat ditindaklanjuti
Kegagalan pengecualian Aturan diaktifkan meskipun ada pengecualian (misalnya, != "ASN_123") karena kolom bernilai null selama eksekusi awal. Tambahkan pemeriksaan bukan null ke bagian peristiwa untuk memastikan data diperkaya sebelum evaluasi, misalnya:

$e.principal.ip_geo_artifact.network.asn != ""
Live dibandingkan dengan pertandingan uji coba Aturan aktif memicu pemberitahuan, tetapi Jalankan Pengujian pada data yang sama menampilkan "No Results". Tambahkan $e.field != "" yang memeriksa semua kolom yang diperkaya (GeoIP, ASN, File Path) untuk menyinkronkan perilaku live dan historis.
Metadata tidak ada Deteksi muncul di dasbor dengan kolom GeoIP atau File Path yang kosong. Hal ini sudah diperkirakan untuk operasi T0. Untuk memperbaikinya, sertakan pemeriksaan field != "" atau konfigurasikan penundaan penyelesaian dalam jadwal aturan Anda agar tersedia lebih banyak waktu untuk penyerapan.

Validasi dan pengujian

Untuk memverifikasi bahwa aturan menangani pengayaan tertunda dengan benar, lakukan hal berikut:

  1. Identifikasi jeda: Temukan deteksi yang Anda yakini sebagai positif palsu. Di kolom Jenis Deteksi, periksa ikon <span class="material-icons">lightbulb</span>. Notifikasi tanpa ikon ini berasal dari proses utama yang paling sering mengalami jeda pengayaan.

  2. Perbarui logika aturan: Tambahkan pemeriksaan field != "" untuk semua titik data yang diperkaya yang digunakan dalam logika Anda.
    Contoh (jalur file):
    $e.target.process.parent_process.file.full_path != ""

  3. Uji dan verifikasi:

    • Gunakan fitur Jalankan Pengujian untuk memastikan logika Anda masih cocok dengan data historis yang diinginkan.
    • Pastikan aturan kini hanya dipicu (atau dikecualikan dengan benar) selama proses penyesuaian setelah kolom pengayaan diisi.

Untuk mengetahui informasi selengkapnya, lihat Memahami penjadwalan eksekusi aturan dan Mengonfigurasi jadwal yang disesuaikan untuk aturan.

Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.