TL; DR
- Aplikacja akceptuje wejście, w tym przypadku „Nancy”, bez próby - zdezynfekować wejście, jak uciekając znaków specjalnych
szkolnych => INSERT INTO studentów VALUES ( „Nancy” ); WSTAW 0 1
- SQL Injection występuje, gdy wejście do komendy bazy jest manipulować - przyczyna serwer bazy danych SQL do wykonania dowolna
szkolne => INSERT INTO studentów VALUES ( „Robert” ); Studenci DROP TABLE ; - '); WSTAW 0 1 TABELA KROPLI
- Dokumenty studenckie zniknęły - mogło być jeszcze gorzej!
szkoła => WYBIERZ * OD uczniów ;
BŁĄD : relacja „studenci” ma nie istnieć
LINIA 1 : WYBIERZ * OD studentów ; ^
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:
szkoła => UTWÓRZ uczniów w tabeli ( nazwa TEKST KLUCZ PODSTAWOWY );
OGŁOSZENIE : TWORZENIE TABLE / PRIMARY KEY będzie utworzyć niejawny indeksu "students_pkey" na stole "studenci" TWORZENIE TABLE
szkoły => INSERT INTO studentów VALUES ( 'John' ); WSTAW 0 1
Załóżmy, że aplikacja używa następującego kodu SQL do wstawiania danych do tabeli:
WSTAWIĆ DO WARTOŚCI studentów ( „foobar” );
Zamień foobar
na prawdziwe nazwisko ucznia. Normalna operacja wstawiania wyglądałaby następująco:
- Wejście: Nancy
szkoła => INSERT INTO studentów VALUES ( 'Nancy' ); WSTAW 0 1
Gdy przeszukujemy tabelę, otrzymujemy:
szkoła => WYBIERZ * OD uczniów ;
imię
-------
Jan
Nancy
( 2 rzędy )
Co się stanie, gdy wstawimy nazwę Little Bobby Tables do tabeli?
- Wejście: Robert '); Studenci DROP TABLE; -
Szkoła => INSERT INTO studentów VALUES ( 'Robert' ); Studenci DROP TABLE ; - '); WSTAW 0 1 TABELA KROPLI
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?
szkoła => WYBIERZ * OD uczniów ;
BŁĄD : relacja „studenci” ma nie istnieć
LINIA 1 : WYBIERZ * OD studentów ; ^
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.