Zadanie 3 - Zabezpieczanie serwera baz danych (Hardening)

Cel zadania

Celem tego zadania jest nauka i zrozumienie fundamentalnych oraz zaawansowanych technik "utwardzania" (ang. hardening) serwera MariaDB/MySQL. Dowiesz się nie tylko, jak usunąć standardowe luki w bezpieczeństwie (anonimowi użytkownicy, testowe bazy), ale także jak świadomie zarządzać dostępem sieciowym, analizować potencjalne wektory ataku i konfigurować serwer w sposób minimalizujący powierzchnię ataku, zarówno w środowisku deweloperskim, jak i produkcyjnym.

Scenariusz / opis zadania

Jako administrator odpowiedzialny za infrastrukturę bazodanową, wiesz, że świeżo zainstalowany serwer jest jak otwarty dom – pełen domyślnych ustawień, które ułatwiają start, ale stanowią zaproszenie dla potencjalnych intruzów. Twoim zadaniem jest przeprowadzenie kompleksowego audytu bezpieczeństwa i wdrożenie poprawek. Musisz działać metodycznie: najpierw zidentyfikować i wyeliminować oczywiste słabości pozostawione przez instalator, takie jak konta bez haseł czy publicznie dostępne bazy testowe. Następnie, musisz ograniczyć powierzchnię ataku, upewniając się, że administrator (root) nie może logować się zdalnie. Wreszcie, zejdziesz na niższy poziom, modyfikując plik konfiguracyjny my.ini/my.cnf, aby serwer nasłuchiwał tylko na lokalnym interfejsie sieciowym, stając się niewidocznym dla sieci zewnętrznej. Przeanalizujesz także działanie skryptu mysql_secure_installation, aby zrozumieć, jakie polecenia SQL wykonuje on w tle.

Pomocnik wykonania: Audyt i utwardzanie krok po kroku

Krok 1: Identyfikacja i eliminacja niebezpiecznych kont

Zaloguj się do serwera jako root (mysql -u root -p). Pierwszym celem są anonimowi użytkownicy – konta z pustą nazwą użytkownika.


-- Wyszukaj konta z pustą nazwą użytkownika
SELECT User, Host FROM mysql.user WHERE User = '';
  
Dlaczego anonimowi użytkownicy są niebezpieczni?

Pozwalają każdemu, kto ma dostęp do serwera, na połączenie się bez podawania nazwy użytkownika. Chociaż ich uprawnienia są zazwyczaj ograniczone do bazy test, stanowią one niepotrzebny punkt wejścia i mogą być wykorzystane do ataków typu "information gathering" (zbierania informacji o wersji serwera, zmiennych systemowych itp.).

Jeśli zapytanie zwróciło jakiekolwiek wyniki, usuń je. Użyj składni IF EXISTS, aby uniknąć błędu, jeśli konto nie istnieje.


DROP USER IF EXISTS ''@'localhost';
-- Powtórz dla każdego hosta, np. ''@'nazwa_hosta' jeśli taki istnieje
  

Krok 2: Usunięcie testowej bazy danych

Domyślna baza test jest publicznie dostępna dla każdego, kto może się połączyć z serwerem. Jest to relikt z przeszłości, który nie ma zastosowania produkcyjnego.

Jakie jest ryzyko?

Nawet pusta, zapisywalna dla wszystkich baza danych może zostać wykorzystana przez atakującego do przechowywania tymczasowych danych, testowania exploitów SQL injection lub po prostu do zaśmiecania serwera.


-- Sprawdź, czy baza 'test' lub bazy o nazwach 'test_%' istnieją
SHOW DATABASES LIKE 'test%';

-- Jeśli istnieje, usuń ją
DROP DATABASE IF EXISTS test;
  

Krok 3: Ograniczenie dostępu dla konta root

Konto root nigdy nie powinno być dostępne zdalnie. Powinno móc logować się tylko z tej samej maszyny, na której działa serwer.


-- Sprawdź, z jakich hostów może logować się root
SELECT User, Host FROM mysql.user WHERE User = 'root';
  

