SSH védelem erősítése további Fail2Ban szűrőmintával a Debian 8 (Jessie) rendszeren

botond küldte be 2019. 05. 09., cs – 23:39 időpontban

Tartalom

 

Bevezető

Debian 8 (Jesssie) alapú szerverünkön előfordulhat, hogy a Fail2Ban használata mellett is becsúsznak olyan naplóbejegyzések, amiket a rendszeren lévő 0.8.13-as verziójú Fail2Ban szűrői nem ismernek fel, így az ezeket a bejegyzéseket előidéző támadások ellen rendszerünk nem annyira védett.

Ebben a leírásban az SSH kiszolgálónkat érő véletlenszerű felhasználónevekkel történő próbálkozások blokkolását fogjuk megoldani a Fail2Ban szűrőmintáinak bővítésével.

Ezt a leírást azoknak az olvasóknak készítettem akik Debian 8 (Jessie) alapú szervert üzemeltetnek és használják rajta a Fail2Ban programot, aminek szívesen fokoznák tovább a hatékonyságát egy újabb szűrőminta beállításával.

 

 

A probléma felderítése

Első körben észre kell tudnunk venni a támadásokat, mert általában ezek a háttérben rejtőzve zajlanak. Ezért nem elég a telepített védelmi eszközeink hatékony működésére hagyatkoznunk, hanem muszáj rendszeresen bogarásznunk a naplófájlokat, valamint a megfelelő lekérdezőparancsok futtatásával kaphatunk további információt rendszerünk biztonsági állapotáról.

E leírás tárgyát képező támadásokat először a lastb paranccsal figyelhetjük meg root-ként:

lastb

A parancs a sikertelen felhasználói belépési kísérleteket listázza ki a /var/log/wtmp fájlból, ami nem szöveges fájl, így csak ezzel a paranccsal tudjuk olvasni rendesen.

Ennek a kimenetén vagy csak egy sort kapunk, például:

btmp begins Wed May  1 00:06:02 2019

Ilyenkor a jelzett időponttól kezdődően nem történt sikertelen belépési kísérlet.

Vagy pedig kapunk egy rövidebb-hosszabb listát a belépési próbálkozásokról. Például:

ftptest  ssh:notty    <kliens IP-címe>   Wed May  8 16:30 - 16:30  (00:00)    
ftptest  ssh:notty    <kliens IP-címe>   Wed May  8 16:30 - 16:30  (00:00)    
apagar   ssh:notty    <kliens IP-címe>   Tue May  7 15:33 - 15:33  (00:00)    
apagar   ssh:notty    <kliens IP-címe>   Tue May  7 15:33 - 15:33  (00:00)    
user01   ssh:notty    <kliens IP-címe>   Mon May  6 15:20 - 15:20  (00:00)    
user01   ssh:notty    <kliens IP-címe>   Mon May  6 15:20 - 15:20  (00:00)    
root     ssh:notty    <kliens IP-címe>   Sun May  5 15:20 - 15:20  (00:00)    
root     ssh:notty    <kliens IP-címe>   Sun May  5 14:53 - 14:53  (00:00)    

btmp begins Sun May  5 14:53:32 2019

Ahol az első oszlop tartalmazza a felhasználóneveket, amikkel próbálkoznak, majd a konzol vagy távoli SSH belépés megjelenítése. Jelen példában távoli próbálkozásokról van szó. Ezt követi a belépni próbáló kliens IP-címe, majd utána jön az esemény időpontja.

Ez egy rövid lista, amit már a szűrő beállítása után napok elteltével listáztam, így már csak napi egy próbálkozás maradt, de előtte körülbelül percenként érkezett egy ilyen próbálkozás.

Ezekről a /var/log/auth.log fájlban is kaphatunk információkat, ha a következőképpen keresünk rá:

cat /var/log/auth.log | grep -i "invalid user"
May  6 15:20:15 <saját hosztnevünk> sshd[xxx]: Invalid user user01 from <próbálkozó IP-címe>
May  6 15:20:15 <saját hosztnevünk> sshd[xxx]: input_userauth_request: invalid user user01 [preauth]
May  6 15:20:17 <saját hosztnevünk> sshd[xxx]: Failed password for invalid user user01 from <próbálkozó IP-címe> port xxx ssh2
[...]

(Minden próbálkozás itt 3 sort eredményez)

Nagyobb mennyiségben ezek veszélyt jelenthetnek egy idő után, mert egy létező felhasználó és annak gyengén beállított jelszava esetén a nagy számok törvénye alapján van rá némi esély, hogy eltalálják. Persze az esély így is nagyon alacsony, de ha tudunk ellene hatékonyan védekezni, akkor miért ne tennénk?

A védelem hiányosságának oka

A probléma abból ered, hogy a Debian 8 (Jessie) rendszerre a hivatalos csomagtárból telepíthető 0.8.13-as verziójú Fail2Ban csomag még nem tartalmazza erre az esetre a szűrőmintát. Ha a Fail2Ban kliens programjával lekérjük az SSH jail-unk állapotát, akkor nem is találunk benne sok mindent:

fail2ban-client status ssh
Status for the jail: ssh
|- filter
|  |- File list:	/var/log/auth.log 
|  |- Currently failed:	0
|  `- Total failed:	0
`- action
   |- Currently banned:	0
   |  `- IP list:	
   `- Total banned:	0

Tehát hiába sorakoznak a /var/log/auth.log fájlunkban az "invalid user" -es bejegyzések, a Fail2Ban mégse blokkolja őket.

 

 

A megoldás

Itt javasolnám, hogy az SSH démont állítsuk át csak hitelesítő kulcsos belépésre, amennyiben módunkban áll. Abban az esetben, ha mégis szükségünk lenne a jelszavakkal történő bejelentkezésekre (pl több ügyfél, változó helyekről történő belépés szükségessége, stb), folytassuk ezt az útmutatót.

A megoldás egyszerűbb, mint gondolnánk: a Debian 9 (Stretch) csomagtárában található Fail2Ban 0.9.6 -os változat már tartalmazza a megfelelő szűrőmintát, amire itt szükségünk lesz. Itt most nem kell forrásból telepíteni az újabb változatot a Debian 8-ra, hanem egyszerűen átvesszük belőle a szükséges szűrőt.

Szűrőminta átvétele a Debian 9-ből

Ha van éppen kéznél egy Debian 9 (Stretch) telepítésünk is, és van rajta Fail2Ban, vagy feltelepítettük, akkor csak listázzuk ki a megfelelő szűrőfájlt:

cat /etc/fail2ban/filter.d/sshd.conf

Ennek a kimenete, amiben a 0.9.6-os verzióhoz tartozó szűrőminták vannak:

[...]
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error|failed) for .* from <HOST>( via \S+)?\s*$
            ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
            ^%(__prefix_line)sFailed \S+ for (?P<cond_inv>invalid user )?(?P<user>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)) from <HOST>(?: port \d+)?(?: ssh\d*)?(?(cond_user):|(?:(?:(?! from ).)*)$)
            ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
            ^%(__prefix_line)s[iI](?:llegal|nvalid) user .*? from <HOST>(?: port \d+)?\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
            ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
            ^%(__prefix_line)s(?:error: )?Received disconnect from <HOST>: 3: .*: Auth fail(?: \[preauth\])?$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
            ^(?P<__prefix>%(__prefix_line)s)User .+ not allowed because account is locked<SKIPLINES>(?P=__prefix)(?:error: )?Received disconnect from <HOST>: 11: .+ \[preauth\]$
            ^(?P<__prefix>%(__prefix_line)s)Disconnecting: Too many authentication failures for .+? \[preauth\]<SKIPLINES>(?P=__prefix)(?:error: )?Connection closed by <HOST> \[preauth\]$
            ^(?P<__prefix>%(__prefix_line)s)Connection from <HOST> port \d+(?: on \S+ port \d+)?<SKIPLINES>(?P=__prefix)Disconnecting: Too many authentication failures for .+? \[preauth\]$
            ^%(__prefix_line)s(error: )?maximum authentication attempts exceeded for .* from <HOST>(?: port \d*)?(?: ssh\d*)? \[preauth\]$
            ^%(__prefix_line)spam_unix\(sshd:auth\):\s+authentication failure;\s*logname=\S*\s*uid=\d*\s*euid=\d*\s*tty=\S*\s*ruser=\S*\s*rhost=<HOST>\s.*$
[...]

Innen egyetlen sorra van szükségünk, mégpedig amelyiket zölddel emeltem ki. Ez a szűrőminta tökéletesen illeszkedik a fentebb bemutatott auth.log fájlban előforduló "invalid user" típusú hibaüzenetekre. Ha nincs kéznél Debian 9 telepítésünk, vagy más disztribúcióban lévő 0.9-es Fail2Ban filterünk, akkor használjuk az itt lévő mintát.

Másoljuk ki ezt a sort, majd illesszük be a Debian 8 (Jessie) rendszerben található sshd.conf fájlba:

nano /etc/fail2ban/filter.d/sshd.conf

Hasonlóan tehetjük itt is a 3. sorba, hogy utána így nézzen ki a fájlunk failregex része:

[...]
failregex = ^%(__prefix_line)s(?:error: PAM: )?[aA]uthentication (?:failure|error) for .* from <HOST>( via \S+)?\s*$
            ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from <HOST>\s*$
            ^%(__prefix_line)sFailed \S+ for (?P<cond_inv>invalid user )?(?P<user>(?P<cond_user>\S+)|(?(cond_inv)(?:(?! from ).)*?|[^:]+)) from <HOST>(?: port \d+)?(?: ssh\d*)?(?(cond_user):|(?:(?:(?! from ).)*)$)
            ^%(__prefix_line)sFailed \S+ for .*? from <HOST>(?: port \d*)?(?: ssh\d*)?(: (ruser .*|(\S+ ID \S+ \(serial \d+\) CA )?\S+ %(__md5hex)s(, client user ".*", client host ".*")?))?\s*$
            ^%(__prefix_line)sROOT LOGIN REFUSED.* FROM <HOST>\s*$
            ^%(__prefix_line)s[iI](?:llegal|nvalid) user .* from <HOST>\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because not listed in AllowUsers\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because listed in DenyUsers\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because not in any group\s*$
            ^%(__prefix_line)srefused connect from \S+ \(<HOST>\)\s*$
            ^%(__prefix_line)sReceived disconnect from <HOST>: 3: \S+: Auth fail$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because a group is listed in DenyGroups\s*$
            ^%(__prefix_line)sUser .+ from <HOST> not allowed because none of user's groups are listed in AllowGroups\s*$
[...]

Mentsük le.

Jail konfiguráció ellenőrzése és finomhangolása

Ezután nyissuk meg a jail.conf fájlt, hogy ellenőrizzük az SSH beállításokat:

nano /etc/fail2ban/jail.conf

Itt keressük meg az "[ssh]" jail-t:

[...]
[ssh]

enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 2
findtime = 3600
[...]

És ellenőrizzük a beállításokat:

  • enabled: true. Legyen bekapcsolva a jail.
  • port: ssh. Ha az alapértelmezet 22-es SSH portszámtól eltérő portot használunk, akkor itt írjuk át a megfelelőre
  • filter: sshd. Itt hivatkozik az ssh jail a megfelelő szűrőfájlra.
  • logpath: ezt a naplófájlt figyeli a Fail2Ban
  • maxretry: Itt szabályozhatjuk a blokkolás szigorúságát. Elvétett jelszó után még ennyi próbálkozást enged.
  • findtime: Itt pedig másodpercekben meghatározhatjuk, hogy mekkora időszeleten belül figyelje a rendszer az azonos IP-címekkel elkövetett hibás belépési kísérleteket

Ezeket állítsuk be saját igényeinknek megfelelően. A fenti példában 2 újra próbálkozást engedtem 3600 másodpercen belül, tehát ez elég szigorú beállítás.

Ha ezzel is megvagyunk, akkor mentsük le a jail.conf fájlt is.

Fail2Ban újraindítása

Ezután már csak a Fail2Ban újraindítás maradt hátra:

systemctl restart fail2ban.service

A systemctl újraindító parancsa után még győződjünk meg, hogy valóban el is indultak-e a jail-ok, mert egy hibás karakterrel a szűrőben már nem tudja elindítani őket:

cat /var/log/fail2ban.log | tail -20

És ebben látnunk kell, hogy szépen elindult minden jail:

[...]
2019-05-09 23:15:29,356 fail2ban.jail   [31572]: INFO    Jail 'ssh' started
2019-05-09 23:15:29,358 fail2ban.jail   [31572]: INFO    Jail 'apache' started
2019-05-09 23:15:29,359 fail2ban.jail   [31572]: INFO    Jail 'apache-multiport' started
2019-05-09 23:15:29,360 fail2ban.jail   [31572]: INFO    Jail 'apache-noscript' started
2019-05-09 23:15:29,361 fail2ban.jail   [31572]: INFO    Jail 'pureftpd' started
2019-05-09 23:15:29,363 fail2ban.jail   [31572]: INFO    Jail 'dovecot-pop3imap' started
2019-05-09 23:15:29,364 fail2ban.jail   [31572]: INFO    Jail 'postfix-sasl' started

Ha itt valami hibát jelezne, akkor vissza kell lépni a szűrőfájlhoz és átnézni, hogy nem került-e bele felesleges karakter az új sor beillesztésekor, stb.

 

 

Ellenőrzés

Néhány óra vagy nap eltelte után ellenőrizhetjük munkánk gyümölcsét, attól függően, hogy milyen gyakran fordult elő szerverünkön az ilyen jellegű illetéktelen belépési kísérlet:

fail2ban-client status ssh

És ha ez idő alatt voltak próbálkozások, akkor már láthatjuk is, ahogy a Fail2Ban szépen fog mindent, mint a zöld festék:

Status for the jail: ssh
|- filter
|  |- File list:	/var/log/auth.log 
|  |- Currently failed:	5
|  `- Total failed:	32
`- action
   |- Currently banned:	2
   |  `- IP list:	xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx
   `- Total banned:	9

 

Konklúzió

Ezzel a kis egyszerű szűrőkiegészítéssel megerősíthettük a Fail2Ban program hatékonyságát, amivel jelen esetben jelentősen lelassíthatjuk a belépési kísérletek ütemét. Teljesen megállítani ezzel a módszerrel sem tudjuk, de drasztikusan lecsökkenthetjük az ugyanarról az IP-címről történő próbálkozások számát.