Membuat kueri multi-tahap di YARA-L

Didukung di:

Dokumen ini menjelaskan cara kueri multi-tahap di YARA-L memungkinkan Anda memasukkan output satu tahap kueri langsung ke input tahap berikutnya. Proses ini memberi Anda kontrol yang lebih besar atas transformasi data daripada satu kueri monolitik.

Mengintegrasikan kueri multi-tahap dengan fitur yang ada

Kueri multi-tahap berfungsi bersama dengan fitur yang ada berikut di Google Security Operations:

  • Aturan deteksi gabungan: Kueri multi-tahap melengkapi aturan deteksi gabungan. Tidak seperti aturan gabungan, kueri multi-tahap yang menggunakan Penelusuran dapat menampilkan hasil secara real time.

  • Rentang waktu dan aturan multi-peristiwa: Anda dapat menggunakan kueri multi-tahap untuk mendeteksi anomali dengan membandingkan jangka waktu yang berbeda dalam data Anda. Misalnya, Anda dapat menggunakan tahap kueri awal untuk membuat tolok ukur selama jangka waktu yang lebih lama, lalu menggunakan tahap selanjutnya untuk mengevaluasi aktivitas terbaru terhadap tolok ukur tersebut. Anda juga dapat menggunakan aturan multi-peristiwa untuk membuat jenis perbandingan yang serupa.

Kueri multi-tahap di YARA-L didukung di Dasbor dan Penelusuran.

Gabungan membantu mengorelasikan data dari berbagai sumber untuk memberikan lebih banyak konteks bagi penyelidikan. Dengan menautkan peristiwa, entitas, dan data terkait lainnya, Anda dapat menyelidiki skenario serangan yang kompleks. Untuk mengetahui informasi selengkapnya, lihat Menggunakan gabungan dalam Penelusuran.

Menentukan sintaksis YARA-L multi-tahap

Saat Anda mengonfigurasi kueri multi-tahap, perhatikan hal-hal berikut:

  • Tahap batas: Kueri multi-tahap harus berisi antara 1 dan 4 tahap bernama, selain tahap root.
  • Sintaksis pesanan: Selalu tentukan sintaksis tahap bernama sebelum menentukan sintaksis tahap root.

Membuat kueri YARA-L multi-tahap

Untuk membuat kueri YARA-L multi-tahap, selesaikan langkah-langkah berikut.

Struktur dan sintaksis pementasan

Buka Investigasi > Penelusuran. Ikuti persyaratan struktural berikut saat Anda menentukan tahap kueri:

Sintaksis: Gunakan sintaksis berikut untuk memberi nama setiap tahap dan memisahkannya dari tahap lainnya:

stage <stage name> { }

  • Kurung kurawal: Tempatkan semua sintaksis tahap di dalam kurung kurawal {}.

  • Urutan: Tentukan sintaksis untuk semua tahap bernama sebelum menentukan tahap root.

  • Mereferensikan: Setiap tahap dapat mereferensikan tahap yang ditentukan sebelumnya dalam kueri.

  • Tahap root: Kueri harus memiliki tahap root, yang diproses setelah semua tahap bernama.

Tahap contoh berikut, daily_stats, mengumpulkan statistik jaringan harian:

stage daily_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $source = principal.hostname
  $target = target.ip
  $source != ""
  $target != ""
  $total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)
  match:
    $source, $target by day
  outcome:
    $exchanged_bytes = sum($total_bytes)
}

Output tahap akses

Output tahap bernama dapat diakses oleh tahap berikutnya menggunakan kolom tahap. Kolom tahap sesuai dengan variabel match dan outcome tahap dan dapat digunakan dengan cara yang sama seperti kolom Model Data Terpadu (UDM).

Gunakan sintaksis berikut untuk mengakses kolom tahap:

$<stage name>.<variable name>

Stempel waktu jendela akses (opsional)

Jika tahap bernama menggunakan jendela hop, geser, atau tumbling, akses awal jendela dan akhir jendela untuk setiap baris output menggunakan kolom khusus ini:

  • $<stage name>.window_start

  • $<stage name>.window_end

window_start dan window_end adalah kolom bilangan bulat yang dinyatakan dalam detik sejak epoch Unix. Ukuran jendela di berbagai tahap dapat bervariasi.

Batasan

Kueri multi-tahap memiliki batasan fungsional dan struktural berikut:

Batas struktural dan tahap

  • Tahap root: Hanya satu tahap root yang diizinkan per kueri.

  • Tahapan bernama: Maksimum empat tahapan bernama didukung.

  • Referensi tahap: Tahap hanya dapat mereferensikan tahap yang ditentukan secara logis sebelumnya dalam kueri yang sama.

  • Gabungan: Maksimum empat gabungan non-tabel data diizinkan di semua tahap.

  • Persyaratan hasil: Setiap tahap bernama (tidak termasuk tahap root) harus menyertakan bagian match atau bagian outcome. Bagian outcome tidak memerlukan agregasi.

