Przykłady ataków SQL Injection
Atak SQL Injection wykorzystuje fakt że dane wpisane do formularza na stronie WWW (lub w inny sposób wysłane do serwera) nie są w żaden sposób walidowane pod kątem ich poprawności. Do tego dochodzi fakt że w zapytaniach SQL stringi należy zamknąć pomiędzy znakami apostrofu. Zatem jeżeli ktoś wpisze do formularza ciąg znaków zawierający m.in. apostrof, różne rzeczy mogą się przytrafić - od zwykłego błędu wykonania zapytania SQL, aż po wykasowanie wszystkich danych z bazy danych czy dysku serwera, albo włamania do innych maszyn w sieci!
Najprostszy atak SQL Injection może wyglądać następująco: załóżmy że na stronie znajduje się następujący formularz:
<form method="post" action="login.php">
Login: <input type="text" name="login"><br>
Hasło: <input type="password" name="pass"><br>
<input type="submit" value="Zaloguj się"><br>
</form>
Po stronie serwera, w kodzie PHP tworzone i wykonywane jest następujące zapytanie:
SELECT USER_ID FROM USERS WHERE (LOGIN='$login') AND (PASS='$pass')
Zmienne $login
i $pass
zawierają odpowiednio login i hasło wpisane w formularzu. Załóżmy że do systemu loguje się admin, posługując się swym bezpiecznym hasłem "jh*8!aaC4". Zapytanie które zostanie wykonane wygląda następująco:
SELECT USER_ID FROM USERS WHERE (LOGIN='admin') AND (PASS='jh*8!aaC4')
Jak na razie wszystko wygląda w porządku. Załóżmy jednak że nasz Czarny Kapelusz (Black Hat) próbuje się włamać, i wpisał jako hasło:
' OR '1'='1
Wynikowe zapytanie które zostanie wykonane będzie następujące:
SELECT USER_ID FROM USERS WHERE (LOGIN='admin') AND (PASS='' OR '1'='1')
Jak widać, w zapytaniu zmienił się warunek który sprawdza hasło - obecnie składa się on z sumy logicznej dwóch warunków: pierwszego który jest fałszywy (no chyba że admin nie ma założonego hasła, co jest mało prawdopodobne), i drugiego który jest zawsze prawdziwy. Wynik: napastnik zalogował się na konto admina bez znajomości (!) jego hasła.
Powyższy przykład ataku można zmodyfikować, wpisując następujący ciąg znaków jako nazwę użytkownika, i dowolne hasło (np. "a"):
admin') --
Wynikowe zapytanie które zostanie wykonane będzie następujące:
SELECT USER_ID FROM USERS WHERE (LOGIN='admin') --') AND (PASS='a')
W języku SQL dwa myślniki umieszczone obok siebie oznaczają początek komentarza, zatem w rezultacie wykona się tylko pierwsza część warunku WHERE
(sprawdzenie nazwy użytkownika).
Napastnikowi może także nie zależeć na uzyskaniu nieautoryzowanego dostępu do serwera, ale na wyrządzeniu jak największych szkód. Może on tu skorzystać z faktu, że baza danych może wykonać kilka zapytań podanych po kolei (i ew. rozdzielonych średnikiem). Przykładowo może on wpisać coś takiego jako nazwę użytkownika:
') DELETE FROM USERS --
Wynik jest mało przyjemny - skasowana zostanie zawartość tabeli USERS. Napastnik może posunąć się jeszcze dalej, wpisując coś takiego:
') DROP DATABASE SKLEP --
Po wykonaniu tej komendy cała nasza baza danych przestaje istnieć! Jeżeli baza danych pozwala na wykonywanie poleceń systemowych, napastnik może także wykasować zawartość twardego dysku. Np. źle skonfigurowana baza danych MS SQL Server na Windows może pozwolić na wykonanie takiego ataku:
'); exec master..xp_cmdshell 'iisreset /stop' --
Wpisane powyższego ciągu znaków jako nazwy użytkownika spowoduje zatrzymanie serwera IIS (Internet Infomation Server, czyli serwer WWW Microsoftu). Jakie to może mieć skutki np. dla sklepu internetowego chyba nie muszę tłumaczyć. Poza tym w systemie istnieje cały szereg innych komend które napastnik może wykorzystać do złych celów.
Celem napastnika może nie być sianie zniszczenia, ale chęć kradzieży poufnych danych. Załóżmy że sklep internetowy pozwala na wyświetlenie listy produktów które zamówiło się w ostatnim czasie, za pomocą zapytania:
SELECT PRODUKT_ID, NAZWA, OPIS, KWOTA
FROM PRODUKTY, ZAMOWIENIA
WHERE (PRODUKTY.PRODUKT_ID=ZAMOWIENIA.PRODUKT.ID)
AND (KLIENT_ID=$id)
ORDER BY NAZWA
W tym przykładzie identyfikator klienta jest przekazywany z zewnątrz. W normalnej sytuacji jest to liczba; jeżeli jednak napastnik wpisze coś takiego:
0 OR 1=1
wtedy ostatnia linia warunku WHERE
przybierze następującą postać:
AND (KLIENT_ID=0 OR 1=1)
Wynik: cała historia zamówień dokonanych przez wszystkich klientów sklepu wyświetli się na stronie.
Napastnik może także dostać się do innych tabel, korzystając z instrukcji UNION
. W tym celu może wpisać np. coś takiego jako id:
-1) UNION SELECT KLIENT_ID, LOGIN, HASLO, 0 FROM KLIENCI --
Ostatnia linia warunku będzie wyglądać następująco:
AND (KLIENT_ID=-1) UNION SELECT KLIENT_ID, LOGIN, HASLO, 0 FROM KLIENCI --)
Zero w drugim zapytaniu SELECT
po UNION
jest konieczne aby liczba kolumn i ich typy się zgadzały. Całe zapytanie po wykonaniu zwróci napastnikowi listę loginów i haseł wszystkich klientów sklepu (być może także personelu, a przy odrobinie szczęścia nawet i hasło admina). Stąd już prosta droga do kradzieży np. danych osobowych.
Na tym możliwości ataków się nie kończą - korzystając z SQL Injection oraz faktu że strona ASP nie sprawdza potencjalnych błędów bazy danych można szukać innych tabel w bazie danych, oraz próbować określić typy ich kolumn - więcej na ten temat jest w materiałach do których linki są podane na końcu.
Listing