Wystarczy spojrzeć na:
(Źródło: https://xkcd.com/327/ )
Co robi ten SQL:
Robert'); DROP TABLE STUDENTS; --
Znam oba '
i jestem --
do komentowania, ale czy to słowo DROP
również nie jest komentowane, ponieważ jest częścią tego samego wiersza?
security
validation
sql-injection
Blankman
źródło
źródło
'
nie służy do komentowania . Nawet gdyby tak było, nie ma przed nim spacji, więc może jedynie zakończyć ciąg znaków, który go poprzedza.Odpowiedzi:
Upuszcza stół uczniów.
Oryginalny kod w programie szkoły prawdopodobnie wygląda mniej więcej tak
Jest to naiwny sposób dodawania tekstu do zapytania, i jak widać , jest bardzo zły .
Po połączeniu wartości z pierwszego imienia, drugiego pola tekstowego FNMName.Text (który jest
Robert'); DROP TABLE STUDENTS; --
) i ostatniego pola tekstowego LName.Text (nazwijmy toDerper
) są połączone z resztą zapytania, wynikiem są teraz właściwie dwa zapytania oddzielone terminator instrukcji (średnik). Drugie zapytanie zostało wprowadzone do pierwszego. Gdy kod wykona to zapytanie względem bazy danych, będzie to wyglądać następującoco w prostym języku angielskim z grubsza przekłada się na dwa zapytania:
i
Wszystko po drugim zapytaniu jest oznaczone jako komentarz :
--', 'Derper')
W
'
imieniu ucznia nie jest komentarzem, to ogranicznik ciągu zamykającego . Ponieważ nazwa ucznia jest ciągiem, jest potrzebna składniowo, aby wypełnić hipotetyczne zapytanie. Ataki typu Injection działają tylko wtedy, gdy wprowadzane zapytanie SQL powoduje powstanie prawidłowego kodu SQL .Edytowane ponownie zgodnie z bystrym komentarzem dan04
źródło
INSERT
, to nawias miałby większy sens. Wyjaśnia to również, dlaczego połączenie z bazą danych nie jest w trybie tylko do odczytu.INSERT
. Myśląc wstecz, i takSELECT
by nie działało, ponieważ wstawka Małych Stół Bobby'ego w tabeli już by upuściła stół.Students
oczekuje więcej niż tylko jednej kolumny (oryginalna / poprawna instrukcja zawierała dwie kolumny). To powiedziawszy, obecność drugiej kolumny jest pomocna, aby pokazać, dlaczego komentarz jest wymagany; a ponieważ nie można zmienić nazwiska Bobby'ego, prawdopodobnie najlepiej jest pozostawić „tak jak jest”, mając niewiele więcej niż tę obserwację jako przypis.Załóżmy, że nazwa była używana w zmiennej
$Name
.Następnie uruchom następujące zapytanie :
Kod omyłkowo umieszcza wszystko, co użytkownik podał jako zmienną.
Chciałeś, aby SQL był:
Ale sprytny użytkownik może dostarczyć wszystko, co chce:
Otrzymujesz:
--
Komentuje tylko pozostałą część linii.źródło
Jak wszyscy już zauważyli,
');
zamyka oryginalne oświadczenie, a następnie następuje drugie oświadczenie. Większość frameworków, w tym języki takie jak PHP, ma teraz domyślne ustawienia zabezpieczeń, które nie zezwalają na wiele instrukcji w jednym ciągu SQL. Na przykład w PHP można uruchamiać wiele instrukcji w jednym ciągu SQL za pomocąmysqli_multi_query
funkcji.Można jednak manipulować istniejącą instrukcją SQL za pomocą wstrzykiwania SQL bez konieczności dodawania drugiej instrukcji. Załóżmy, że masz system logowania, który sprawdza nazwę użytkownika i hasło za pomocą tego prostego wyboru:
Jeśli podasz
peter
jako nazwę użytkownika isecret
hasło, wynikowy ciąg SQL wyglądałby następująco:Wszystko w porządku. Teraz wyobraź sobie, że podajesz ten ciąg jako hasło:
Następnie wynikowy ciąg SQL byłby następujący:
Umożliwi to zalogowanie się na dowolne konto bez znajomości hasła. Nie trzeba więc używać dwóch instrukcji, aby użyć wstrzykiwania SQL, chociaż można zrobić bardziej destrukcyjne rzeczy, jeśli można podać wiele instrukcji.
źródło
Nie,
'
nie jest to komentarz w SQL, ale separator.Mama podejrzewała, że programista bazy danych poprosił o wygląd:
(na przykład), aby dodać nowego ucznia, w którym
$xxx
zawartość zmiennej została pobrana bezpośrednio z formularza HTML, bez sprawdzania formatu ani znaków specjalnych.Więc jeśli
$firstName
zawieraRobert'); DROP TABLE students; --
program bazy danych wykona następujące żądanie bezpośrednio na DB:to znaczy. zakończy wcześnie polecenie wstawiania, wykona dowolny złośliwy kod, którego chce cracker, a następnie skomentuje pozostałą część kodu.
Mmm, jestem zbyt wolny, widzę już 8 odpowiedzi przed moją w pomarańczowym zespole ... :-) Wydaje się, że jest to popularny temat.
źródło
TL; DR
Spowoduje to upuszczenie (usunięcie) tabeli ucznia.
( Wszystkie przykłady kodu w tej odpowiedzi zostały uruchomione na serwerze bazy danych PostgreSQL 9.1.2. )
Aby wyjaśnić, co się dzieje, spróbujmy tego z prostą tabelą zawierającą tylko pole nazwy i dodaj pojedynczy wiersz:
Załóżmy, że aplikacja używa następującego kodu SQL do wstawiania danych do tabeli:
Zamień
foobar
na prawdziwe nazwisko ucznia. Normalna operacja wstawiania wyglądałaby następująco:Gdy przeszukujemy tabelę, otrzymujemy:
Co się stanie, gdy wstawimy nazwę Little Bobby Tables do tabeli?
Wstrzyknięcie SQL jest wynikiem imienia ucznia kończącego instrukcję i zawierającego osobne
DROP TABLE
polecenie; dwa myślniki na końcu danych wejściowych mają na celu skomentowanie pozostałego kodu, który w przeciwnym razie spowodowałby błąd. Ostatni wiersz danych wyjściowych potwierdza, że serwer bazy danych upuścił tabelę.Ważne jest, aby zauważyć, że podczas
INSERT
operacji aplikacja nie sprawdza danych wejściowych pod kątem znaków specjalnych, a zatem umożliwia wprowadzanie dowolnych danych wejściowych do polecenia SQL. Oznacza to, że złośliwy użytkownik może wstawić, w polu normalnie przeznaczonym do wprowadzania przez użytkownika, specjalne symbole, takie jak cudzysłowy, wraz z dowolnym kodem SQL, aby spowodować wykonanie go przez system bazy danych, stąd też wstrzyknięcie SQL .Wynik?
Wstrzykiwanie SQL to odpowiednik bazy danych podatności na zdalne wykonanie dowolnego kodu w systemie operacyjnym lub aplikacji. Nie można nie docenić potencjalnego wpływu udanego wstrzyknięcia SQL - w zależności od systemu bazy danych i konfiguracji aplikacji atakujący może go użyć do spowodowania utraty danych (jak w tym przypadku), uzyskania nieautoryzowanego dostępu do danych, a nawet wykonania dowolny kod na maszynie hosta.
Jak zauważono w komiksie XKCD, jednym ze sposobów ochrony przed atakami iniekcyjnymi SQL jest dezynfekcja danych wejściowych bazy danych, na przykład poprzez ucieczkę znaków specjalnych, aby nie mogły modyfikować bazowej komendy SQL, a zatem nie mogły powodować wykonania dowolnego kodu SQL. Jeśli używasz sparametryzowanych zapytań, na przykład za pomocą
SqlParameter
ADO.NET, dane wejściowe zostaną co najmniej automatycznie oczyszczone, aby zabezpieczyć się przed wstrzyknięciem SQL.Jednak odkażanie danych wejściowych na poziomie aplikacji może nie zatrzymać bardziej zaawansowanych technik wstrzykiwania SQL. Na przykład istnieją sposoby na obejście
mysql_real_escape_string
funkcji PHP . W celu dodatkowej ochrony wiele systemów baz danych obsługuje przygotowane instrukcje . Jeśli poprawnie zaimplementowane w backendie, przygotowane instrukcje mogą uniemożliwić wstrzykiwanie SQL, traktując dane wejściowe jako semantycznie oddzielone od reszty polecenia.źródło
Powiedzmy, że naiwnie napisałeś taką metodę tworzenia uczniów:
I ktoś wpisuje imię
Robert'); DROP TABLE STUDENTS; --
W bazie danych uruchamiane jest to zapytanie:
Średnik kończy polecenie wstawiania i uruchamia kolejne; the - komentuje resztę linii. Polecenie DROP TABLE jest wykonywane ...
Dlatego parametry wiązania są dobrą rzeczą.
źródło
Pojedynczy cytat to początek i koniec łańcucha. Średnik jest końcem instrukcji. Więc jeśli dokonali takiego wyboru:
SQL stałby się:
W niektórych systemach
select
uruchamiany byłby pierwszy, a następniedrop
instrukcja! Komunikat brzmi: NIE WBUDUJ WARTOŚCI W SWOIM SQL. Zamiast tego użyj parametrów!źródło
Te
');
końce zapytanie, to nie rozpocznie komentarz. Następnie upuszcza tabelę studentów i komentuje resztę zapytania, które miało zostać wykonane.źródło
Autor bazy danych prawdopodobnie zrobił to
Jeśli podano nazwę ucznia, to dokonuje wyboru o nazwie „Robert”, a następnie upuszcza tabelę. Część „-” zmienia resztę podanego zapytania w komentarz.
źródło
W tym przypadku „nie jest znakiem komentarza. Służy do ograniczania literałów łańcuchowych. Artysta komiksowy opiera się na pomyśle, że dana szkoła ma dynamiczny sql gdzieś, który wygląda mniej więcej tak:
Teraz znak „kończy literał ciągów, zanim programista się tego spodziewał. W połączeniu z; Aby zakończyć instrukcję, osoba atakująca może teraz dodać dowolną nazwę SQL. - - komentarz na końcu ma na celu upewnienie się, że wszelkie pozostałe pliki SQL w oryginalnej instrukcji nie uniemożliwiają kompilacji zapytania na serwerze.
FWIW, myślę też, że w tym komiksie jest ważny ważny błąd: jeśli myślisz o oczyszczeniu danych wejściowych do bazy danych, jak sugeruje komiks, nadal robisz to źle. Zamiast tego powinieneś pomyśleć o kwarantannie danych wejściowych do bazy danych, a poprawnym sposobem na to są sparametryzowane zapytania.
źródło
'
Znaków w SQL służy do stałych łańcuchowych. W tym przypadku służy do zakończenia stałej łańcucha, a nie do komentarza.źródło
Oto jak to działa: Załóżmy, że administrator szuka rekordów ucznia
Ponieważ konto administratora ma wysokie uprawnienia, możliwe jest usunięcie tabeli z tego konta.
Kod do pobrania nazwy użytkownika z żądania to
Teraz zapytanie byłoby mniej więcej takie (aby przeszukać tabelę uczniów)
Wynikowe zapytanie staje się
Ponieważ dane wejściowe użytkownika nie są dezynfekowane, powyższe zapytanie zostało zmanipulowane na 2 części
Podwójny myślnik (-) po prostu skomentuje pozostałą część zapytania.
Jest to niebezpieczne, ponieważ może unieważnić uwierzytelnianie hasła, jeśli jest obecne
Pierwszy wykona normalne wyszukiwanie.
Drugi zrzuci ucznia z tabeli, jeśli konto ma wystarczające uprawnienia (ogólnie konto szkolnego administratora uruchomi takie zapytanie i będzie miało wyżej wymienione uprawnienia).
źródło
SELECT* FROM sutdents ...
- zapomniałeś „s”. Właśnie to upuszczasz.DROP TABLE STUDENTS;
Nie trzeba wprowadzać danych formularza, aby wykonać iniekcję SQL.
Nikt wcześniej tego nie zauważył, więc mogę zaalarmować niektórych z was.
Przeważnie spróbujemy załatać dane wejściowe formularzy. Ale to nie jedyne miejsce, w którym możesz zostać zaatakowany przez wstrzyknięcie SQL. Możesz wykonać bardzo prosty atak za pomocą adresu URL, który wysyła dane za pośrednictwem żądania GET; Rozważ następujący przykład:
Twój adres URL wyglądałby http://yoursite.com/show?id=1
Teraz ktoś może spróbować czegoś takiego
Spróbuj zastąpić nazwę tabeli rzeczywistą nazwą tabeli. Jeśli poprawnie poda nazwę twojego stołu, opróżnią twój stół!(Bardzo łatwo jest brutalnie wymusić ten adres URL za pomocą prostego skryptu)
Twoje zapytanie wyglądałoby mniej więcej tak:
Przykład wrażliwego kodu PHP używającego PDO:
Rozwiązanie - użyj metod PDO preparat () i bindParam ():
źródło