Batasan jendela dan kompatibilitas

  • Dukungan fitur: Kueri multi-tahap didukung di Penelusuran dan Dasbor, tetapi tidak didukung di Aturan.

  • Jenis jendela: Hindari mencampur berbagai jenis jendela dalam satu kueri.

  • Dependensi jendela: Tahap yang menggunakan jendela bergeser atau hop tidak dapat bergantung pada tahap lain yang juga menggunakan jendela bergeser atau hop.

  • Ukuran jendela yang berjatuhan: Meskipun ukuran jendela yang berjatuhan dalam berbagai tahap dapat bervariasi, perbedaan ukuran harus kurang dari 720x.

Contoh: Perbedaan agregasi tahap

Konfigurasi jendela contoh berikut tidak diizinkan:

stage monthly_stats {
  metadata.event_type = "NETWORK_CONNECTION"
    $source = principal.hostname
    $target = target.ip
    $source != ""
    $target != ""
    $total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)

  match:
    $source, $target by month

  outcome:
    $exchanged_bytes = sum($total_bytes)
}

$source = $monthly_stats.source
$target = $monthly_stats.target

match:
    $source, $target by minute

Jika tahap monthly_stats menggabungkan data menurut bulan, dan tahap root menggabungkan output monthly_stats menurut menit, maka setiap baris dari monthly_stats dipetakan ke 43.200 baris di tahap root (karena ada 43.200 menit dalam satu bulan).

Batasan tahap dan kueri

Setiap tahap dalam kueri multi-tahap memiliki batasan berikut:

  • Sebagian besar batasan yang berlaku untuk kueri satu tahap juga berlaku untuk setiap tahap:

    • Persyaratan output: Setiap tahap harus menghasilkan setidaknya satu variabel kecocokan atau hasil (kolom tahap).

    • Jendela dalam gabungan: Ukuran jendela maksimum (hop, tumbling, atau sliding) yang digunakan dalam gabungan adalah 2 hari.

    • Jumlah maksimum variabel hasil:

      • 20 untuk pelanggan yang tidak memilih untuk mengizinkan batas variabel hasil yang lebih besar

      • 50 untuk pelanggan yang memilih untuk mengizinkan batas variabel hasil yang lebih besar

    • Ukuran minimum dan maksimum jendela lompatan.

    • Jumlah maksimum elemen dalam variabel hasil bernilai array.

  • Kueri multi-tahap tunduk pada batasan yang sama seperti kueri statistik:

    • Kueri statistik: 120 QPH (API dan UI)

    • Penelusuran tampilan dari Google SecOps: 100 tampilan per menit

    • Gabungan multi-tahap didukung di antarmuka pengguna dan EventService.UDMSearch API, tetapi tidak di SearchService.UDMSearch API. Kueri multi-tahap tanpa gabungan juga didukung di antarmuka pengguna.

Batasan acara dan global

Acara maksimum:

Kueri multi-tahap sangat dibatasi dalam jumlah peristiwa yang dapat diproses secara bersamaan:

  • Peristiwa UDM: Maksimal 2 peristiwa UDM diizinkan.

  • Peristiwa Entity Context Graph (ECG): Maksimum satu peristiwa ECG diizinkan.

Batasan kueri global:

Batas ini adalah batasan di seluruh platform yang mengontrol seberapa jauh ke belakang dan seberapa banyak data yang dapat ditampilkan oleh kueri multi-tahap.

  • Untuk rentang waktu kueri, rentang waktu maksimum untuk kueri standar adalah 30 hari.

  • Ukuran total maksimum kumpulan hasil adalah 10.000 hasil.

Contoh kueri multi-tahap

Contoh dalam bagian ini membantu menggambarkan cara membuat kueri YARA-L multi-tahap yang lengkap.

Contoh: Menelusuri koneksi jaringan yang sangat aktif (jam)

Contoh YARA-L multi-tahap ini mengidentifikasi pasangan alamat IP dengan aktivitas jaringan yang lebih tinggi dari biasanya, menargetkan pasangan yang mempertahankan aktivitas tinggi selama lebih dari tiga jam. Kueri ini mencakup dua komponen yang diperlukan: tahap bernama, hourly_stats, dan tahap root.

Tahap hourly_stats menelusuri pasangan principal.ip dan target.ip dengan tingkat aktivitas jaringan yang tinggi.

