W poprzednim poście dotyczącym bezpieczeństwa MySQL omówiliśmy szereg opcji, które można wykorzystać do zwiększenia bezpieczeństwa instancji MySQL. Obejmowały one:
- Ogólne środki bezpieczeństwa MySQL;
- Kontrolowanie dostępu w MySQL;
- Tworzenie, zmienianie i usuwanie użytkowników w MySQL;
- Przyznawanie i odbieranie uprawnień użytkownikom i użytkownikom w MySQL;
- Sprawdzanie, jakie uprawnienia są przypisane użytkownikom w MySQL.
W tym poście omówimy pozostałe opcje, w tym:
- Kategorie kont w MySQL;
- Role w MySQL;
- Zarezerwowane konta w MySQL;
- Zarządzanie hasłami w MySQL;
- Blokowanie konta w MySQL;
- Wtyczki bezpieczeństwa oferowane przez MySQL;
- Zabezpieczanie kopii zapasowych MySQL.
Pamiętaj, że jeszcze raz nie omówimy absolutnie wszystkiego, co musisz wiedzieć, ale postaramy się zapewnić dobre punkty wyjścia do własnych badań.
Kategorie kont w MySQL
Kategorie kont zostały wprowadzone w MySQL 8 - konkretnie w MySQL 8.0.16. Oto sedno tego:
- Istnieją dwie oddzielne kategorie kont:zwykli użytkownicy i użytkownicy systemu;
- Zwykły użytkownik to użytkownik bez uprawnienia SYSTEM_USER - użytkownik systemu to użytkownik z uprawnieniem SYSTEM_USER;
- Zwykły użytkownik może modyfikować zwykłe konta - taki użytkownik nie może modyfikować kont systemowych;
- Użytkownik systemu może modyfikować zarówno konto systemowe, jak i zwykłe;
- Zwykłe konta mogą być modyfikowane zarówno przez zwykłych użytkowników, jak i użytkowników systemu;
- Konta systemowe mogą być modyfikowane tylko przez użytkowników systemu.
Aby korzystać z kategorii kont w MySQL pod względem bezpieczeństwa, należy pamiętać, że uprawnienie SYSTEM_USER wpływa na takie rzeczy, jak manipulowanie kontami oraz zabijanie sesji i instrukcji w nich zawartych - ta koncepcja w MySQL pozwala ograniczyć pewne modyfikacje do niektórych kont, dzięki czemu MySQL jest bezpieczniejszy. Kategorie kont mogą być również używane do ochrony kont systemowych przed manipulacją przez zwykłe konta:w tym celu nie przyznawaj uprawnień do modyfikacji schematu mysql zwykłym kontom.
Aby przyznać kontu uprawnienia SYSTEM_USER, użyj następującego zapytania na utworzonym koncie:
GRANT SYSTEM_USER ON *.* TO system_user;
Role w MySQL
W MySQL role są zbiorami uprawnień. Kiedy przyznajesz kontu użytkownika rolę w MySQL, przyznajesz wszystkie uprawnienia związane z tą rolą. Role można tworzyć za pomocą instrukcji CREATE ROLE:
CREATE ROLE ‘role_1’, ‘role_2’;
Nazwy ról składają się z części użytkownika i części hosta — część użytkownika nie może być pusta, a część hosta domyślnie ma wartość „%”, jeśli nie jest określona.
Gdy tworzone są role, należy im przypisać uprawnienia. Uprawnienia można przypisać za pomocą instrukcji GRANT:
- UDZIEL WSZYSTKO NA demo_database.* DO ‘demo_user’; przyznałby wszystkie uprawnienia użytkownikowi o nazwie demo_user w bazie danych o nazwie demo_database;
- GRANCJA WSTAW, WYBIERZ, AKTUALIZUJ, USUŃ W bazie danych.* TO ‘użytkownik_demo’; przyzna uprawnienia INSERT, SELECT, UPDATE i DELETE użytkownikowi o nazwie demo_user w bazie danych o nazwie demo_database;
- PRZYZNAJ WYBÓR NA demo_database.* TO ‘demo_user’; przyzna uprawnienia SELECT użytkownikowi o nazwie demo_user w bazie danych o nazwie demo_database.
Aby przypisać rolę poszczególnym użytkownikom, użyj następującej składni:
GRANT ‘role_name’ TO ‘user_name’@’localhost’;
Aby przypisać wiele ról pojedynczemu użytkownikowi, użyj następującej składni:
GRANT ‘role_1’, ‘role_2’ TO ‘user_name’@’localhost’;
Aby przypisać role wielu użytkownikom jednocześnie, użyj następującej składni:
GRANT ‘role_name’ TO ‘user1’@’localhost’, ‘user2’@’localhost’;
Role mogą być pomocne w zapobieganiu incydentom związanym z bezpieczeństwem, ponieważ jeśli atakujący zna hasło niezbyt uprzywilejowanego użytkownika, błędnie zakładając, że użytkownik jest bardzo „potężny” pod względem ról, Twoja aplikacja (i baza danych) mogą być bardzo dobrze uratowanym.
Konta zastrzeżone w MySQL
W przypadku kont zarezerwowanych należy pamiętać, że MySQL tworzy konta podczas inicjalizacji katalogu danych. Istnieje kilka kont, które powinny być uważane za zastrzeżone w MySQL:
- 'root'@'localhost' - to konto jest kontem superużytkownika i ma podobne do boskich przywileje we wszystkich bazach danych MySQL (może wykonywać dowolną operację na dowolnej bazie danych MySQL). Warto zauważyć, że nazwę użytkownika root można również zmienić, aby uniknąć ujawnienia wysoce uprzywilejowanego konta. Aby zmienić nazwę konta, uruchom następujące zapytanie:
RENAME USER ‘root’@’localhost’ TO ‘username’@’localhost’;
- Upewnij się, że przyznałeś PRZYWILEJE FLUSH; oświadczenie po zmianie nazwy konta, aby zmiany zaczęły obowiązywać.
- 'mysql.sys'@'localhost' - to konto jest użytkownikiem systemu, który jest używany jako definiujący widok, procedury i funkcje w schemacie sys. Dodany w MySQL 5.7.9, aby uniknąć problemów, które mogą pojawić się w przypadku zmiany nazwy konta root.
- ‘mysql.session’@’localhost’ – to konto jest używane wewnętrznie przez wtyczki w celu uzyskania dostępu do serwera.
W tym przypadku nie można zrobić zbyt wiele z punktu widzenia bezpieczeństwa, ale należy pamiętać, że konto root ma boskie uprawnienia, co oznacza, że może wykonywać dowolną operację na dowolnej bazie danych MySQL i zachować ostrożność przy podejmowaniu decyzji, komu przyznać uprawnienia dostępu do konta. Pamiętaj też, do czego używane są inne konta MySQL.
Zarządzanie hasłami w MySQL
MySQL obsługuje również funkcje zarządzania hasłami. Niektóre z nich to:
- Możliwość okresowego wygasania haseł;
- Możliwość uniknięcia ponownego użycia hasła;
- Możliwość generowania haseł;
- Możliwość sprawdzenia, czy używane hasło jest silne;
- Możliwość tymczasowego zablokowania użytkowników po zbyt wielu nieudanych próbach logowania.
Teraz przyjrzymy się tym opcjom dokładniej.
Aby ręcznie wygasnąć hasło, użyj instrukcji ALTER USER w następujący sposób:
ALTER USER ‘user’@’localhost’ PASSWORD EXPIRE;
Aby ustawić politykę globalną, zmodyfikuj plik my.cnf tak, aby zawierał parametr default_password_lifetime. Parametr można zdefiniować poniżej sekcji [mysqld] (poniższy przykład ustawia czas życia hasła na 3 miesiące (90 dni)):
default_password_lifetime=90
Jeśli chcesz, aby hasła nigdy nie wygasały, ustaw parametr default_password_litetime na 0.
Możesz także ustawić wygaśnięcie hasła dla określonych użytkowników. Jeśli chcesz ustawić okres ważności hasła dla użytkownika o nazwie demo_user, możesz użyć następującego przykładu:
ALTER USER ‘demo_user’@’localhost’ PASSWORD EXPIRE INTERVAL 90 DAY;
Aby wyłączyć wygasanie hasła:
ALTER USER ‘demo_user’@’localhost’ PASSWORD EXPIRE NEVER;
Aby zresetować globalną politykę wygasania haseł:
ALTER USER ‘demo_user’@’localhost’ PASSWORD EXPIRE DEFAULT;
Ograniczenia ponownego użycia haseł nie pozwalają na ponowne użycie haseł - aby skorzystać z tej funkcji, użyj zmiennych password_history i password_reuse_interval. Możesz umieścić te zmienne w my.cnf, patrząc na poniższy przykład, lub ustawić je w czasie wykonywania, dodając SET PERSIST przed poniższymi instrukcjami.
Aby uniemożliwić ponowne użycie któregokolwiek z 5 poprzednio używanych haseł nowszych niż 365 dni, użyj:
password_history=5
password_reuse_interval=365
Aby wymagać co najmniej 5 zmian hasła przed zezwoleniem na ponowne użycie:
ALTER USER ‘demo_user’@’localhost’ PASSWORD HISTORY 5;
To samo można zrobić podczas tworzenia użytkownika - zamień ALTER USER na CREATE USER.
Aby wygenerować losowe hasło podczas tworzenia użytkownika, uruchom:
CREATE USER [email protected] IDENTIFIED BY RANDOM PASSWORD;
Aby zmienić hasło użytkownika na losowo wygenerowane:
SET PASSWORD FOR [email protected] TO RANDOM;
Twoje losowe hasło zostanie wyświetlone poniżej.
Pamiętaj, że domyślne losowe hasła mają długość 20 znaków. Długość można kontrolować za pomocą zmiennej generowane_random_password_length, która ma zakres od 5 do 255.
W celu sprawdzenia, czy użyte hasło jest silne, można użyć zmiennej VALIDATE_PASSWORD_STRENGTH - funkcja wyświetla liczbę od 0 do 100, gdzie 0 oznacza najsłabsze, a 100 najsilniejsze:
SELECT VALIDATE_PASSWORD_STRENGTH('hasło');
Blokowanie konta w MySQL
MySQL 8.0.19 wprowadził również możliwość tymczasowego blokowania kont użytkowników. Można to osiągnąć za pomocą zmiennych FAILED_LOGIN_ATTEMPTS i PASSWORD_LOCK_TIME.
Aby włączyć blokowanie konta podczas tworzenia użytkownika, uruchom:
CREATE USER ‘demo_user’@’localhost’ IDENTIFIED BY ‘password’ FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 5;
Wartość po FAILED_LOGIN_ATTEMPTS określa, po ilu nieudanych próbach konto zostanie zablokowane, wartość po PASSWORD_LOCK_TIME określa czas blokady konta w dniach. Możliwe jest również określenie wartości, która nie kończy się, dopóki konto nie zostanie odblokowane, określając PASSWORD_LOCK_TIME jako UNBOUNDED.
Wtyczki bezpieczeństwa oferowane przez MySQL
MySQL oferuje również kilka wtyczek, które mogą jeszcze bardziej zwiększyć możliwości bezpieczeństwa. MySQL oferuje:
- Wtyczki do uwierzytelniania;
- Wtyczki do kontroli połączeń;
- Wtyczki do sprawdzania poprawności hasła;
- Wtyczki audytu;
- Wtyczki zapory;
Te wtyczki mogą być używane do wielu rzeczy pod względem bezpieczeństwa:
Wtyczki uwierzytelniające
Wtyczki uwierzytelniania umożliwiają użytkownikom wybór między wieloma podłączanymi metodami uwierzytelniania dostępnymi w MySQL. Można ich używać razem z instrukcjami CREATE USER lub ALTER USER. Oto przykład:
CREATE USER ‘user_1’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’;
To zapytanie implementuje uwierzytelnianie przy użyciu natywnej metody haszowania hasła.
Wtyczki kontroli połączeń
Wtyczki kontroli połączeń mogą wprowadzać coraz większe opóźnienia w odpowiedziach serwera na próby połączenia, jeśli liczba prób połączenia przekroczy określoną liczbę - są w stanie powstrzymać potencjalne ataki typu brute-force. Ta biblioteka wtyczek została wprowadzona do MySQL w wersji 5.7.17 i można ją dodać do MySQL poprzez my.cnf lub ładując wtyczki na serwer w czasie wykonywania.
Aby dodać wtyczki do my.cnf , dodaj następujący wiersz poniżej [mysqld]:
plugin-load-add=connection_control.so
Po zmodyfikowaniu pliku zapisz zmiany i uruchom ponownie MySQL.
Aby załadować wtyczki na serwer w czasie wykonywania, uruchom:
INSTALL PLUGIN CONNECTION_CONTROL SONAME ‘connection_control.so’;
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME ‘connection_control.so’;
W razie potrzeby dostosuj przyrostek .so. Jeśli wszystko wykonałeś poprawnie, tabela CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS powinna zawierać wszystkie nieudane próby połączenia.
Wtyczki do sprawdzania hasła
Wtyczki do sprawdzania poprawności haseł mogą umożliwiać użytkownikom używanie silniejszych haseł, jeśli są używane prawidłowo. Wtyczkę do sprawdzania poprawności hasła można zainstalować za pośrednictwem my.cnf lub ładując wtyczkę na serwer w czasie wykonywania. Aby zainstalować wtyczkę przez my.cnf, dodaj następujący wiersz poniżej [mysqld], a następnie zrestartuj serwer:
plugin-load-add=validate_password.so
Aby załadować wtyczkę w czasie wykonywania, uruchom następującą instrukcję:
INSTALL PLUGIN validate_password SONAME ‘validate_password.so’;
Aby załadować wtyczkę w czasie wykonywania i zapobiec jej usunięciu, dodaj validate-password=FORCE_PLUS_PERMANENT do my.cnf.
Aby uniemożliwić uruchomienie serwera, jeśli wtyczka nie została zainicjowana, użyj opcji --validate-password z wartością FORCE lub FORCE_PLUS_PERMANENT.
Zasadę siły hasła można również zmienić:w tym celu zmień wartość validate_password_policy na LOW, MEDIUM lub STRONG. Wartość LOW sprawdza tylko długość hasła, MEDIUM zasada dodaje pewne warunki, a STRONG zasada dodaje warunek, że podciągi hasła składające się z 4 lub więcej znaków nie mogą pasować do słów w pliku słownika, który można określić, modyfikując zmienną validate_password_dictionary_file.
Wtyczki do pęku kluczy
Wtyczki pęku kluczy mogą umożliwiać komponentom i wtyczkom serwera bezpieczne przechowywanie poufnych informacji w celu ich pobrania. Aby załadować wtyczkę do MySQL, dodaj następujący kod poniżej [mysqld]:
early-plugin-load=keyring_file.so
Aby określić plik magazynu kluczy, dodaj następujące elementy (zmienna keyring_vault_config powinna wskazywać na plik konfiguracyjny):
loose-keyring_vault_config=”/var/lib/mysql_keyring/keyring_vault.conf”
Plik kluczy powinien zawierać zmienną vault_url, która definiuje adres serwera skarbca, zmienną secret_mount_point, która definiuje nazwę punktu podłączenia, w którym skarbiec kluczy przechowuje klucze, oraz token, który powinien być zdefiniowane przez serwer repozytorium. Opcjonalnie można również zdefiniować zmienną vault_ca (powinna wskazywać na certyfikat CA używany do podpisywania certyfikatów skarbca).
Uruchom ponownie serwer, aby zmiany zaczęły obowiązywać;
Wtyczki audytu
Wtyczki audytu umożliwiają monitorowanie, rejestrowanie i blokowanie aktywności wykonywanej na serwerach MySQL. Aby zainstalować MySQL Enterprise Audit, uruchom skrypt znajdujący się w katalogu współdzielonym Twojej instancji MySQL (unikaj umieszczania hasła do instancji MySQL w terminalu - użyj my.cnf):
mysql < /path/to/audit_log_filter_linux_install.sql
Możesz również uniemożliwić usunięcie wtyczki w czasie wykonywania — dodaj następujące informacje w sekcji [mysqld]:
audit_log=FORCE_PLUS_PERMANENT
Uruchom ponownie serwer, aby zastosować zmiany. Zwróć uwagę, że rejestrowanie oparte na regułach domyślnie nie rejestruje żadnych zdarzeń podlegających kontroli, więc aby rejestrować wszystko, utwórz filtr:
SELECT audit_log_filter_set_filter(‘log_filter’, ‘{ “filter”: { “log”: true } }’);
Następnie przypisz go do konta:
SELECT audit_log_filter_set_user(‘%’, ‘log_filter’);
Pamiętaj, że wtyczki audytu są dostępne tylko w MySQL Enterprise Edition;
Wtyczki zapory
Wtyczki zapory mogą umożliwiać użytkownikom zezwalanie lub odmawianie wykonania określonych instrukcji SQL na podstawie określonych wzorców. MySQL Enterprise Firewall został wprowadzony w MySQL 5.6.24 - jest w stanie chronić dane poprzez monitorowanie, alarmowanie i blokowanie nieautoryzowanej aktywności:jest w stanie blokować ataki typu SQL injection, monitorować zagrożenia i blokować podejrzany ruch, a także wykrywać włamania do baza danych. Zapora może również rejestrować zablokowane oświadczenia — można je przeglądać i obserwować w czasie rzeczywistym liczbę zatwierdzonych i odrzuconych oświadczeń.
Aby zainstalować zaporę MySQL Enterprise Firewall, po prostu włącz ją podczas instalacji MySQL Server w systemie Windows. Można ją również zainstalować, wyłączyć lub odinstalować za pomocą MySQL Workbench 6.3.4. Zaporę można również zainstalować ręcznie, uruchamiając skrypt w katalogu współdzielonym instalacji MySQL. Aby włączyć zaporę, dodaj następujący wiersz poniżej [mysqld] i zrestartuj serwer:
mysql_firewall_mode=ON
Zaporę można również włączyć w czasie wykonywania:
SET GLOBAL mysql_firewall_mode = ON;
Alternatywnie, aby zachować zaporę (co oznacza, że zapora nie będzie musiała być ponownie włączana przy każdym kolejnym ponownym uruchomieniu serwera):
SET PERSIST mysql_firewall_mode = ON;
Następnie przyznaj uprawnienie FIREWALL_ADMIN każdemu kontu, które administruje zaporą, a uprawnienie FIREWALL_USER każdemu kontu, które powinno mieć dostęp tylko do własnych reguł zapory. Przyznaj też uprawnienie EXECUTE do procedur przechowywanych zapory w bazie danych mysql. Aby zapora działała, zarejestruj za jej pomocą profile, a następnie przeszkol zaporę, aby znała dozwolone instrukcje, które może wykonać baza danych, a następnie poinformuj zaporę, aby dopasowywała przychodzące instrukcje do ustawionej białej listy. Każdy profil posiada tryb pracy - WYŁĄCZONY, NAGRYWANIE, OCHRONA lub WYKRYWANIE. OFF wyłącza profil, RECORDING trenuje zaporę, PROTECTING zezwala lub odmawia wykonania instrukcji, a DETECTING wykrywa (ale nie blokuje) próby włamań. Reguły dla określonego profilu można zresetować, ustawiając jego wartość na RESET. OFF wyłączy profil. Aby ustawić tryb, użyj następującego zapytania, gdzie name to nazwa profilu, a OFF to tryb operacyjny:
CALL mysql.sp_set_firewall_mode(name, ‘OFF’);
Wtyczka zapory jest również dostępna tylko w MySQL Enterprise Edition.
Zabezpieczanie kopii zapasowych MySQL
Jeśli chodzi o kopie zapasowe MySQL, masz kilka opcji.
- Jeśli używasz mysqldump, możesz przechowywać swoją nazwę użytkownika i hasło w my.cnf i wywołać mysqldump w ten sposób (następujące polecenie zrzuci wszystkie bazy danych do pliku /home/backup.sql):
$ mysqldump --defaults-extra-file=/var/lib/my.cnf --single-transaction --all-databases > /home/backup.sql
- Przechowując swoją nazwę użytkownika i hasło w my.cnf, nie wpisujesz hasła wewnątrz terminala - taka metoda wykonywania kopii zapasowych jest bezpieczniejsza, ponieważ podczas działania zrzutu polecenie można zobaczyć za pomocą ps ax polecenie.
-
Możesz również rozważyć użycie mysqldump-secure, który jest skryptem opakowującym zgodnym z POSIX, który jest w stanie kompresować i szyfrować kopie zapasowe z myślą o silnym bezpieczeństwie .
-
Kopie zapasowe można zaszyfrować za pomocą OpenSSL - po prostu weź kopię zapasową, a następnie zaszyfruj ją za pomocą następującego polecenia:
$ openssl enc -aes-256-cbc -salt -in backup.tar.gz -out backup.tar.gz.enc -k password
Powyższa komenda utworzy nowy zaszyfrowany plik backup.tar.gz.enc w bieżącym katalogu. Plik zostanie zaszyfrowany wybranym hasłem (zastąp hasło wybranym hasłem). Plik można później odszyfrować, uruchamiając następujące polecenie:
$ openssl aes-256-cbc -d -in backup.tar.gz.enc -out backup.tar.gz -k password
Zastąp hasło hasłem.
-
mysqldump ma inną opcję szyfrowania kopii zapasowych (poniższy przykład również kompresuje je za pomocą gzip):
$ mysqldump --all-databases --single-transaction --triggers --routines | gzip | openssl enc -aes-256-cbc -k password > backup.xb.enc
Zastąp hasło wybranym hasłem.
-
Możesz także zaszyfrować swoje kopie zapasowe za pomocą mariabackup lub xtrabackup. Oto przykład z dokumentacji MariaDB:
$ mariabackup --user=root --backup --stream=xbstream | openssl enc -aes-256-cbc -k password > backup.xb.enc
Zastąp hasło wybranym hasłem.
-
Kopie zapasowe można również szyfrować za pomocą ClusterControl — jeśli opcja szyfrowania jest włączona dla określonej kopii zapasowej, ClusterControl zaszyfruje kopię zapasową za pomocą AES-256 CBC (szyfrowanie odbywa się w węźle zapasowym). Jeśli kopia zapasowa jest przechowywana w węźle kontrolera, pliki kopii zapasowej są przesyłane strumieniowo w formacie zaszyfrowanym przy użyciu socat lub netcat. Jeśli kompresja jest włączona, ClusterControl najpierw skompresuje kopię zapasową, a następnie zaszyfruje ją. Klucz szyfrowania zostanie wygenerowany automatycznie, jeśli nie istnieje, a następnie będzie przechowywany w konfiguracji CMON w opcji backup_encryption_key. Pamiętaj, że ten klucz jest zaszyfrowany i powinien zostać zdekodowany jako pierwszy. Aby to zrobić, uruchom następujące polecenie:
$ cat /etc/cmon.d/cmon_ClusterID.cnf | grep ^backup_encryption_key | cut -d"'" -f2 | base64 -d > keyfile.key
Polecenie odczyta backup_encryption_key i zdekoduje jego wartość na wyjście binarne. Pliku klucza można użyć do odszyfrowania kopii zapasowej w następujący sposób:
$ cat backup.aes256 | openssl enc -d -aes-256-cbc -pass file:/path/to/keyfile.key > backup_file.xbstream.gz
Więcej przykładów znajdziesz w dokumentacji ClusterControl.
Wnioski
W tych postach dotyczących bezpieczeństwa MySQL omówiliśmy pewne środki bezpieczeństwa, które mogą być przydatne, jeśli czujesz potrzebę zwiększenia bezpieczeństwa swoich instancji MySQL. Chociaż nie omówiliśmy absolutnie wszystkiego, uważamy, że te punkty mogą być dobrym punktem wyjścia do zwiększenia bezpieczeństwa instalacji MySQL. Weź z tych postów, co chcesz, przeprowadź własne badania i zastosuj środki bezpieczeństwa najbardziej odpowiednie w Twojej sytuacji.