Narzędzia skryptowe do szybkiej analizy logów (scripting and SQL-based tools for instant log analysis)

Abstract

Suppose that we need to quickly analyze some logs after security incident, and we have only – or as much as – our own heads and the interpreter of some decent scripting language. We can quickly write some useful scripting tools that facilitate searching out the log files to find the kind of information we’re looking for. These scripts can be based on the regular expressions (regexp) or wildcards (globbing) approach. If the log volume is not very large, such scripts can prove to be sufficient for us. Otherwise, to achieve greater efficiency we need something more.

This paper presents a prototype of just such a solution. It uses loading of logs from flat text files into a database in order to then being able to process information more efficient than by REGEXP and GLOBBING way– using SQL and database tools.

Administratorzy systemów i analitycy zdarzeń bezpieczeństwa niejednokrotnie muszą szybko i sprawnie  przetwarzać duże wolumeny logów. Nie zawsze mają do natychmiastowej dyspozycji narzędzia, które mogą im to ułatwić. Myślę tu przede wszystkim o systemie klasy SIEM czy oprogramowaniu takim, jak choćby znakomity Splunk (www.splunk.com). Czasem trzeba posłużyć się czymś znacznie prostszym – narzędziem skryptowym własnego autorstwa.

Załóżmy, że musimy szybko przeprowadzić analizę logów po incydencie bezpieczeństwa, a do dyspozycji mamy jedynie – a może aż – własną głowę i interpreter jakiegoś przyzwoitego języka skryptowego. Możemy szybko napisać skrypty, które wyszukają w logach tego, na czym nam najbardziej zależy. Skrypty mogą szukać istotnych dla nas wzorców informacji w oceanie logów na podstawie wyrażeń regularnych (regexp) lub znaków uogólniających (globbing). Jeśli wolumen logów nie jest bardzo duży, to takie właśnie skrypty mogą okazać się dla nas w zupełności wystarczające. W przeciwnym razie, dla uzyskania większej wydajności możemy potrzebować czegoś więcej.

Niniejszy artykuł prezentuje prototyp takiego właśnie rozwiązania. Polega ono na załadowaniu logów z płaskich plików tekstowych do bazy danych, by potem móc przetwarzać informacje wydajniejszymi niż REGEXP i GLOBBING narzędziami bazodanowymi.

Podczas opracowywania tego narzędzia wybór padł na język skryptowy Tcl oraz na bazę SQLite. Dlaczego Tcl? Chyba dlatego, że go osobiście bardzo lubię i mam z nim związane pozytywne doświadczenia. Ponadto, Tcl jest zaimplementowany w oprogramowaniu systemowym znanych mi skądinąd niektórych z urządzeń Cisco. Tym niemniej zamiast Tcl-a możemy użyć jakiegokolwiek innego języka skryptowego, choćby Perla, Ruby’ego lub Pythona. Zresztą przepisanie skryptu na te języki jest czynnością raczej nieskomplikowaną dla każdego, kto zna podstawy „skryptowania” w dowolnym języku, choćby w języku powłoki. Dlaczego SQLite? Dlatego, że jest proste, darmowe narzędzie działające bezserwerowo, możliwe do zainstalowania na dowolnym PC-cie.  Oczywiście, po niewielkich modyfikacjach można skrypt dostosować do pracy z bardziej „skomplikowanymi” systemami bazodanowymi działającymi w oparciu o serwery – MySQL, Sybase, Oracle, MS SQL Server etc. Dobrze jeśli takowe systemy bazodanowe mamy „na podorędziu”, jednak – kiedy trzeba działać błyskawicznie – możemy nie mieć czasu na ich instalację i uruchomienie. Wtedy lepsze jest to, co prostsze, czyli w naszym przypadku SQLite.

Przygotowania

Na początek musimy przygotować płaski plik tekstowy zawierający logi. Przy pomocy edytora tekstowego należy dodatkowo dopisać w jego pierwszym wierszu definicję struktury tabeli. Skrypt został bowiem napisany z założeniem automatycznego tworzenia tabeli w bazie, na podstawie informacji o jej strukturze zawartej w pierwszym wierszu pliku z danymi wejściowymi.

Przykład definicji tabeli:

timestamp text, severity integer, facility text, message text

Odpowiada on logom o następującej strukturze:

2012/12/25;1;SYSTEM;Failure in MEM podsystem
2012/12/27;1;SYSTEM;Failure in CPU podsystem
2012/12/29;1;SYSTEM;Failure in I/O podsystem

W pierwszym wierszu pliku podane są oddzielone przecinkami pary: nazwa pola – typ pola. Oczywiście, sposób zdefiniowania struktury jest kwestią całkowicie umowną, byleby potem konsekwentnie i bezbłędnie go oprogramować w kodzie skryptu.

Zakładam, że na tym etapie dysponujemy już interpreterem Tcl-a oraz środowiskiem SQLite. Jeśli nie, to polecam doskonałe narzędzia Tcl do pobrania za darmo ze strony Activestate (www.activestate.com). W systemach unixowych interpreter Tcl powinien być dostępny, jako narzędzie standardowe (oczywiście jeśli został zainstalowany takowy pakiet). SQLite można, także za darmo, pobrać ze strony http://www.sqlite.org.

Jak działa skrypt?

Logika skryptu jest niezwykle prosta:

  1. Sprawdzenie poprawnej składni wywołania;
  2. Odczytanie pliku źródłowego i inicjalizacja zmiennych;
  3. Utworzenie tabeli jeśli takowa jeszcze nie istnieje;
  4. Załadowanie danymi z pliku tabeli bazy danych.

Plik źródłowy skryptu posiada komentarze, które wyjaśniają szczegóły jego działania.

Zatem, wywołujemy skrypt:

