Membuat kueri multi-tahap di YARA-L
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
matchatau bagianoutcome. Bagianoutcometidak 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
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.UDMSearchAPI, tetapi tidak diSearchService.UDMSearchAPI. 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_ipStatistik untuk IP tujuan (string):
$hourly_stats.dst_ipStatistik untuk jumlah peristiwa (bilangan bulat):
$hourly_stats.countSimpangan baku byte yang diterima (float):
$hourly_stats.std_recd_bytesByte yang diterima rata-rata (float):
$hourly_stats.avg_recd_bytesWaktu mulai bucket jam dalam detik dari epoch Unix (bilangan bulat):
$hourly_stats.window_startWaktu 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_statsmelakukan agregasi harian awal. Fungsi ini menghitung total byte yang dipertukarkan setiap hari untuk setiap pasangan IP (sourcedantarget) 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_statsuntuk 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_senttahap penelusuran untuk lima peristiwa dengan aktivitas jaringan tertinggi.Tahap
top_5_bytes_sentmenghasilkan 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
rootmenghitung 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_statsmenelusuri pasangan IP yang memiliki aktivitas jaringan tinggi dalam jam yang sama.hourly_statsmenghasilkan 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.