Tahap ini menampilkan satu nilai per jam untuk kolom berikut:

  • Statistik untuk IP sumber (string): $hourly_stats.src_ip

  • Statistik untuk IP tujuan (string): $hourly_stats.dst_ip

  • Statistik untuk jumlah peristiwa (bilangan bulat): $hourly_stats.count

  • Simpangan baku byte yang diterima (float): $hourly_stats.std_recd_bytes

  • Byte yang diterima rata-rata (float): $hourly_stats.avg_recd_bytes

  • Waktu mulai bucket jam dalam detik dari epoch Unix (bilangan bulat): $hourly_stats.window_start

  • Waktu berakhir bucket jam dalam detik dari epoch Unix (bilangan bulat): $hourly_stats.window_end

Tahap root memproses output tahap hourly_stats. Menghitung statistik untuk pasangan principal.ip dan target.ip dengan aktivitas yang melebihi nilai minimum yang ditentukan oleh $hourly_stats. Kemudian, filter pasangan dengan aktivitas tinggi selama lebih dari tiga jam.


stage hourly_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $src_ip = principal.ip
  $dst_ip = target.ip
  $src_ip != ""
  $dst_ip != ""

  match:
    $src_ip, $dst_ip by hour

  outcome:
    $count = count(metadata.id)
    $avg_recd_bytes = avg(network.received_bytes)
    $std_recd_bytes = stddev(network.received_bytes)

  condition:
    $avg_recd_bytes > 100 and $std_recd_bytes > 50
}

$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)

match:
 $src_ip, $dst_ip

outcome:
 $list = array_distinct($time_bucket_count)
 $count = count_distinct($hourly_stats.window_start)

condition:
 $count > 3

Jika Anda mengubah kondisi kecocokan di tahap root sebagai berikut, Anda dapat memperkenalkan agregasi berjendela menurut hari untuk kueri multi-tahap.

match:
 $src_ip, $dst_ip by day

Contoh: Menelusuri koneksi jaringan yang tidak biasa (menggunakan skor Z)

Kueri multi-tahap ini membandingkan aktivitas jaringan rata-rata harian dengan aktivitas hari ini menggunakan penghitungan skor Z (mengukur jumlah standar deviasi dari rata-rata). Kueri ini secara efektif menelusuri aktivitas jaringan yang sangat tinggi dan tidak biasa antara aset internal dan sistem eksternal.

Prasyarat: Jangka waktu kueri harus lebih besar dari atau sama dengan 2 hari dan menyertakan hari ini agar skor Z yang dihitung efektif.

Kueri multi-tahap ini mencakup tahap daily_stats dan tahap root, yang bekerja sama untuk menghitung skor Z untuk aktivitas jaringan:

  • Tahap daily_stats melakukan agregasi harian awal. Fungsi ini menghitung total byte yang dipertukarkan setiap hari untuk setiap pasangan IP (source dan target) dan menampilkan kolom tahap berikut (sesuai dengan kolom dalam baris output):

    • $daily_stats.source: tunggal, string
    • $daily_stats.target: tunggal, string
    • $daily_stats.exchanged_bytes: tunggal, bilangan bulat
    • $daily_stats.window_start: tunggal, bilangan bulat
    • $daily_stats.window_end: tunggal, bilangan bulat
  • Tahap root menggabungkan output tahap daily_stats untuk setiap pasangan IP. Fitur ini menghitung rata-rata dan standar deviasi byte harian yang dipertukarkan di seluruh rentang penelusuran, beserta byte yang dipertukarkan hari ini. Fungsi ini menggunakan tiga nilai kalkulasi tersebut untuk menentukan skor Z.

  • Output mencantumkan skor Z untuk semua pasangan IP hari ini, yang diurutkan dalam urutan menurun.

// Calculate the total bytes exchanged per day by source and target

stage daily_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $source = principal.hostname
  $target = target.ip
  $source != ""
  $target != ""
  $total_bytes = cast.as_int(network.sent_bytes + network.received_bytes)
  match:
    $source, $target by day
  outcome:
    $exchanged_bytes = sum($total_bytes)
}

// Calculate the average per day over the time window and compare with the bytes
   exchanged today

$source = $daily_stats.source
$target = $daily_stats.target
$date = timestamp.get_date($daily_stats.window_start)

match:
  $source, $target

outcome:
  $today_bytes = sum(if($date = timestamp.get_date(timestamp.current_seconds()), $daily_stats.exchanged_bytes, 0))
  $average_bytes = window.avg($daily_stats.exchanged_bytes)
  $stddev_bytes = window.stddev($daily_stats.exchanged_bytes)
  $zscore = ($today_bytes - $average_bytes) / $stddev_bytes

order:
  $zscore desc

Mengekspor variabel yang tidak diagregasi dari tahap

