Ringkasan parser

Didukung di:

Dokumen ini memberikan ringkasan tentang cara Google Security Operations mengurai log mentah ke format Model Data Terpadu (UDM).

Google SecOps dapat menerima data log yang berasal dari sumber penyerapan berikut:

  • Penerus Google SecOps
  • Feed Chronicle API
  • Chronicle API
  • Partner teknologi pihak ketiga

Secara umum, pelanggan mengirim data sebagai log mentah asli. Google SecOps mengidentifikasi perangkat yang menghasilkan log secara unik menggunakan LogType. LogType mengidentifikasi:

  • vendor dan perangkat yang menghasilkan log, seperti Cisco Firewall, Linux DHCP Server, atau Bro DNS.
  • parser yang mengonversi log mentah ke UDM terstruktur. Ada hubungan one-to-one antara parser dan LogType. Setiap parser mengonversi data yang diterima oleh satu LogType.

Google SecOps menyediakan serangkaian parser default yang membaca log mentah asli dan menghasilkan data UDM terstruktur menggunakan data dalam log mentah asli. Google SecOps mengelola parser ini. Pelanggan juga dapat menentukan petunjuk pemetaan data kustom dengan membuat parser khusus pelanggan. Jika Anda mengirim payload multi-baris, sistem akan menafsirkan setiap baris sebagai entri log terpisah.

Alur kerja penyerapan dan normalisasi

Parser berisi petunjuk pemetaan data. Parser menentukan cara data dipetakan dari log mentah asli ke satu atau beberapa kolom dalam struktur data UDM.

Jika tidak ada error penguraian, Google SecOps akan membuat data terstruktur UDM menggunakan data dari log mentah. Proses konversi log mentah ke data UDM disebut normalisasi.

Parser default dapat memetakan subset nilai inti dari log mentah. Biasanya, kolom inti ini adalah yang paling penting untuk memberikan insight keamanan di Google SecOps. Nilai yang tidak dipetakan tetap berada di log mentah, tetapi tidak disimpan dalam data UDM.

Pelanggan juga dapat menggunakan metode penyerapan Chronicle API untuk mengirim data dalam format UDM terstruktur. Untuk mengetahui informasi tentang cara bermigrasi dari Ingestion API lama ke Chronicle API, lihat Bermigrasi dari SIEM API lama ke Chronicle API.

Menyesuaikan cara data yang diserap diurai

Google SecOps menyediakan kemampuan berikut yang memungkinkan pelanggan menyesuaikan penguraian data pada data log asli yang masuk. Untuk mengetahui detail selengkapnya tentang cara mengelola parser ini, lihat Mengelola parser bawaan dan kustom.

  • Parser khusus pelanggan: pelanggan membuat konfigurasi parser kustom untuk jenis log tertentu yang memenuhi persyaratan spesifik mereka. Parser khusus pelanggan menggantikan parser default untuk LogType tertentu. Untuk mengetahui detail selengkapnya, lihat Mengelola parser bawaan dan kustom.
  • Ekstensi parser: Pelanggan dapat menambahkan petunjuk pemetaan kustom selain konfigurasi parser default. Setiap pelanggan dapat membuat kumpulan petunjuk pemetaan kustom yang unik. Petunjuk pemetaan ini menentukan cara mengekstrak dan mengubah kolom tambahan dari log mentah asli ke kolom UDM. Ekstensi parser tidak menggantikan parser default atau khusus pelanggan.

Contoh menggunakan log proxy web Squid

Bagian ini memberikan contoh log proxy web Squid dan menjelaskan cara nilai dipetakan ke data UDM. Untuk mengetahui deskripsi semua kolom dalam skema UDM, lihat Daftar kolom Model Data Terpadu.

Contoh log proxy web Squid berisi nilai yang dipisahkan spasi. Setiap data mewakili satu peristiwa dan menyimpan data berikut: stempel waktu, durasi, klien, kode hasil/status hasil, byte yang dikirim, metode permintaan, URL, pengguna, kode hierarki, dan jenis konten. Dalam contoh ini, kolom berikut diekstrak dan dipetakan ke dalam data UDM: waktu, klien, status hasil, byte, metode permintaan, dan URL.

