Zastrzyk SQL - SQL Injection

STRESZCZENIE: Na czym polegają ataki tego typu, jakie niosą ze sobą zagrożenia, sposoby zapobiegania. Kilka przykładów niebezpiecznych konstrukcji oraz wykrytych przypadków podatności na SQL Injection.

Czym jest "Zastrzyk SQL"?

Atak typu SQL injection polega na takiej manipulacji aplikacją komunikującą się z bazą danych, aby ta umożliwiła atakującemu uzyskanie dostępu lub modyfikację danych, do których nie posiada on uprawnień.
W praktyce polega to na wykorzystaniu interfejsu użytkownika (adresu URL, formularza HTML/XML, okna dialogowego itp.) do wprowadzenia do aplikacji spreparowanego ciągu znaków, który, dzięki naiwności programisty, bez odpowiedniego uprzedniego przetworzenia, stanie się częścią kodu wykonanywanego w bazie danych. W zależności od architektury aplikacji, może to być gotowe wyrażenie SQL, ale nie tylko. Może to być również sekwencja komend specyficznego dla danej bazy/platformy języka DML - Data Manipulation Language lub odwołanie do procedury składowanej, która samoczynnie utworzy właściwe wyrażenie SQL. Zagrożenie atakami typu SQL injection dotyczy przede wszystkim aplikacji internetowych z racji relatywnie łatwego dostępu do nich, jednak technikę tę można z powodzeniem zastosować do atakowania aplikacji typu klient, serwer.

Czemu jest groźny?

Odpowiedź mogłaby być parafrazą powyższego opisu - pozwala osobom niepowołanym na dostęp do informacji w bazie, a nawet manipulację nimi.

Poza tym ataki typu SQL Injection są niebezpieczne, dlatego że większość programistów zwyczajnie nie zdaje sobie sprawy z ich istnienia. Ci zaś, którzy o nich słyszeli, nie są skłonni sądzić, że tworzone przez nich systemy są na nie podatne. Po drugie, ataki typu SQL injection to ataki wysokiego poziomu. Oznacza to, że zabezpieczenia działające na poziomie sieci IP np. systemy zaporowe (firewall) są wobec nich bezradne - mówiąc wprost - w ogóle ich nie zauważają. Wobec ataków SQL injection bezsilne są nawet systemy wykrywania włamań.

W walce z atakami typu SQL injection bezużyteczne okazują się także, działające w wyższych warstwach, skanery antywirusowe oraz filtry treści wykorzystujące bazy sygnatur. Problem polega tu na tym, że ataki te nie wykorzystują znanych błędów w oprogramowaniu, dla których istnieją sygnatury, np. serwerach WWW czy serwerach baz danych, lecz błędy popełnione przez projektantów i programistów tworzących przy ich pomocy konkretne rozwiązania, np. internetowa aplikacja do obsługi zamówień w konkretnej firmie.

Konstrukcje

Niewinny apostrof

Pierwszym testem podatności aplikacji na SQL Injection jest wprowadzenie '. Jeśli wyświetli się błąd, możemy podejrzewać, że aplikacja nie jest odporna na SQL Injection. Wyświetlane błędy są ogólnie dobrym źródłem informacji. Jeśli otrzymaliśmy komunikat błędu po wprowadzeniu apostrofu w polu e-mail, na stronie z opcją - "Wyślij mi moje hasło" podejrzewamy, że wyrażenie wywołane w bazie wygląda tak:

SELECT fieldlist
FROM table
WHERE field = '$EMAIL';

$EMAIL to wpisany adres, już wiemy, że jest częścią dynamicznie wykonywanego kodu. Wprowadzając xxx@mimuw.edu.pl' otrzymujemy:

SELECT fieldlist
FROM table
WHERE field = 'xxx@mimuw.edu.pl'';

i syntax error.

Możemy wprowadzić również, coś takiego: 'anything' OR 'x'='x

SELECT fieldlist
FROM table
WHERE field = 'anything' OR 'x'='x';

Ciekawe...

