Pomysł jest bardzo prosty - zapytanie i dane przesyłane są osobno na serwer bazy danych .
To wszystko.
Źródłem problemu z iniekcją SQL jest mieszanie kodu i danych.
W rzeczywistości nasze zapytanie SQL jest legalnym programem . A my tworzymy taki program dynamicznie, dodając pewne dane w locie. W związku z tym dane mogą zakłócać kod programu, a nawet go zmieniać, co pokazuje każdy przykład wstrzyknięcia SQL (wszystkie przykłady w PHP / Mysql):
$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";
wygeneruje zwykłe zapytanie
SELECT * FROM users where id=1
podczas gdy ten kod
$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";
wygeneruje złośliwą sekwencję
SELECT * FROM users where id=1; DROP TABLE users;
Działa, ponieważ dodajemy dane bezpośrednio do treści programu i stają się one częścią programu, więc dane mogą zmienić program, aw zależności od przekazanych danych będziemy mieli albo zwykłe dane wyjściowe, albo users
usuniętą tabelę .
O ile w przypadku przygotowanych wypowiedzi nie zmieniamy naszego programu, to pozostaje on nienaruszony, o
to chodzi.
Najpierw wysyłamy program na serwer
$db->prepare("SELECT * FROM users where id=?");
gdzie dane są zastępowane przez jakąś zmienną zwaną parametrem lub symbolem zastępczym.
Zwróć uwagę, że do serwera wysyłane jest dokładnie to samo zapytanie, bez żadnych danych! Następnie wysyłamy dane z drugim żądaniem, zasadniczo oddzielonym od samego zapytania:
$db->execute($data);
więc nie może zmienić naszego programu i wyrządzić żadnej szkody.
Całkiem proste - prawda?
Jedyne co muszę dodać, że zawsze pomijane w każdej instrukcji:
Przygotowane instrukcje mogą chronić tylko literały danych , ale nie mogą być używane z żadną inną częścią zapytania.
Kiedy więc musimy dodać, powiedzmy, dynamiczny identyfikator - na przykład nazwę pola - przygotowane zestawienia nie mogą nam pomóc. Mam wyjaśnił sprawę niedawno , więc nie będę powtarzać.
$spoiled_data = "1; DROP TABLE users;"
->$query = "SELECT * FROM users where id=$spoiled_data";
od:$db->prepare("SELECT * FROM users where id=?");
->$data = "1; DROP TABLE users;"
->$db->execute($data);
. Czy nie zrobią tego samego?Oto SQL do skonfigurowania przykładu:
Klasa Inject jest podatna na iniekcje SQL. Zapytanie jest dynamicznie wklejane wraz z danymi wejściowymi użytkownika. Celem zapytania było pokazanie informacji o Robercie. Wynagrodzenie lub premia na podstawie danych wejściowych użytkownika. Jednak złośliwy użytkownik manipuluje danymi wejściowymi, uszkadzając zapytanie, dołączając odpowiednik „lub prawda” do klauzuli where, tak aby wszystko zostało zwrócone, w tym informacje o Aaronie, które miały być ukryte.
Po uruchomieniu tego pierwszy przypadek dotyczy normalnego użytkowania, a drugi złośliwego wstrzyknięcia:
Nie należy budować instrukcji SQL z konkatenacją łańcuchów danych wejściowych użytkownika. Jest nie tylko podatny na wstrzyknięcie, ale ma również wpływ na buforowanie na serwerze (instrukcja zmienia się, więc prawdopodobieństwo trafienia w pamięć podręczną instrukcji SQL jest mniejsze, podczas gdy przykład wiązania zawsze uruchamia tę samą instrukcję).
Oto przykład Binding, aby uniknąć tego rodzaju zastrzyków:
Uruchomienie tego z tymi samymi danymi wejściowymi, co w poprzednim przykładzie, pokazuje, że złośliwy kod nie działa, ponieważ żaden typ płatności nie pasuje do tego ciągu:
źródło
PREPARE
tworzy ustaloną nazwaną instrukcję, która jest już przeanalizowana (tj. instrukcja nie zmieni się już bez względu na dane wejściowe), podczas gdyEXECUTE
uruchomi nazwaną instrukcję wiążącą parametry. PonieważPREPARE
ma tylko czas trwania sesji, naprawdę wygląda na to, że jest przeznaczony dla wydajności, a nie do zapobiegania wstrzykiwaniu przez skrypty psql. Aby uzyskać dostęp do psql, może nadać uprawnienia do procedur składowanych i powiązać parametry w ramach procs.Zasadniczo, dzięki przygotowanym instrukcjom dane pochodzące od potencjalnego hakera są traktowane jako dane - i nie ma możliwości, aby można je było wymieszać z SQL aplikacji i / lub zinterpretować jako SQL (co może się zdarzyć, gdy przekazane dane są umieszczane bezpośrednio w SQL aplikacji).
Dzieje się tak dlatego, że przygotowane instrukcje najpierw „przygotowują” zapytanie SQL, aby znaleźć efektywny plan zapytania, a później wysyłają rzeczywiste wartości, które przypuszczalnie pochodzą z formularza - wtedy zapytanie jest faktycznie wykonywane.
Więcej świetnych informacji tutaj:
Przygotowane instrukcje i iniekcja SQL
źródło
Przeczytałem odpowiedzi i nadal czułem potrzebę podkreślenia kluczowego punktu, który wyjaśnia istotę przygotowanych oświadczeń. Rozważ dwa sposoby wykonywania zapytań w bazie danych, w przypadku których wymagane są dane wejściowe użytkownika:
Podejście naiwne
Jeden łączy dane wejściowe użytkownika z częściowym ciągiem znaków SQL w celu wygenerowania instrukcji SQL. W takim przypadku użytkownik może osadzić złośliwe polecenia SQL, które zostaną następnie przesłane do bazy danych w celu wykonania.
Na przykład złośliwe dane wejściowe użytkownika mogą prowadzić do
SQLString
równości"SELECT * FROM CUSTOMERS WHERE NAME='James';DROP TABLE CUSTOMERS;'
Ze względu na złośliwego użytkownika
SQLString
zawiera 2 instrukcje, z których druga ("DROP TABLE CUSTOMERS"
) spowoduje szkodę.Przygotowane wyciągi
W tym przypadku, ze względu na oddzielenie zapytania i danych, dane wejściowe użytkownika nigdy nie są traktowane jako instrukcja SQL, a zatem nigdy nie są wykonywane . Z tego powodu każdy wstrzyknięty złośliwy kod SQL nie wyrządziłby żadnej szkody. Więc
"DROP TABLE CUSTOMERS"
nigdy nie zostałby wykonany w powyższym przypadku.Krótko mówiąc, przy przygotowanych instrukcjach złośliwy kod wprowadzony przez użytkownika nie zostanie wykonany!
źródło
Kiedy tworzysz i wysyłasz przygotowaną instrukcję do DBMS, jest ona przechowywana jako zapytanie SQL do wykonania.
Później łączysz swoje dane z zapytaniem w taki sposób, że DBMS używa tych danych jako parametrów zapytania do wykonania (parametryzacji). DBMS nie używa danych, które łączysz jako uzupełnienie już skompilowanego zapytania SQL; to po prostu dane.
Oznacza to, że zasadniczo niemożliwe jest wykonanie wstrzyknięcia SQL przy użyciu przygotowanych instrukcji. Sam charakter przygotowanych instrukcji i ich związek z DBMS temu zapobiega.
źródło
W SQL Server użycie przygotowanej instrukcji jest zdecydowanie odporne na wstrzyknięcie, ponieważ parametry wejściowe nie tworzą zapytania. Oznacza to, że wykonane zapytanie nie jest zapytaniem dynamicznym. Przykład instrukcji podatnej na iniekcję SQL.
Teraz, jeśli wartość w zmiennej inoutusername jest czymś w rodzaju 'lub 1 = 1 -, to zapytanie staje się teraz:
A reszta jest komentowana później
--
, więc nigdy nie jest wykonywana i pomijana, jak przy użyciu przygotowanego przykładu instrukcji, jak poniżej.W efekcie nie możesz wysłać kolejnego parametru, unikając w ten sposób iniekcji SQL ...
źródło
Kluczową frazą jest
need not be correctly escaped
. Oznacza to, że nie musisz się martwić, że ludzie będą próbować wstawiać myślniki, apostrofy, cytaty itp.Wszystko załatwiamy za Ciebie.
źródło
Załóżmy, że masz to w serwlecie, który masz rację. Jeśli złośliwa osoba przekaże złą wartość dla „filtra”, możesz zhakować bazę danych.
źródło
Podstawowa przyczyna nr 1 - problem z separatorem
Wstrzyknięcie Sql jest możliwe, ponieważ używamy cudzysłowów do oddzielania ciągów, a także jako części ciągów, co czasami uniemożliwia ich interpretację. Gdybyśmy mieli ograniczniki, których nie można użyć w danych łańcuchowych, wstrzyknięcie sql nigdy by się nie wydarzyło. Rozwiązanie problemu z separatorem eliminuje problem z wtryskiem sql. Robią to zapytania strukturalne.
Przyczyna nr 2 - Ludzka natura, ludzie są przebiegli, niektórzy przebiegli ludzie są złośliwi i wszyscy popełniają błędy
Inną główną przyczyną iniekcji sql jest natura ludzka. Ludzie, w tym programiści, popełniają błędy. Gdy popełnisz błąd w zapytaniu strukturalnym, nie narazi to systemu na wstrzyknięcie sql. Jeśli nie używasz zapytań strukturalnych, błędy mogą generować lukę w zabezpieczeniach sql injection.
Jak zapytania strukturalne rozwiązują podstawowe przyczyny iniekcji SQL
Zapytania strukturalne rozwiązują problem separatora, umieszczając polecenia sql w jednej instrukcji i umieszczając dane w oddzielnej instrukcji programowania. Instrukcje programowania tworzą potrzebną separację.
Zapytania strukturalne pomagają zapobiegać powstawaniu krytycznych luk w zabezpieczeniach przez błędy ludzkie. Jeśli chodzi o ludzi popełniających błędy, wstrzyknięcie sql nie może nastąpić, gdy używane są zapytania strukturalne. Istnieją sposoby zapobiegania wstrzykiwaniu sql, które nie obejmują zapytań strukturalnych, ale normalny błąd ludzki w takich podejściach zwykle prowadzi do przynajmniej częściowego narażenia na wstrzyknięcie sql. Zapytania strukturalne są odporne na awarie po wstrzyknięciu sql. Możesz popełnić wszystkie błędy świata, prawie za pomocą zapytań strukturalnych, tak samo jak w przypadku każdego innego programowania, ale żadnego, który możesz zrobić, nie można przekształcić w ssstem przejęty przez wstrzyknięcie sql. Dlatego ludzie lubią mówić, że jest to właściwy sposób zapobiegania wstrzykiwaniu sql.
Więc masz to, przyczyny wstrzyknięcia sql i kwerendy strukturalne natury, które uniemożliwiają ich użycie.
źródło