Tahapan bernama dapat menyertakan bagian outcome yang tidak diagregasi. Artinya, variabel yang ditentukan dalam bagian outcome tersebut dikeluarkan langsung dari tahap, sehingga tahap berikutnya dapat mengaksesnya sebagai kolom tahap tanpa memerlukan penggabungan yang dikelompokkan.

Contoh: Mengekspor variabel yang tidak diagregasi

Contoh ini menunjukkan cara mengekspor variabel yang tidak diagregasi. Perhatikan logika berikut:

  • top_5_bytes_sent tahap penelusuran untuk lima peristiwa dengan aktivitas jaringan tertinggi.

  • Tahap top_5_bytes_sent menghasilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:

    • $top_5_bytes_sent.bytes_sent: tunggal, bilangan bulat
    • $top_5_bytes_sent.timestamp_seconds: tunggal, bilangan bulat
  • Tahap root menghitung stempel waktu terbaru dan paling awal untuk lima peristiwa dengan aktivitas jaringan tertinggi.

stage top_5_bytes_sent {
  metadata.event_type = "NETWORK_CONNECTION"
  network.sent_bytes > 0

  outcome:
    $bytes_sent = cast.as_int(network.sent_bytes)
    $timestamp_seconds = metadata.event_timestamp.seconds

  order:
    $bytes_sent desc 
  
  limit:
    5
}

outcome:
  $latest_timestamp = timestamp.get_timestamp(max($top_5_bytes_sent.timestamp_seconds))
  $earliest_timestamp = timestamp.get_timestamp(min($top_5_bytes_sent.timestamp_seconds))

Menerapkan windowing dalam kueri multi-tahap

Kueri multi-tahap mendukung semua jenis windowing (hop, geser, dan tumbling) dalam tahap bernama. Jika tahap bernama menyertakan jendela, awal jendela dan akhir jendela untuk setiap baris output dapat diakses menggunakan kolom khusus berikut:

  • $<stage name>.window_start
  • $<stage name>.window_end

Contoh: Jendela hop

Contoh berikut mengilustrasikan cara menggunakan jendela lompatan dalam kueri multi-tahap:

  • Tahap hourly_stats menelusuri pasangan IP yang memiliki aktivitas jaringan tinggi dalam jam yang sama.

  • hourly_stats menghasilkan kolom tahap berikut yang sesuai dengan kolom dalam baris output:

    • $hourly_stats.src_ip: tunggal, string
    • $hourly_stats.dst_ip: tunggal, string
    • $hourly_stats.count: tunggal, bilangan bulat
    • $hourly_stats.std_recd_bytes: tunggal, float
    • $hourly_stats.avg_recd_bytes: tunggal, float
    • $hourly_stats.window_start: tunggal, bilangan bulat
    • $hourly_stats.window_end: tunggal, bilangan bulat
  • Tahap root memfilter pasangan IP dengan aktivitas tinggi lebih dari 3 jam. Jam dapat tumpang-tindih karena penggunaan jendela lompatan di tahap hourly_stats.

stage hourly_stats {
  metadata.event_type = "NETWORK_CONNECTION"
  $src_ip = principal.ip
  $dst_ip = target.ip
  $src_ip != ""
  $dst_ip != ""

  match:
    $src_ip, $dst_ip over 1h

  outcome:
    $count = count(metadata.id)
    $avg_recd_bytes = avg(network.received_bytes)
    $std_recd_bytes = stddev(network.received_bytes)

  condition:
    $avg_recd_bytes > 100 and $std_recd_bytes > 50
}

$src_ip = $hourly_stats.src_ip
$dst_ip = $hourly_stats.dst_ip
$time_bucket_count = strings.concat(timestamp.get_timestamp($hourly_stats.window_start), "|", $hourly_stats.count)

match:
 $src_ip, $dst_ip

outcome:
 $list = array_distinct($time_bucket_count)
 $count = count_distinct($hourly_stats.window_start)

condition:
 $count > 3

Masalah umum

Sebaiknya tinjau batasan dan solusi alternatif yang direkomendasikan berikut saat Anda menerapkan kueri multi-tahap:

  • Semua kueri multi-tahap berperilaku seperti kueri Penelusuran statistik (outputnya terdiri dari statistik gabungan, bukan peristiwa yang tidak digabungkan atau baris tabel data).

  • Performa gabungan dengan UDM dan peristiwa entitas di satu sisi dapat mengalami performa rendah karena ukuran set data tersebut. Sebaiknya filter peristiwa UDM dan entitas di sisi gabungan sebanyak mungkin (misalnya, filter menurut jenis peristiwa).

Untuk panduan umum tentang praktik yang direkomendasikan, lihat Praktik terbaik Yara-L dan untuk informasi khusus tentang gabungan, lihat Praktik terbaik.

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