Zdradliwe znaki specjalne

  • ' zakończenie pojedynczego cudzysłowu, w który są ujmowane dane wprowadzane z wewnątrz;
  • ; Zakończenie zapytania i rozpoczęcie nowego;
  • -- Początek komentarza - w ten sposób usuwa się dalszą część kodu, która nie jest intruzowi potrzebna, a może wywołać błąd składniowy i uniemożliwić wykonanie ataku.

    Przykłady:

    "SELECT id FROM users WHERE username = '" . $username . "' AND password = '" . $password ."'";

    Operatorem konkatenacji w języku PHP jest znak kropki. Cudzysłowy ograniczają poszczególne ciągi znaków (string), a znaki apostrofu (') otaczają fragmenty danych wprowadzane przez użytkownika.

    Na czym polega atak? Jeżeli użytkownik do formularza LoginPage.php wprowadzi następujące dane:

    Użytkownik: '; delete from users-- Hasło:

    To kluczowy fragment kodu PHP, po wstawieniu wprowadzonych danych będzie wyglądał następująco:

    "SELECT id FROM users WHERE username = '" . '; delete from users" . "' AND password = '" . . "'";

    Wstrzykiwania kodu SQL cd.

    Gdy atakujący posiada już jakąś wiedzę o bazie danych i chce korzystać z możliwości dostępu do niej przez przemycenia własnego kodu SQL, może za pomocą UNION lub subSELECT'ów odwoływać się do nazw innych tabel.
    Przy odrobinie szczęścia lub cierpliwości można zgadnąć nazwę jednej z tabel (o ile nie zostanie ona wcześniej dostarczona w treści komunikatu o błędzie).

    SELECT email, passwd, login_id, full_name
    FROM table
    WHERE email = 'x' AND 1=(SELECT COUNT(*) FROM tabname); --';

    Wyszukiwanie użytkowników - LIKE

    Gdy atakującemu udało się już uzyskać nazwę pola tabeli.

    SELECT email, passwd, login_id, full_name
    FROM members
    WHERE email = 'x' OR full_name LIKE '%Bob%';

    Jak uniknąć błędu?

    Analiza wejścia

    Wszystkie dane pochodzące z zewnątrz aplikacji powinny być filtrowane. Procedury powinny przepuszczać tylko te znaki/ciągi, które są dopuszczalne w danym kontekście. Szczególnie ważne jest wyszukiwanie słów kluczowych, takich jak SELECT. Znaków takich jak cudzysłów, apostrof czy podwójny myślnik.
    Oczyszczanie wczytanego ciągu znaków nie zawsze jest jednak rzeczą prostą, a przynajmniej czasami, może być uciążliwe (SQL jest językiem rozbudowanym, istotny jest również kontekst, w którym znaki zostają wczytane).

    Zarządzanie komunikatami o błędach

    Zwykły użytkownik nie powinien otrzymywać komunikatów, mogacych zdradzać szczegóły budowy bazy danych.

    Ograniczanie uprawnień użytkowników

    Przy nadawaniu uprawnień należy stosować zasadę najmniejszych przywilejów. W fazie projektowania należy zdefiniować najmniejszy zestaw informacji niezbędny do wykonania danego zadania. Szczególną uwagę należy zwrócić na prawa dostępu do wewnętrznych struktur bazy danych.

    Oddzielenie danych od kodu

    Unikanie dynamicznie generowanego kodu SQL jest najlepszym rozwiazaniem. Większość interfejsów baz danych zapewnia taką możliwosć (parametry wiązane - PHP, parametry nazwane JDBC). Wyrażenie powinno najpierw zostać "przygotowane" i czekać w bazie na wyliczenie z podanym parametrem, który już nie może zostać pomylony z kodem.

    Przykład w perl'u

    $sth = $dbh->prepare("SELECT email, userid FROM members WHERE email = ?;"); $sth->execute($email);

    Ta metoda wydaje się być najbardziej skuteczna. Do pokonania SQL Injection wystarczy dobra praktyka programistyczna. W takim razie...

    Kto robi, a kto wykorzystuje błędy?

    Na koniec dwa przykłady z roku 2004, pochodzące z witryny hacking.pl.

    Tlenofon

    Na stronach Tlenofonu, która jest usługą portalu o2.pl i komunikatora tlen.pl występował dość poważny błąd pozwalający na dowolną modyfikację zapytań w bazie danych.

    Błąd, który został znaleziony występował w skrypcie obsługującym dział FAQ na stronie tlenofon.pl.

    Z powodu braku kontroli nad przesyłaną informacją znajdującą się w zmiennej nr istniała możliwość "wyjścia" z polecenia SQL - wprowadzając swój własny kod do zmiennej nr gdzie wówczas można było bez problemu dodawać, modyfikować bądź, co gorsza usuwać dowolny wpis w bazie danych.

    Podstawiając pod zmienną nr odpowiedni kod:

    nr=0'%20UNION%20SELECT%200,'Co%20mam%20zrobic%20gdy%20na%20stronie%20znajde%20powazny%20blad%20SQL%20injection%20?','Wyslac%20info%20do%20Hacking.pl%20:)'/*

    w efekcie który wyświetlał na stronie informacje: "Co mam zrobic gdy na stronie znajde powazny blad SQL injection ? Wyslac info do Hacking.pl", a to wszystko bez potrzeby modyfikowania informacji już znajdujących się w bazie danych. Poniżej zrzut z ekranu przedstawiający wyświetlenie przekazanych informacji:

    Kibice internauci

    Kibice Pogoni Szczecin zamieścili na klubowym forum dyskusyjnym link do oficjalnej strony prezydenta RP Aleksandra Kwaśniewskiego.

    Klikasz i czytasz: "Wszyscy obywatele będący kibicami Lecha Poznań zostaną wydaleni z kraju w ciągu najbliższych trzech dni. Jest to kolejny krok w stronę dostosowania praw obowiązujących w Unii Europejskiej, do której Polska wchodzi już 1 maja 2004".

    Wiadomość nie jest oczywiście prawdziwa i to nie biuro prasowe Kwaśniewskiego ją przygotowało. Internauci znaleźli dziurę, która umożliwia bardzo łatwą redakcję tekstów na stronie prezydenta.

    Jak się okazuje to nie jedyna dziura jaka występuje na stronach prezydenta RP. Inna dziura umożliwia modyfikację zapytania SQL, gdzie wartość zmiennej GET "kat_ID" jest wstawiana bezpośrednio do zapytania. Większych problemów nie będzie z wylistowaniem wszystkich informacji z serwisu informacyjnego.

    Możliwe jest także odwołanie się do innych tabel SQL, a nawet modyfikacja ich zawartości, gdzie przykładem może być dodanie własnej informacji do serwisu informacyjnego, który będzie widoczny dla wszystkich odwiedzających stronę Prezydenta, a nie jak to miało miejsce w przypadku niedawnej luki, tylko przy podaniu odpowiednio spreparowanego adresu, który zresztą sam musiał zawierać treść informacji.

    Te manipulacje byłyby z pewnością bardzo utrudnione, gdyby nie inne zaniedbanie autorów serwisu - przy jakimkolwiek błędzie w adresie, dostajemy podane jak na talerzu zapytanie SQL, a więc i strukturę bazy, której odgadnięcie czy zdobycie w przypadku SQL injection stanowi zazwyczaj największy problem.

    źródła:
    COMPUTERWORLD (31 marca 2003) - Wojciech Dworakowski, Łukasz Luzar: Zastrzyk prosto w serce - artykuł
    www.hacking.pl.
    SQL Injection Walkthrough www.securiteam.com
    Steve Friedl's Unixwiz.net SQL Injection Attacks by Example
    Oracle Security papers - Pete Finnigan petefinnigan.com
    Preventing SQL Injection Attacks - Patrick Santry wwwcoder.com
    Protecting Yourself from SQL Injection Attacks By Ross Overstreet źródło
    wikipedia.org