SIEM – kicsiben

Egy korábbi - a forgalomelemzésről szóló - cikkemben említettem, hogy az IDS által generált riasztásokat érdemes lehet egy ezek kezelésére kitalált rendszernek átadni, ahol aztán majd a többi rendszerünkből érkező egyéb logokkal együtt értelmezhetjük azokat. Végül pedig megtehetjük a szükséges lépéseket a feltárt probléma és/vagy biztonsági incidens megoldása érdekében. Az ilyen rendszert hívjuk SIEM-nek. Ennek azonban szinte kizárólag csak nagyvállalati (enterprise) környezetben van értelme. Legfőképp azért mert a logok és riasztások értelmezése és feldolgozása komoly szakmai tapasztalatokat, 7x24-es felügyeletet, és nem utolsó sorban hatalmas hardver erőforrásokat is igényel. Manapság azonban egyre több IT eszközünk van már az otthonunkban is, amikről általában fogalmunk sincs hogy mit csinálnak. A többséget ez valójában nem is nagyon érdekli. Na ez a cikk azon kisebbségnek szól, akikben már legalább az az igény felmerült, hogy jó lenne látni kivel/mivel kommunikál  az okos TV, a konzol, az IP kamera, a NAS, vagy az okos hűtő. Vagy éppen milyen támadási próbálkozások érik a routert az internet felől. Itt nyilván nem igény a 7x24-es felügyelet, és egy rack szekrénnyi szervert sem fogunk mindezért a spájzba tenni... Használjuk azt amink van, de legalábbis mindenképp alkalmazkodunk az otthoni eszközök (nagyon) limitált erőforrásaihoz. Ez azt jelenti, hogy eleve szóba sem jöhet egyik dobozos SIEM termék sem. Nézzük, mi az amire mindenképp szükség lesz:
  • NAS - mint központi log gyűjtő eszköz

Egy NAS amúgy is praktikus és hasznos dolog, de hogy mire jó azt most itt nem részletezném, sőt a továbbiakban feltételezem, hogy van még rajta szabad hely, és hogy igény szerint tudsz rá telepíteni további szoftvereket is.

  • Router - mint elsődleges log forrás
Router  várhatóan ugyan mindenkinek van otthon, ám ez legtöbb esetben a szolgáltató tulajdona, és mi csak használati jogot kaptunk rajta. Ezesetben is feltételezem, hogy olyan routered van, ami tud távoli szerverre logolni, és tetszés szerint konfigurálhatod.

Log gyűjtés

Az első lépés, hogy legyen a hálózatban egy olyan eszköz, ami befogadja a többi eszköz által küldött logokat. Ahogy az a fentiekből már kiderülhetett, otthoni körülmények között erre a legalkalmasabb eszköz egy NAS. Főleg akkor, ha már amúgy is van otthon ilyen eszközünk :) Persze, kell hogy tudja a log gyűjtés funkciót, és a legjobb, ha ezt a syslog-ng szoftver segítségével teszi. A Synology termékei esetében például ez az ideális állapot adott, már csak megfelelően fel kell konfigurálni. A továbbiakban én a nyers - és így gyártófüggetlen - konfigurációs állománnyal (/etc/syslog-ng/syslog-ng.conf) fogom bemutatni a szükséges beállításokat. Remélhetőleg a gyártók által adott grafikus felület nem butítja le a syslog-ng nagyszerű lehetőségeit, és feltételezem mindenki megtalálja, hol kell ezeket bekattintani a grafikus felületen. A következő konfig részlet felelős azért, hogy a lokálisan a NAS-on futó egyéb alkalmazások, és a saját maga által generált logokat is "befogadja".
source s_local {
 system();
 internal();
};
Ez a szekció pedig ahhoz kell, hogy a hálózaton is képes legyen fogadni (a default 514 TCP és UDP portokon) a küslő log források által küldött üzeneteket.
source s_network {
 syslog(transport(udp));
 syslog(transport(tcp))
};
Természetesen, a fenti példák önállóan nem fognak működő konfigurációt eredményezni, ezek csak azok a részletek, amiket mindenképpen tartalmaznia kell a a végső teljes konfigurációs állománynak.

Log feldolgozás

