SQL Injection - jak zabezpieczyć stronę
Dodano: 17 listopada 2009 • 2915 wyświetleń • 6 komentarzy
Na prawie każdej stronie generowanej dynamicznie korzysta się z jakiegoś typu bazy danych SQL. Najczęściej jest to MySQL, ale tutaj akurat jest to nieistotne, ponieważ wskazówki, które przedstawię w tym artykule, mają zastosowanie do języka SQL w połączeniu z PHP. Artykuł będzie bowiem o zabezpieczeniu formularzy na stronie WWW przed włamaniami.
W tytule pojawił się tajemniczy zestaw słów: "SQL Injection". W dosłownym tłumaczeniu z języka angielskiego oznacza on zastrzyk SQL. Nazwa wzięła się z sposobu w jaki wykorzystuje się nieodpowiednie zabezpieczenia.
Najprostszym przykładem będzie prosta wyszukiwarka na stronę internetową. W pole, w które wpisujemy hasło, które nas interesuje "wstrzykujemy" złośliwy kod SQL. Jeśli zapytanie SQL skryptu wygląda tak:
$zapytanie="SELECT * FROM `arts` WHERE `title` LIKE '" . $fraza . "'";
to wystarczy w formularzu podać:
*'; DELETE FROM `users` WHERE `id` LIKE '*
Wtedy zapytanie wyszukiwarki przybierze następującą postać:
SELECT * FROM `arts` WHERE `title` LIKE '*'; DELETE FROM `users` WHERE `id` LIKE '*'
Część zaznaczona na czerwono, to ciąg wpisany w pole formularza. Całość zadziała następująco: najpierw zostaną pobrane wszystkie wpisy, o dowolnym tytule (* - oznacza w SQL dowolny ciąg znaków), a następnie zostaną usunięte wszystkie wpisy z tabeli users.
Jak więc widać brak odpowiedniego zabezpieczenia formularzy może spowodować całkowite zniszczenie strony, która jest oparta wyłącznie na bazie danych.
Poprzez SQL Inection można również dokonać ataku typu DoS (Denial of Service - z ang. odmowa dostępu). Polega on na podaniu bardzo czasochłonnego zapytania. Przykładowo:
x' AND BENCHMARK(99999999,BENCHMARK(99999999,BENCHMARK(99999999,MD5(NOW())))))=0 OR '1'='1
W podanym wyżej przykładzie, serwer ma za zadanie obliczyć sumę MD5 dla aktualnego czasu 99999999[sup]3[/sup] = 999999970000000299999999 razy!
Kolejnym typem ataków przez SQL Injection jest tzw. "ślepy atak". Polega ona na wykonaniu takiego zapytania, które nie będzie zwracało żadnego wyniku. Może ono wyglądać np. tak:
SELECT * FROM `users` WHERE `name` LIKE 'Mietek' AND 1=3
Powyższe zapytanie nie zwróci żadnego wyniku, ponieważ liczba 1 nigdy nie będzie równa 3, a więc może być spełniony tylko jeden warunek.
Teraz powiem trochę o zabezpieczeniach. Pierwszym, najszybszym sposobem, jest "przepuszczenie" danych z formularza przez funkcję addslashes();. Umieszcza ona (tzw. backslash) przed potencjalnie niebezpiecznymi znakami jak: ', ; itp.
Drugim, zabezpieczeniem, które mimo wykorzystania pierwszego podanego tu sposobu warto wykonać, jest usunięcie niektórych przywilejów dla użytkownika, który jest wykorzystywany przez skrypty. Skrypt dodający komentarze na stronie potrzebuje przecież tylko dwóch (ew. trzech) przywilejów. Potrzebuje mieć możliwość wstawiania nowych wpisów (INSERT), wybierania wpisów (SELECT) i czasem edytowania (UPDATE). Usuwając możliwość kasowania wpsiów (DELETE), tabel i kolumn (DROP) zabezpieczamy się przed takimi atakami, którym udało się przejść przez pierwszy poziom (do wykonania takiego ataku potrzeba naprawdę profesjonalnego hackera).
Ostatecznie, można się posunąć do wyłączenia niepotrzebnej funkcjonalności w samym silniku.
Zobacz również:
Komentarze
Napisz komentarz
O mnie: Nazywam się Kacper Kołodziej. Jestem uczniem II klasy II LO w Pabianicach o profilu matematyczno-fizycznym. Od 7 lat gram na gitarze. Skończyłem Państwową Szkołę Muzyczną I stopnia w Pabianicach; aktualnie jestem w trzeciej klasie szkoły II stopnia. Oprócz muzyki zajmuję się także tworzeniem stron. Moje prace można obejrzeć w portfolio.
O blogu: Na tym blogu publikuję wszystkie artykuły mojego autorstwa dotyczące programowania, tworzenia stron www, komputerów i internetu, a także muzyki.




webmo Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.0.15) Gecko/2009101601 Firefox/3.0.15
pozdrawiam
18 listopada 2009 o 11:15:16
lisek Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3 GTB6
Jak ktoś chce już na maxa zabezpieczyć bazę, to można też użyć wyrażeń regularnych (chociaż to tak tylko dla świętego spokoju, to co Kacper opisał w zupełności wystarczy). Np w polu "imię" dozwolić litery i spacje, cudzysłowy itd są tu niepotrzebne. W polu "wiek": same cyfry, w polu hasło-wszystkie znaki, ale całość potem przez md5 lub sha1, po tych funkcjach cudzysłowów bym się nie spodziewał...
15 stycznia 2010 o 19:35:16
Masayashi strona www Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.127 Safari/533.4
pozdro
02 września 2010 o 18:38:29
Kacper Kołodziej strona www Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.53 Safari/534.3
03 września 2010 o 21:05:16
Masayashi strona www Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.53 Safari/534.3
nie wiem skąd się dowiedziałeś że trzeba ten apostrof wstawić żeby funkcji użyć? Nie trzeba tego apostrofu nigdzie wstawiać. ASCII i hex - może? Najwidoczniej nie posiadasz zbyt dużo wiedzy na ten temat, bo ASCII i hex bez problemu działa w wypadku addslashes(). Najlepszym sposobem na zabezpieczenie jest: whitelist, wyrażenia regularne, htmlspecialchars(), strip_tags(), sprawdzanie czy jest to liczba lub ciąg znaków np. is_int() lub is_string(). Tak przy okazji znak apostrofu można wstawić za pomocą ASCII, hex lub char() więc i tak da się to obejść.
Pozdro
PS Poczytaj trochę o SQLi i Blind SQLi
04 września 2010 o 10:35:28
Kacper Kołodziej strona www Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.53 Safari/534.3
04 września 2010 o 12:20:28