Idealny wynik to localhost, 127.0.0.1 i ::1 (dla IPv6). Jeśli widzisz % (dowolny host) lub jakikolwiek inny adres IP/nazwę hosta, jest to poważna luka bezpieczeństwa.


-- Usuń zdalny dostęp dla roota, jeśli istnieje
DELETE FROM mysql.user WHERE User = 'root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
  

Krok 4: Skrypt mysql_secure_installation (Linux/macOS)

Na systemach Linux i macOS ten skrypt jest preferowaną metodą, ponieważ automatyzuje powyższe kroki w interaktywny sposób. W środowisku XAMPP na Windows ten skrypt nie jest dostępny, dlatego wszystkie kroki wykonujemy ręcznie.

Co dokładnie robi ten skrypt?

Po uruchomieniu sudo mysql_secure_installation, skrypt wykonuje następujące operacje (w zależności od odpowiedzi użytkownika):

Krok 5: Konfiguracja sieciowa w my.ini

Najskuteczniejszym sposobem na zablokowanie dostępu z sieci jest skonfigurowanie serwera tak, aby nasłuchiwał tylko na lokalnym adresie IP.

Otwórz plik C:\xampp\mysql\bin\my.ini i w sekcji [mysqld] dodaj lub odkomentuj linię:

[mysqld]
# ... inne opcje ...
bind-address = 127.0.0.1
# ... inne opcje ...
  
Znaczenie bind-address

Ta dyrektywa mówi serwerowi, do którego interfejsu sieciowego ma się "przywiązać". Ustawienie 127.0.0.1 (localhost) oznacza, że serwer będzie akceptować połączenia TCP/IP tylko z tej samej maszyny. Próby połączenia z innego komputera w sieci zostaną odrzucone na poziomie sieciowym, zanim jeszcze dojdzie do etapu uwierzytelniania. Jeśli ta linia jest zakomentowana lub ustawiona na 0.0.0.0, serwer nasłuchuje na wszystkich dostępnych interfejsach sieciowych.

Pamiętaj! Po każdej zmianie w pliku konfiguracyjnym musisz zrestartować usługę MariaDB/MySQL, aby zmiany zostały załadowane.

Krok 6: Zastosowanie zmian i weryfikacja

Po wykonaniu wszystkich operacji SQL, zakończ sesję poleceniem:


FLUSH PRIVILEGES;
  

To polecenie nakazuje serwerowi ponowne wczytanie tabel uprawnień z bazy mysql. Jest to absolutnie kluczowe po ręcznych zmianach w tych tabelach.

Jak sprawdzić, czy serwer jest widoczny w sieci?

Przed zmianą bind-address, z innego komputera w tej samej sieci, możesz użyć polecenia telnet [IP_SERWERA] 3306. Jeśli otrzymasz odpowiedź, oznacza to, że port jest otwarty. Po dodaniu bind-address = 127.0.0.1 i restarcie serwera, to samo polecenie powinno zakończyć się błędem połączenia.

Warstwy zabezpieczeń serwera

Model "cebuli"

+----------------------------------------------------------------------+
| Warstwa 4: Firewall Systemowy / Sieciowy                             |
|  (Blokuje dostęp do portu 3306 z niezaufanych sieci)                 |
| +------------------------------------------------------------------+ |
| | Warstwa 3: Konfiguracja Serwera (`my.ini`)                       | |
| |  `bind-address = 127.0.0.1` (Blokuje ruch z zewnątrz)            | |
| | +--------------------------------------------------------------+ | |
| | | Warstwa 2: Konta Użytkowników (`mysql.user`)                 | | |
| | |  - Brak anonimowych kont                                     | | |
| | |  - `root` tylko z `localhost`                                | | |
| | | +----------------------------------------------------------+ | | |
| | | | Warstwa 1: Hasła i Uprawnienia (GRANT/REVOKE)            | | | |
| | | |  - Silne, unikalne hasła dla wszystkich kont             | | | |
| | | |  - Zasada minimalnych uprawnień dla każdego użytkownika  | | | |
| | | +----------------------------------------------------------+ | | |
| | +--------------------------------------------------------------+ | |
| +------------------------------------------------------------------+ |
+----------------------------------------------------------------------+