Ha már egy központi helyre beérkeztek a logjaink, akkor jöhet a következő lépés, a tárolásuk előtti feldolgozásuk, azaz parszolásuk. Mivel a syslog üzenetek alapvetően struktúrálatlanok, és ráadásul a többféle forrás miatt az üzenetek felépítése is különböző, így nincs könnyű dolgunk. És mivel a parszolás lényege, hogy megkönnyítsük a további feldolgozásukat, ezért előre tudni kell, hogy mit is szeretnénk velük csinálni. Jelen projekt célja, hogy a logok struktúráltan legyenek tárolva, és kiemeljük belőle a számunkra érdekes információkat. Első körben egy egyszerű szűrővel külön választjuk a csomagszűrő logjait, és az addrwatch program által generált üzeneteket:
filter f_iptables { match("IN=" value("MESSAGE")) and match("OUT=" value("MESSAGE")); };
filter f_addrwatch { program("addrwatch"); };
Majd a syslog-ng parszolási képességeit is bevetjük:
parser p_iptables {
 kv-parser (prefix("fw."));
};

parser p_arp {
 csv-parser(
 prefix("arp.")
 columns("facility" "timestamp", "interface", "vlan", "MAC", "IP", "type")
 delimiters(" ")
 );
};
Az első példában egyszerűen csak egy prefixet adunk a beépített kv-parser által kigyűjtött mezőknek, a második esetben pedig a perfixen kívül, mi magunk definiáljuk, hogy a továbbiakban melyik mezőket szeretnénk felhasználni az eredeti syslog üzenetből.

Log tárolás

A parszolás után jöhet az üzenetek tárolása. A syslog-ng rengeteg lehetősége közül én a mysql-t választottam, mert:
  • mindenképpen struktúrált formában kell tárolni az üzeneteket, a későbbi egyszerű és gyors feldolgozhatóság (kereshetőség) érdekében,
  • gyenge hardvereken is hatékonyan alkalmazható,
  • a NAS-on már eleve telepítve, sőt más funkciók miatt használva is volt.
Az alábbi konfig részlet tehát az sql adatbázisokról szól:
destination mysql_messages {
 sql(type(mysql)
 host("localhost") username("syslog") password("*****")
 database("syslog")
 table("messages")
 columns("timestamp", "host", "program", "pid", "severity", "message")
 values("${YEAR}-${MONTH}-${DAY} ${HOUR}:${MIN}:${SEC}", "${HOST}", "${PROGRAM}", "${PID}", "${LEVEL_NUM}","${MESSAGE}"));
};

destination mysql_packetfilter {
 sql(type(mysql)
 host("localhost") username("syslog") password("*****")
 database("syslog")
 table("packetfilter")
 columns("timestamp", "host", "IN_Interface", "MAC", "SRC_IP", "SRC_Port", "OUT_Interface", "DST_IP", "DST_Port", "Protocol", "Type", "Action", "Chain")
 values("${YEAR}-${MONTH}-${DAY} ${HOUR}:${MIN}:${SEC}", "${HOST}", "${fw.IN}", "${fw.MAC}", "${fw.SRC}", "${fw.SPT}", "${fw.OUT}", "${fw.DST}", "${fw.DPT}", "${fw.PROTO}", "${fw.TYPE}", "${fw.A}", "${fw.C}"));
};

destination mysql_addrwatch {
 sql(type(mysql)
 host("localhost") username("syslog") password("*****")
 database("syslog")
 table("addrwatch")
 columns("timestamp", "vlan", "MAC", "IP")
 values("${YEAR}-${MONTH}-${DAY} ${HOUR}:${MIN}:${SEC}", "${arp.vlan}", "${arp.MAC}", "${arp.IP}"));
};
A példában látható hogy 3 külön adatbázis táblába fogom tárolni a logokat. A táblák nevei remélhetőleg eléggé beszédesek ahhoz, hogy ne kelljen túlmagyarázni melyik mire való, és bízom benne, hogy a korábbi filterek és parszerek alkalmazása is kezd értelmet nyerni. Az általam használt változók közt vannak beépített makrók, és a parszerek által létrehozott változók egyaránt. Ezek megkülönböztetésében (is) sokat segít az általam is használt prefixálás. Az adatbázishoz való kapcsolódást minden esetben külön meg kell adni, és az ehhez szükséges felhasználót és (adatbázist) előre el kell készíteni. Ehhez alapvető SQL ismeretek szükségesek, ennek lépéseit nem részletezem. A táblákat maga a syslog-ng is képes lenne dinamikusan létrehozni, azonban ajánlatos ezeket előre elkészíteni. Az itt vázolt példák működőképesk, ám még közel sincsenek a végleges állapotukban. (Az adatbázis indexek hiányosságai is ezt bizonyítják ;) Végül, íme az utolsó konfig részlet, ami értelmet ad az eddig bemutatott darabkáknak:
log { source(s_network); filter(f_iptables); parser(p_iptables); destination(mysql_packetfilter);};
log { source(s_network); filter(f_addrwatch); parser(p_arp); destination(mysql_addrwatch);};
log { source(s_local); source(s_network); destination(mysql_messages);};