1588059648.129 23 192.168.23.4 TCP_HIT/200 904 GET www.google.com/images/sunlogo.png - HIER_DIRECT/203.0.113.52 image/jpeg

Contoh proxy web squid

Saat Anda membandingkan struktur ini, perhatikan bahwa hanya subset data log asli yang disertakan dalam data UDM. Kolom tertentu wajib diisi dan kolom lainnya bersifat opsional. Selain itu, hanya subset bagian dalam data UDM yang berisi data. Jika parser tidak memetakan data dari log asli ke data UDM, Anda tidak akan melihat bagian data UDM tersebut di Google SecOps.

Nilai log dipetakan ke UDM

Bagian metadata menyimpan stempel waktu peristiwa. Perhatikan bahwa nilai dikonversi dari format Epoch ke RFC 3339. Konversi ini bersifat opsional. Stempel waktu dapat disimpan sebagai format Epoch, dengan prapemrosesan untuk memisahkan bagian detik dan milidetik ke dalam kolom terpisah.

Kolom metadata.event_type menyimpan nilai NETWORK_HTTP yang merupakan nilai yang dijumlahkan yang mengidentifikasi jenis peristiwa. Nilai metadata.event_type menentukan kolom UDM tambahan mana yang wajib diisi dan mana yang opsional. Nilai product_name dan vendor_name berisi deskripsi perangkat yang mudah digunakan yang mencatat log asli.

metadata.event_type dalam data Peristiwa UDM tidak sama dengan log_type yang ditentukan saat menyerap data menggunakan Chronicle API. Kedua atribut ini menyimpan informasi yang berbeda.

Bagian network berisi nilai dari peristiwa log asli. Perhatikan dalam contoh ini bahwa nilai status dari log asli diurai dari kolom 'kode hasil/status' sebelum ditulis ke data UDM. Hanya result_code yang disertakan dalam data UDM.

Nilai log dipetakan ke UDM

Bagian principal menyimpan informasi klien dari log asli. Bagian target menyimpan URL yang sepenuhnya memenuhi syarat dan alamat IP.

Bagian security_result menyimpan salah satu nilai enum untuk mewakili tindakan yang dicatat dalam log asli.

Ini adalah data UDM yang diformat sebagai JSON. Perhatikan bahwa hanya bagian yang berisi data yang disertakan. Bagian src, observer, intermediary, about, dan extensions tidak disertakan.

{
        "metadata": {
            "event_timestamp": "2020-04-28T07:40:48.129Z",
            "event_type": "NETWORK_HTTP",
            "product_name": "Squid Proxy",
            "vendor_name": "Squid"
        },
        "principal": {
            "ip": "192.168.23.4"
        },
        "target": {
            "url": "www.google.com/images/sunlogo.png",
            "ip": "203.0.113.52"
        },
        "network": {
            "http": {
                "method": "GET",
                "response_code": 200,
                "received_bytes": 904
            }
        },
        "security_result": {
            "action": "UNKNOWN_ACTION"
        }
}

Langkah-langkah dalam petunjuk parser

Petunjuk pemetaan data dalam parser mengikuti pola umum, sebagai berikut:

  1. Mengurai dan mengekstrak data dari log asli.
  2. Memanipulasi data yang diekstrak. Hal ini mencakup penggunaan logika kondisional untuk mengurai nilai secara selektif, mengonversi jenis data, mengganti substring dalam nilai, mengonversi ke huruf besar atau huruf kecil, dll.
  3. Menetapkan nilai ke kolom UDM.
  4. Menampilkan data UDM yang dipetakan ke kunci @output.

Mengurai dan mengekstrak data dari log asli

Menetapkan pernyataan filter

Pernyataan filter adalah pernyataan pertama dalam kumpulan petunjuk penguraian. Semua petunjuk penguraian tambahan terdapat dalam pernyataan filter.

filter {

}

Menginisialisasi variabel yang akan menyimpan nilai yang diekstrak

Dalam pernyataan filter, inisialisasi variabel perantara yang akan digunakan parser untuk menyimpan nilai yang diekstrak dari log.

Variabel ini digunakan setiap kali log individual diurai. Nilai di setiap variabel perantara akan ditetapkan ke satu atau beberapa kolom UDM nanti dalam petunjuk penguraian.

  mutate {
    replace => {
      "event.idm.read_only_udm.metadata.product_name" => "Webproxy"
      "event.idm.read_only_udm.metadata.vendor_name" => "Squid"
      "not_valid_log" => "false"
      "when" => ""
      "srcip" => ""
      "action" => ""
      "username" => ""
      "url" => ""
      "tgtip" => ""
      "method" => ""
    }
  }

Mengekstrak nilai individual dari log

Google SecOps menyediakan serangkaian filter, berdasarkan Logstash, untuk mengekstrak kolom dari file log asli. Bergantung pada format log, Anda menggunakan satu atau beberapa filter ekstraksi untuk mengekstrak semua data dari log. Jika stringnya adalah:

  • JSON native, sintaksis parser mirip dengan filter JSON yang mendukung log berformat JSON. JSON bertingkat tidak didukung.
  • Format XML, sintaksis parser mirip dengan filter XML yang mendukung log berformat XML.
  • pasangan kunci-nilai, sintaksis parser mirip dengan filter Kv yang mendukung pesan berformat pasangan kunci-nilai.
  • Format CSV, sintaksis parser mirip dengan filter Csv yang mendukung pesan berformat CSV.
  • semua format lainnya, sintaksis parser mirip dengan filter GROK dengan pola bawaan GROK . Hal ini menggunakan petunjuk ekstraksi gaya Regex.

Google SecOps menyediakan subset kemampuan yang tersedia di setiap filter. Google SecOps juga menyediakan sintaksis pemetaan data kustom yang tidak tersedia di filter. Lihat Referensi sintaksis parser untuk mengetahui deskripsi fitur yang didukung dan fungsi kustom.

Melanjutkan contoh log proxy web Squid, petunjuk ekstraksi data berikut mencakup kombinasi sintaksis Logstash Grok dan ekspresi reguler.

Pernyataan ekstraksi berikut menyimpan nilai dalam variabel perantara berikut:

  • when
  • srcip
  • action
  • returnCode
  • size
  • method
  • username
  • url
  • tgtip

Pernyataan contoh ini juga menggunakan kata kunci overwrite untuk menyimpan nilai yang diekstrak di setiap variabel. Jika proses ekstraksi menampilkan error, pernyataan on_error akan menetapkan not_valid_log ke true.

grok {
   match => {
     "message" => [
       "%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
     ]
   }
   overwrite => ["when","srcip","action","returnCode","size","method","url","username","tgtip"]
   on_error => "not_valid_log"
}

Memanipulasi dan mengubah nilai yang diekstrak

Google SecOps memanfaatkan kemampuan plug-in filter mutate Logstash untuk memungkinkan manipulasi nilai yang diekstrak dari log asli. Google SecOps menyediakan subset kemampuan yang tersedia di plug-in. Lihat Sintaksis parser untuk mengetahui deskripsi fitur yang didukung dan fungsi kustom, seperti:

  • mengonversi nilai ke jenis data yang berbeda
  • mengganti nilai dalam string
  • menggabungkan dua array atau menambahkan string ke array. Nilai string dikonversi ke array sebelum digabungkan.
  • mengonversi ke huruf kecil atau huruf besar

Bagian ini memberikan contoh transformasi data yang dibuat berdasarkan log proxy web Squid yang ditampilkan sebelumnya.

Mengubah stempel waktu peristiwa

Semua peristiwa yang disimpan sebagai data UDM harus memiliki stempel waktu peristiwa. Contoh ini memeriksa apakah nilai untuk data diekstrak dari log. Kemudian, contoh ini menggunakan fungsi tanggal Grok untuk mencocokkan nilai dengan format waktu UNIX.

if [when] != "" {
  date {
    match => [
      "when", "UNIX"
    ]
   }
 }

Mengubah nilai username

Pernyataan contoh berikut mengonversi nilai dalam variabel username ke huruf kecil.

mutate {
   lowercase => [ "username"]
   }

Mengubah nilai action

Contoh berikut mengevaluasi nilai dalam variabel perantara actiondan mengubah nilai menjadi ALLOW, BLOCK, atau UNKNOWN_ACTION yang merupakan nilai valid untuk kolom UDM security_result.action. Kolom UDM security_result.action adalah jenis yang dijumlahkan yang hanya menyimpan nilai tertentu.

if ([action] == "TCP_DENIED" or [action] == "TCP_MISS" or [action] == "Denied" or [action] == "denied" or [action] == "Dropped") {
      mutate {
        replace => {
          "action" => "BLOCK"
        }
      }
   } else if ([action] == "TCP_TUNNEL" or [action] == "Accessed" or [action] == "Built" or [action] == "Retrieved" or [action] == "Stored") {
     mutate {
        replace => {
          "action" => "ALLOW"
        }
     }
   } else {
      mutate {
        replace => {
          "action" => "UNKNOWN_ACTION" }
      }
   }

Mengubah alamat IP target

Contoh berikut memeriksa nilai dalam variabel perantara tgtip. Jika ditemukan, nilai tersebut akan dicocokkan dengan pola alamat IP menggunakan pola Grok yang telah ditentukan. Jika terjadi error saat mencocokkan nilai dengan pola alamat IP, fungsi on_error akan menetapkan properti not_valid_tgtip ke true. Jika kecocokan berhasil, properti not_valid_tgtip tidak akan ditetapkan.

if [tgtip] not in [ "","-" ] {
   grok {
     match => {
       "tgtip" => [ "%{IP:tgtip}" ]
     }
     overwrite => ["tgtip"]
     on_error => "not_valid_tgtip"
   }

Mengubah jenis data returnCode dan ukuran

Contoh berikut mengonversi nilai dalam variabel size ke uinteger dan nilai dalam variabel returnCode ke uinteger. Hal ini diperlukan karena variabel size akan disimpan ke kolom UDM network.received_bytes yang menyimpan jenis data int64. Variabel returnCode akan disimpan ke kolom UDM network.http.response_code yang menyimpan jenis data int32.

mutate {
  convert => {
    "returnCode" => "integer"
    "size" => "uinteger"
  }
}

Menetapkan nilai ke kolom UDM dalam peristiwa

Setelah nilai diekstrak dan diproses sebelumnya, tetapkan nilai tersebut ke kolom dalam data peristiwa UDM. Anda dapat menetapkan nilai yang diekstrak dan nilai statis ke kolom UDM.

Jika Anda mengisi event.disambiguation_key, pastikan kolom ini unik untuk setiap peristiwa yang dihasilkan untuk log tertentu. Jika dua peristiwa berbeda memiliki disambiguation_key yang sama, hal ini akan menyebabkan perilaku yang tidak terduga dalam sistem.

Contoh parser di bagian ini dibuat berdasarkan contoh log proxy web Squid sebelumnya.

Menyimpan stempel waktu peristiwa

Setiap data peristiwa UDM harus memiliki nilai yang ditetapkan untuk kolom UDM metadata.event_timestamp. Contoh berikut menyimpan stempel waktu peristiwa yang diekstrak dari log ke variabel bawaan @timestamp. Google Security Operations menyimpan stempel waktu ini ke kolom UDM metadata.event_timestamp secara default.

mutate {
  rename => {
    "when" => "timestamp"
  }
}

Menetapkan jenis peristiwa

Setiap data peristiwa UDM harus memiliki nilai yang ditetapkan untuk kolom UDM metadata.event_type. Kolom ini adalah jenis yang dijumlahkan. Nilai kolom ini menentukan kolom UDM tambahan mana yang harus diisi agar data UDM dapat disimpan. Proses penguraian dan normalisasi akan gagal jika salah satu kolom yang wajib diisi tidak berisi data yang valid.

replace => {
    "event.idm.read_only_udm.metadata.event_type" => "NETWORK_HTTP"
   }
}

Menyimpan nilai username dan method menggunakan pernyataan replace

Nilai di kolom perantara username dan method adalah string. Contoh berikut memeriksa apakah nilai yang valid ada dan, jika ada, menyimpan nilai username ke kolom UDM principal.user.userid dan nilai method ke kolom UDM network.http.method.

if [username] not in [ "-" ,"" ] {
  mutate {
    replace => {
      "event.idm.read_only_udm.principal.user.userid" => "%{username}"
    }
  }
}

if [method] != "" {
  mutate {
    replace => {
      "event.idm.read_only_udm.network.http.method" => "%{method}"
    }
  }
}

Menyimpan action ke kolom UDM security_result.action

Di bagian sebelumnya, nilai dalam variabel perantara action dievaluasi dan diubah menjadi salah satu nilai standar untuk kolom UDM security_result.action.

Kolom UDM security_result dan action menyimpan array item, yang berarti Anda harus mengikuti pendekatan yang sedikit berbeda saat menyimpan nilai ini.

Pertama, simpan nilai yang diubah ke kolom perantara security_result.action. Kolom security_result adalah induk dari kolom action.

mutate {
   merge => {
     "security_result.action" => "action"
   }
}

Selanjutnya, simpan kolom perantara security_result.action perantara ke security_result kolom UDM. Kolom UDM security_result menyimpan array item, sehingga nilai ditambahkan ke kolom ini.

 # save the security_result field
mutate {
  merge => {
    "event.idm.read_only_udm.security_result" => "security_result"
  }
}

Menyimpan alamat IP target dan alamat IP sumber menggunakan pernyataan merge

Simpan nilai berikut ke data peristiwa UDM:

  • Nilai dalam variabel perantara srcip ke kolom UDM principal.ip.
  • Nilai dalam variabel perantara tgtip ke kolom UDM target.ip.

Kolom UDM principal.ip dan target.ip menyimpan array item, sehingga nilai ditambahkan ke setiap kolom.

Contoh berikut menunjukkan pendekatan yang berbeda untuk menyimpan nilai ini. Selama langkah transformasi, variabel perantara tgtip dicocokkan dengan alamat IP menggunakan pola Grok yang telah ditentukan. Pernyataan contoh berikut memeriksa apakah properti not_valid_tgtip benar (true) yang menunjukkan bahwa tgtip nilai tidak dapat dicocokkan dengan pola alamat IP. Jika salah (false), nilai tgtip akan disimpan ke kolom UDM target.ip.

if ![not_valid_tgtip] {
  mutate {
    merge => {
      "event.idm.read_only_udm.target.ip" => "tgtip"
    }
  }
 }

Variabel perantara srcip tidak diubah. Pernyataan berikut memeriksa apakah nilai diekstrak dari log asli, dan jika ya, menyimpan nilai ke kolom UDM principal.ip.

if [srcip] != "" {
  mutate {
    merge => {
      "event.idm.read_only_udm.principal.ip" => "srcip"
    }
  }
}

Menyimpan url, returnCode, dan size menggunakan pernyataan rename

Pernyataan contoh berikut menyimpan nilai menggunakan pernyataan rename:

  • Variabel url disimpan ke kolom UDM target.url.
  • Variabel perantara returnCode disimpan ke kolom UDM network.http.response_code.
  • Variabel perantara size disimpan ke kolom UDM network.received_bytes.
mutate {
  rename => {
     "url" => "event.idm.read_only_udm.target.url"
     "returnCode" => "event.idm.read_only_udm.network.http.response_code"
     "size" => "event.idm.read_only_udm.network.received_bytes"
  }
}

Mengikat data UDM ke output

Pernyataan terakhir dalam petunjuk pemetaan data menampilkan data yang diproses ke data peristiwa UDM.

