Atak SQL Injection to jeden z najpopularniejszych ataków na bazy danych MySQL i jeden z największych problemów twórców profesjonalnych serwisów www opartych na PHP oraz innych językach działających po stronie serwera i odpowiadających za komunikację aplikacja – baza danych. Celem tego ataku jest wstrzyknięcie / modyfikacja / usunięcie lub wydobycie z bazy danych poprzez klienta bazy danych (np. aplikację webową) odpowiednich danych lub struktur. Skrajnymi przypadkami zagrożenia może być niszczenie tabel baz danych, wybieranie z nich szczególnie sensytywnych danych (np. danych osobowych) lub niszczenie całych baz. Możliwe jest nawet wykonywanie niebezpiecznych komend na poziomie hosta bazy danych lub, podczas łączenia się do bazy danych na prawach administratora baz danych, haker może również tworzyć osobnego, własnego użytkownika posiadającego maksymalne uprawnienia.
Oto przykład prostej komendy w mysqli zdefiniowanej w języku PHP:
Przykład 1:
mysqli_query($con,"INSERT INTO Names (Imie, Nazwisko, Wiek) VALUES ('Jan', 'Kowalski',32)"); |
Zmienna $con odpowiada w powyższym przykładzie za połączenie z bazą danych.
Jeżeli powyższe zapytanie zamienimy na przejmujące wartość danej zmiennej (np. przychodzącej POSTem), może wyglądać następująco:
Przykład 2:
mysqli_query($con,"INSERT INTO Names (Imie, Nazwisko, Wiek) VALUES ('$imie', '$nazwisko',$wiek)"); |
Tak wykonane mysqli_query to jedna z najprostszych postaci komendy typu INSERT wykonywanej do bazy danych i przechwytujących wartości zmiennej wysłanych np. z formularza napisanego w technologii HTML w żaden sposób nie zabezpieczonej przed atakiem SQL Injection.
Logika aplikacji powinna zapewniać odpowiednie przetworzenie funkcji z przykładu 2. Najprostszą metodą, aby zapewnić elementarne bezpieczeństwo, jest używanie PHPowej funkcji mysql_real_escape_string(), dodającej znaki unikowe w łańcuchu znaków, które są używane w komendzie SQL. Funkcja ta jest rekomendowana w miejsce starszych i mniej bezpiecznych funkcji: mysql_escape_string() oraz addslashes().
W jaki inny sposób można zabezpieczyć się przed atakiem SQL Injection?
Po pierwsze, należy pamiętać, że aplikacje, czyli klienci, którzy łączą się z bazą danych, zawsze powinni być traktowani jako potencjalne zagrożenie dla ciągłości działania bazy. Ponieważ łączą się oni z bazą danych jako pewien użytkownik, a więc logując się do niej, zgodnie z zasadą ograniczonego zaufania, powinny łączyć się jako użytkownik z odpowiednimi ograniczeniami. Po stronie bazy danych warto więc zdefiniować usera specjalnie na potrzeby klientów. Użytkownik taki powinien mieć np. uprawnienia jedynie do odczytu danych (SELECT).
Ponadto, w przypadku aplikacji PHP należy stosować rozszerzenia mysqli lub pdo_mysql zamiast starszego ext/mysql.
Innymi dobrymi praktykami podczas zabezpieczenia bazy MySQL, podobnie jak PostgreSQL, są:
-
Nadanie kolumnom i procedurom mniej intuicyjnych nazw, szczególnie w przypadku umieszczania w nich kluczowych danych. Hakerzy atakują bazę danych często wybierają popularne nazwy tabel lub kolumn w tych tabelach (np. users lub użytkownicy). Jeżeli nazwy te będą miały charakter schematyczny wówczas SQL Injection może być zdecydowanie trudniejszy do przeprowadzenia.
-
Zasada opisana w powyższym punkcie powinna odnosić się również do nazw użytkowników. Powinniśmy zrezygnować z oczywistych nazw takich jak „admin”, ponieważ je również również zdecydowanie łatwiej podrobić przy SQL Injection oraz przy próbie włamania bezpośrednio przez phpmyadmina (lub pgadmina).
-
Kluczowe dane powinny być kodowane co najmniej przy użyciu mechanizmu md5 (zalecane są jednak mechanizmy z grupy SHA-1). W przypadku kodowania należy jednak pamiętać, że zakodowanie nazwy użytkownika „admin” przy użyciu md5 da nam 32- znakowy string, który dla wprawnego hakera będzie znany (na podstawie np. baz md5). Bezpiecznym połączeniem jest zatem łączenie nazw mało intuicyjnych z odpowiednim ich kodowaniem. Inne rozwiązania czynią bazę danych gorzej zabezpieczoną.
-
Używanie w języku działającego po stronie serwera funkcji zabezpieczających wysyłane dane takich jak mysql_real_escape_string() lub settype ().
Mottem, do którego należy się stosować projektując bazy danych, jest to, że powyższe zabezpieczenia powinny dotyczyć wszystkich rodzajów baz danych, a nie tylko posiadających kluczowe dane. Zagrożenia, które istniejąc dla zupełnie niezabezpieczonych baz, mogą narażać całą usługę na niespodziewane przerwanie ciągłości działania. Pamiętajmy bowiem, że mimo że aplikacja jako taka nie zostanie uszkodzona, jednak może odwoływać się do zaatakowanych (skasowanych lub zmodyfikowanych) danych/struktur, wprowadzając użytkowników w błąd, lub uniemożliwiając poprawne wyświetlenie danych.
Autor Artykułu: Mateusz Jabłoński z http://www.datalab.pl/
Listing