Log források

Nyilvánvaló, hogy logok nélkül értelmetlen az egész projekt. Szóval minél több log forrást be tudunk kötni a rendszerbe, annál több információval dolgozhatunk, így annál több mindent fogunk tudni kideríteni. A példámban a következő log források szerepelnek:

NAS

A legtöbb NAS-on futó szoftver valamilyen Linux származék, így maga az OS, és a rajta futó legtöbb alkalmazás syslog kompatibilis. Tehát, képes az üzeneteit syslog-on keresztül a tudtunkra hozni. Az már egy másik kérdés, hogy ebből a NAS gyártók milyen lehetőségeket hagytak meg a felhasználók számára. A fenti példát követve várhatóan a NAS (és a rajta futó alkalmazások) logjai is az adatbázisba kerülnek majd.

Router

Nem meglepő módon, a legtöbb router szintén Linux alapokra épült, így tőlük is várhatunk logokat. Sőt, mivel ez az otthoni hálózatunk egyik kiemelt eleme, így tőle várjuk a legfontosabb üzeneteket. Persze megint a erősen gyártókra vagyunk utalva, hacsak nem cseréltük le a rajta léfő firmware-t  DD-WRT, OpenWRT vagy épp LEDE megoldására. Én az utóbbit használom, amin a távoli loggyűjtő szerver beállítása magától értetődő, csak a NAS IP címét kell tudni hozzá.

Ahogy a fenti példa konfigokból is kiderülhetett, a log üzeneteket szétválogathatjuk pl. az üzenetet küldő szoftverek szerint:

csomagszűrő
Ami - szinte minden routeren -  az iptables. Azonban hogy ez mit logol az már beállítás függő. Nekem a LEDE "gyári megoldása" (sem) szimpatikus, így saját magam hoztam létre a routeren a csomagszűrő szabályokat. És hogy értelmezhető logokat küldjön, egyedi  'log-prefix' -eket használtam, amiket fel is parszoltam.
 -j LOG --log-prefix "A=DROP C=inet "
Ami azt jelenti, hogy ezek nélkül az 'Action' és a 'Chain' mezők üresen maradnak az adatbázisban.
addrwatch
Ez a program (amit OpenWRT vagy LEDE esetén utólag kell telepíteni) szintén a routeren fut, és a hálózatban megjelenő MAC - és a hozzájuk tartozó IP címekről ad információt. Ez önmagában még nem túl hasznos, de folyamatban van egy másik projektem, ami ennek  segítségével értesít majd engem a hálózatomra lépett minden új eszközről.

Természetesen, további alkalmazásokat (openvpn, dns, dhcp, ssh)  és/vagy eszközöket (WiFi AP, IP kamera, riasztó) is bevonhatunk a részletes(ebb) parszolásba, annak érdekében, hogy még több használható adat kerüljön struktúráltan tárolásra. Sőt, köszönhetően a syslog-ng sokoldalúságának, az egyesével beérkező logsorokat korrelálhatjuk is egymással, ezzel még tovább növelve a rendszerünk hatékonyságát.


Mivel a napi munkám során nagyvállalati SIEM megoldásokkal dolgozom, így tisztában vagyok vele, hogy ez így még messze nem nevezhető SIEM -nek :) Azonban azt is látom, hogy a logok jól megtervezett összegyűjtése, és előfeldolgozása elengedhetetlen feladat egy SIEM rendszer bevezetése előtt. Tehát, ha mindez megvan, akkor már "csak" pár lekérdezést és grafikont kell készíteni, hogy könnyen értelmezhető információkat kapjunk az összegyűjtött logokból :) Mivel Itt is a rendelkezésünkre álló hardver erőforrás lesz a szűk keresztmetszet, így a piacon jelenleg fellelhető, óriási erőforrásokat igénylő megoldások továbbra sem jöhetnek szóba. Ezt is újra kell tervezni - kicsiben :)