mutate {
    merge => {
      "@output" => "event"
    }
  }

Kode parser lengkap

Ini adalah contoh kode parser lengkap. Urutan petunjuk tidak mengikuti urutan yang sama seperti bagian sebelumnya dalam dokumen ini, tetapi menghasilkan output yang sama.

filter {

# initialize variables
  mutate {
    replace => {
      "event.idm.read_only_udm.metadata.product_name" => "Webproxy"
      "event.idm.read_only_udm.metadata.vendor_name" => "Squid"
      "not_valid_log" => "false"
      "when" => ""
      "srcip" => ""
      "action" => ""
      "username" => ""
      "url" => ""
      "tgtip" => ""
      "method" => ""
    }
  }

  # Extract fields from the raw log.
    grok {
      match => {
        "message" => [
          "%{NUMBER:when}\\s+\\d+\\s%{SYSLOGHOST:srcip} %{WORD:action}\\/%{NUMBER:returnCode} %{NUMBER:size} %{WORD:method} (?P<url>\\S+) (?P<username>.*?) %{WORD}\\/(?P<tgtip>\\S+).*"
        ]
      }
      overwrite => ["when","srcip","action","returnCode","size","method","url","username","tgtip"]
      on_error => "not_valid_log"
    }

  # Parse event timestamp
  if [when] != "" {
    date {
      match => [
        "when", "UNIX"
      ]
     }
   }

   # Save the value in "when" to the event timestamp
   mutate {
     rename => {
       "when" => "timestamp"
     }
   }

   # Transform and save username
   if [username] not in [ "-" ,"" ] {
     mutate {
       lowercase => [ "username"]
        }
      }
     mutate {
       replace => {
         "event.idm.read_only_udm.principal.user.userid" => "%{username}"
       }
     }


if ([action] == "TCP_DENIED" or [action] == "TCP_MISS" or [action] == "Denied" or [action] == "denied" or [action] == "Dropped") {
      mutate {
        replace => {
          "action" => "BLOCK"
        }
      }
   } else if ([action] == "TCP_TUNNEL" or [action] == "Accessed" or [action] == "Built" or [action] == "Retrieved" or [action] == "Stored") {
     mutate {
        replace => {
          "action" => "ALLOW"
        }
     }
   } else {
      mutate {
        replace => {
          "action" => "UNKNOWN_ACTION" }
      }
   }

  # save transformed value to an intermediary field
   mutate {
      merge => {
        "security_result.action" => "action"
      }
   }

    # save the security_result field
    mutate {
      merge => {
        "event.idm.read_only_udm.security_result" => "security_result"
      }
    }

   # check for presence of target ip. Extract and store target IP address.
   if [tgtip] not in [ "","-" ] {
     grok {
       match => {
         "tgtip" => [ "%{IP:tgtip}" ]
       }
       overwrite => ["tgtip"]
       on_error => "not_valid_tgtip"
     }

     # store  target IP address
     if ![not_valid_tgtip] {
       mutate {
         merge => {
           "event.idm.read_only_udm.target.ip" => "tgtip"
         }
       }
     }
   }

   # convert  the returnCode and size  to integer data type
   mutate {
     convert => {
       "returnCode" => "integer"
       "size" => "uinteger"
     }
   }

   # save  url, returnCode, and size
   mutate {
     rename => {
        "url" => "event.idm.read_only_udm.target.url"
        "returnCode" => "event.idm.read_only_udm.network.http.response_code"
        "size" => "event.idm.read_only_udm.network.received_bytes"
     }

     # set the event type to NETWORK_HTTP
     replace => {
        "event.idm.read_only_udm.metadata.event_type" => "NETWORK_HTTP"
     }
   }

   # validate and set source IP address
   if [srcip] != "" {
     mutate {
       merge => {
         "event.idm.read_only_udm.principal.ip" => "srcip"
       }
     }
   }

  # save  event to @output
   mutate {
     merge => {
       "@output" => "event"
     }
   }

} #end of filter

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