tclsh skrypt.tcl plik_z_logami

Sprawdzamy, czy powstała baza danych, jakie zawiera tabele i czy została zasilona danymi:

sqlite log_database.db
SQLite version 3.7.14.1 2012-10-04 19:37:12
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
log

sqlite> .schema log
CREATE TABLE log('id integer primary key autoincrement, timestamp text, severit integer, facility text, message text');

sqlite> select * from log;
2012/12/25;1;SYSTEM;Failure in MEM podsystem
2012/12/27;1;SYSTEM;Failure in CPU podsystem
2012/12/29;1;SYSTEM;Failure in I/O podsystem
sqlite>

Po załadowaniu bazy danych możemy przetwarzać logi narzędziami bazodanowymi.

Dalsze doskonalenie

Skrypt, który jest tematem tego artykułu jest – co podkreślam – jedynie prototypem, a nie gotowym rozwiązaniem. Chcąc doprowadzić go do postaci w pełni użytecznego narzędzia można pójść dalej i rozwinąć go, choćby w kierunku:

  • Zbudowania graficznego lub tekstowego interfejsu komunikacji z użytkownikiem (interakcja z użytkownikiem, parametryzacja, browning, prezentacja wyników itd.);
  • Poprawienia obsługi wyjątków;
  • Czytania pliku z logami wiersz po wierszu, zamiast w całości do zmiennej w pamięci operacyjnej;
  • Pozyskiwania informacji przez generowanie zapytań do bazy i zapisywanie wyników ich działania w plikach z danymi wyjściowymi lub dalsze przetwarzanie tych danych w procesie zarządzania zdarzeniami.

Zachęcam do dalszych eksperymentów. Jeśli udało mi się zainspirować czytelników mojego artykułu do realizacji nowych pomysłów, to mój cel został spełniony.

Listing

package require sqlite3

# Przeczytaj tekstowy plik płaski z logami z dysku
# Odczytaj stamtąd nazwy i typy pól oraz strukturę tabeli
# Zainicjalizuj tymi danymi zmienne skryptu.
# -------------------------------------------------------
# Funkcja file_read do czytania pliku z logami
# Poprawne jej wykonania zwraca zawartość pliku
# Błąd wykonania skutkuje zwróceniem pustego łańcucha znaków
# oraz wyprowadzeniem komunikatu o błędzie.
# Parametrem skryptu jest nazwa pliku (ze ścieżką dostępu, jeśli
# plik znajduje się poza bieżącym katalogiem).
# --------------------------------------------------------

proc file_read {filename} { 
   if {[catch {set fp [open $filename r]}]} {
      puts stderr "Could not open $filename for reading"
       return ""
   }
   set data [read $fp]
   close $fp
   return $data
}

# ----- Sprawdzenie poprawnej składni wywołania ----- 
if {$argc < 1} {
   puts "Proper syntax: tclsh $argv0 plik_z_danymi"
   exit
} else {
   set filename [lindex $argv 0]
}

# ------------------------------------------------------------- 
# Przypisanie zmiennej dane wyniku działania funkcji file_read 
# -------------------------------------------------------------
set dane [file_read $filename]
set lista [split $dane "\n"]

# ------------------------------------------------------------------------------------
# Odczytaj strukturę bazy z pierwszego elementu listy (pierwszy wiersz pliku z logami)
# ------------------------------------------------------------------------------------
set struktura [lindex $lista 0]

# ---- Inicjalizacja zmienej listowej lista_zmiennych
set lista_zmiennych ""

# ------------------------------------------------------------------------- 
# Dopisanie do listy lista_zmiennych kolejnych elementów zmiennej struktura
# odseparowanych od siebie znakiem przecinka
# ------------------------------------------------------------------------- 
foreach elem [split $struktura ","] {
   append lista_zmiennych ", " [lindex $elem 0] 
}

# ----- Usunięcie z listy_zmiannych początkowego (zbędnego) przecinka
regsub -all {^, +} $lista_zmiennych "" lista_zmiennych

# ----- Dopisanie pola indeksu tabeli bazy danych
set prefix "id integer primary key autoincrement"
set struktura [format "%s, %s" $prefix $struktura]
set wielkosc [llength $lista]

# ---------------------------------------------------------------------------------
# Utworzenie bazy danych w pliku log_database.db w bieżącym katalogu
# Utworzenie tabeli log w bazie danych, jeśli takowa jeszcze nie została wykreowana
# ---------------------------------------------------------------------------------
sqlite3 log_db ./log_database.db
log_db eval "CREATE TABLE IF NOT EXISTS log('$struktura')"

# -----------------------------------------------
# Zasilenie bazy danych logami z pliku tekstowego
# -----------------------------------------------
for {set i 1} {$i<$wielkosc} {set i [expr $i + 1]} {
   set logi [lindex $lista $i]
   puts "Pozycja $i: $logi"
   log_db eval "INSERT INTO log VALUES('$logi')"
}

Informacje Janusz Nawrat
Just ordinary man who likes thinking...

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

TOMASZ WEŁNA

artysta grafik | wykładowca

PRACOWNIA OKO

Szkoła Rysunku Malarstwa i Grafiki DR TOMASZA WEŁNY | KRAKÓW | Plac Matejki 10 | tel 691 81 75 74

Piękno neurobiologii

Blog Jerzego Vetulaniego

Teoria muzyki, zasady muzyki, podstawy muzyki

Teoria muzyki, zasady muzyki, podstawy muzyki - czyli to co każdy amator muzyki wiedzieć powinien :)

Personal Development & Inspirations

Przemyślenia i refleksje, którymi warto się podzielić (blog by Janusz Nawrat)

Business IT Cooperation Platform

Biznes i IT - dwa światy, które muszą współdziałać

%d bloggers like this: