Hogyan védekezzünk az "Access denied for user root@ip-cím (using password: YES/NO)" típusú adatbázis kiszolgálónkat érő támadásokkal szemben a Fail2Ban segítségével

botond küldte be 2022. 06. 05., v – 01:45 időpontban

Tartalom

 

Bevezető

Ha weboldalakat üzemeltetünk, akkor szerverünk, és a rajta működő weboldalak és szolgáltatások gyakran ki vannak téve a külső támadásoknak, ami alól MySQL/MariaDB adatbázis kiszolgálónk sem kivétel. Ha szerverünkön a Fail2Ban védelmi szoftver is rendelkezésre áll - például egy ISPConfig-os szerverkörnyezet részeként -, akkor ebből a rövid leírásból megtudhatjuk, hogyan tehetjük biztonságosabbá szerverünket az "Access denied for user root@ip-cím (using password: YES/NO)" típusú adatbázis kiszolgálónkat érő támadásokkal szemben.

 

 

A probléma észlelése

A szerver üzemeltetésének részeként az ember rendszeresen ellenőrzi, elemzi a különböző naplófájlokat, amikből hasznos információkat szerezhet a szerver állapotával kapcsolatban. Mivel ebben a leírásban az adatbázis kiszolgáló biztonságosabbá tételéről ejtünk szót, ezért megnézzük a MySQL hibanaplóját root-ként:

sudo cat /var/log/mysql/error.log | grep "Access denied"

A példa kedvéért itt rászűrtem a leírás tárgyát képező hibatípusra.

MySQL/MariaDB hibanapló megtekintése

Ahogy látható, a hibanapló tartalmaz néhány belépési kísérletet root-ként az adatbázis kiszolgálóba. Itt kétféle hibatétel szerepel:

2022-06-04  3:25:14 1551015 [Warning] Access denied for user 'root'@'xxx.xxx.xxx.xxx' (using password: NO)
2022-06-04  3:25:14 1551016 [Warning] Access denied for user 'root'@'xxx.xxx.xxx.xxx' (using password: YES)

Az egyik, amikor jelszó használata nélkül, a másik pedig amikor jelszóval próbálkoznak. Az ip-cím pedig a támadó ip-címe. Összesen 11 darab szerepel a mai napi hibanaplóban.

A következő fejezetben erre találunk megoldást a Fail2Ban védelmi szoftver segítségével.

 

A Fail2Ban beállítása

A Fail2Ban program kiválóan alkalmas az ilyen típusú támadások elhárítására. A szoftver alapból rengeteg szűrőt tartalmaz, csak be kell állítani a szükséges példányokat és engedélyezni kell őket.

A mysqld-auth szűrő áttekintése

Kimondottan erre a problémára készítették megoldásként a mysqld-auth nevű szűrőt. Tekintsünk bele:

sudo nano /etc/fail2ban/filter.d/mysqld-auth.conf

A fájl tartalma pedig az alábbi:

# Fail2Ban filter for unsuccesful MySQL authentication attempts
#
#
# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld]:
# log-error=/var/log/mysqld.log
# log-warning = 2
#
# If using mysql syslog [mysql_safe] has syslog in /etc/my.cnf

[INCLUDES]

# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf

[Definition]

_daemon = mysqld

failregex = ^%(__prefix_line)s(?:\d+ |\d{6} \s?\d{1,2}:\d{2}:\d{2} )?\[\w+\] Access denied for user '[^']+'@'<HOST>' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$

ignoreregex =

# DEV Notes:
#
# Technically __prefix_line can equate to an empty string hence it can support
# syslog and non-syslog at once.
# Example:
# 130322 11:26:54 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES)
#
# Authors: Artur Penttinen
#          Yaroslav O. Halchenko

Itt látható is, hogy a fentebb írt hibaüzenet figyelésére készült. Le is futtathatunk egy tesztet a szűrővel a fail2ban-regex parancs használatával:

sudo fail2ban-regex /var/log/mysql/error.log /etc/fail2ban/filter.d/mysqld-auth.conf

A kimenet pedig nálam:

Running tests
=============

Use   failregex filter file : mysqld-auth, basedir: /etc/fail2ban
Use      datepattern : Default Detectors
Use         log file : /var/log/mysql/error.log
Use         encoding : UTF-8


Results
=======

Failregex: 11 total
|-  #) [# of hits] regular expression
|   1) [11] ^(?:\[\])?\s*(?:<[^.]+\.[^.]+>\s+)?(?:\S+\s+)?(?:kernel: \[ *\d+\.\d+\]\s+)?(?:@vserver_\S+\s+)?(?:(?:(?:\[\d+\])?:\s+[\[\(]?mysqld(?:\(\S+\))?[\]\)]?:?|[\[\(]?mysqld(?:\(\S+\))?[\]\)]?:?(?:\[\d+\])?:?)\s+)?(?:\[ID \d+ \S+\]\s+)?(?:\d+ |\d{6} \s?\d{1,2}:\d{2}:\d{2} )?\[\w+\] Access denied for user '[^']+'@'<HOST>' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [26] {^LN-BEG}ExYear(?P<_sep>[-/.])Month(?P=_sep)Day(?:T|  ?)24hour:Minute:Second(?:[.,]Microseconds)?(?:\s*Zone offset)?
`-

Lines: 26 lines, 0 ignored, 11 matched, 15 missed
[processed in 0.00 sec]

|- Missed line(s):
[...]

Az eredményeknél láthatjuk, hogy a fentebbi naplófájlban megjelenő 11 tételt észre is vette, tehát a szűrő működik, már csak be kell kapcsolnunk a jail-t.

 

 

A mysqld-auth jail létrehozása és elindítása

Új jail létrehozásához nyissuk meg a /etc/fail2ban/jail.local fájlt szerkesztésre:

sudo nano /etc/fail2ban/jail.local

és ha még nem szerepel benne ez a jail, adjuk a fájl végéhez az alábbi részt:

[mysqld-auth]
enabled   = true
port      = 3306
filter    = mysqld-auth
logpath   = /var/log/mysql/error.log
findtime  = 3600
maxretry  = 2
bantime   = 86400

ahol a sorok jelentése a következő:

  • [mysqld-auth]: Jail neve. Ez lényegében bármi lehet - a szögletes zárójeleken belül természetesen -, de célszerű a szűrő nevét használni, hogy később ne keveredjünk bele, ha sok jail-unk van.
  • enabled: Jail engedélyezése true érték esetén.
  • port: ezen a porton tiltja a MySQL kapcsolódásokat, amennyiben szükséges. A MySQL alapértelmezett portja a 3306. Amennyiben ettől eltérő egyedi portot használunk az adatbázis csatlakozásokhoz, azt adjuk meg.
  • filter: A fentebb már megtekintett szűrőfájl kiterjesztés nélküli neve, amit a /etc/fail2ban/filter.d/ könyvtárból olvas be.
  • logpath: ezt a naplófájlt elemzi a Fail2Ban
  • findtime: Az a másodpercekben megadott időablak, amin belül figyeli az incidensek előfordulásának számát. Ezt állíthatjuk saját igényeinknek megfelelően, hozzáigazítva saját körülményeinkhez. Például ha gyorsabb lefolyású belépési kísérlet sorozatok (azonos ip-címről történő próbálkozások) fordulnak elő rövidebb idők alatt, akkor adhatunk alacsonyabb értéket, de ha napközben véletlenszerű szétszóródással próbálkoznak ugyanarról az ip-címről, akkor adjunk meg nagyobb időablakot.
  • maxretry: Ez pedig a megengedett próbálkozások számát jelenti. Ha ezt eléri a találatok száma, akkor történik a letiltás. Ezt is saját igényeinknek megfelelően állítsuk be.
  • bantime: A tiltáskor ennyi időre tiltja le a tűzfalban az ip-címet a megadott port vonatkozásában.

Ha megvagyunk a beállításokkal mentsük le a fájlt, majd indítsuk újra a Fail2Ban szolgáltatást:

sudo systemctl restart fail2ban.service

Ellenőrzés

Ha újraindítottuk a Fail2Ban-t, ellenőrizhetjük a jail működését a fail2ban-client paranccsal:

fail2ban-client status mysqld-auth

Itt most még (kicsivel éjfél után) nem fogott semmit, de később már lehetnek ip-címek a tiltólistájában:

Fail2Ban jail ellenőrzése

 

MySQL külső csatlakozás egyértelműsítése

A félreértések elkerülése végett fontos tisztázni, hogy mi számít külső csatlakozásnak. Külső adatbázis csatlakozásnak az minősül, ha egy másik számítógépről direktben csatlakoznak a szerverünkön működő adatbázis kiszolgálóhoz a megadott portszámon, ami alapértelmezetten a 3306. Az adatbázis kiszolgáló lehetőséget biztosít az adatbázisok kívülről történő eléréséhez, például különböző kliens oldali adatbáziskezelők számára, vagy a más helyeken futó egyéb alkalmazásokból történő kapcsolódásához. Az ugyanazon a szerveren működő webes felületről történő csatlakozás nem számít külső csatlakozásnak, így például a phpMyAdmin webes adatbáziskezelővel történő belépés localhost-ként csatlakozik az adatbázis kiszolgálóhoz, de ugyanígy a szerveren működő dinamikus weboldalak is. Ennek megfelelően tehát ez a leírás csak a külső csatlakozással történő illetéktelen belépési kísérletek megakadályozására terjed ki.

A fentiek alapján tehát a phpMyAdmin-ba hibás jelszóval történő belépési kísérletek nem kerülnek tiltásra, mivel azok localhost (szerveren belüli) csatlakozások. Erre példaként az alábbi naplófájl, amit most saját magam generáltam néhány hibás phpMyAdmin belépéssel:

MySQL hibanapló localhost adatokkal

Ezt a példát azért hoztam elő, mert jellemzően ez is egy elég gyakori eset, mivel a phpMyAdmint többen is használhatják egy szerveren, valamint bárki számára elérhető, amennyiben nincs különösebben elrejtve. Amennyiben a phpMyAdmin felületén történő érvénytelen belépési kísérleteket is szeretnénk blokkolni, erről egy másik leírásban tájékozódhatunk.

 

MySQL külső csatlakozások letiltása

Ha nem használunk semmilyen kívülről kapcsolódó alkalmazást, akkor le is tilthatjuk az egészet, így csak a localhost-ról lehet csatlakozni az adatbázisainkhoz.

Ehhez nyissuk meg a MySQL/MariaDB kiszolgálónk fő konfigurációs fájlját:

  • MySQL esetén: /etc/mysql/my.cnf
  • MariaDB esetén: /etc/mysql/mariadb.conf.d/50-server.cnf
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

Majd ebben keressük meg az elején az alábbi részt:

[...]
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address            = 127.0.0.1
[...]

És vegyük ki a komment karaktert (#) a "bind-address" sora elől.

Ezután mentsük le, majd indítsuk újra az adatbázis kiszolgálót:

sudo systemctl restart mysqld

Ezután már nem lehet kívülről csatlakozni az adatbázisainkhoz.

 

 

Konklúzió

Sokat foglalkoztunk már a Fail2Ban biztonsági eszközzel, most ismét gyarapítottuk szűrőinket a védelem érdekében. Ezzel a Fail2Ban jail beállítással egy fokkal még biztonságosabbá tettük szerverünket amellett, hogy továbbra is tudunk kívülről csatlakozni adatbázisainkhoz, aminek köszönhetően például az otthoni gépünkről is végre tudunk hajtani biztonsági mentéseket vagy bármilyen SQL parancsokat. Amennyiben viszont nem kívánunk élni ezzel a lehetőséggel, teljesen le is tilthatjuk a távoli hozzáférést MySQL/MariaDB kiszolgálónkhoz.