Jak PreparedStatement uniknąć lub zapobiec SQL injection?

Wiem, że PreparedStatements uniknąć / zapobiec SQL Injection. Jak to robi? Czy ostateczne zapytanie formularza, które jest konstruowane przy użyciu PreparedStatements będzie ciągiem znaków lub w inny sposób?

Author: Mark Rotteveel, 2009-10-17

9 answers

Problem z SQL injection polega na tym, że wejście użytkownika jest używane jako część instrukcji SQL. Używając gotowych instrukcji możesz wymusić, aby dane wejściowe użytkownika były traktowane jako zawartość parametru (a nie jako część polecenia SQL).

Ale jeśli nie używasz danych wejściowych użytkownika jako parametru dla przygotowanej instrukcji, ale zamiast tego budujesz polecenie SQL łącząc ze sobą ciągi znaków, jesteś nadal podatny na iniekcje SQL , nawet gdy używasz przygotowanych instrukcji.

 61
Author: tangens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-17 13:07:36

Rozważ dwa sposoby robienia tego samego:

PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();

Lub

PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();

Jeśli "user" pochodzi z wejścia użytkownika, a wejście użytkownika było

Robert'); DROP TABLE students; --
Wtedy, w pierwszej kolejności, zostałbyś złapany. W drugim będziesz bezpieczny, a małe stoliki Bobby ' ego zostaną zarejestrowane do twojej szkoły.
 156
Author: Paul Tomblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-22 13:38:59

Aby zrozumieć, jak PreparedStatement zapobiega wstrzykiwaniu SQL, musimy zrozumieć fazy wykonywania zapytań SQL.

1. Faza Kompilacji. 2. Faza Egzekucyjna.

Gdy silnik SQL server otrzyma zapytanie, musi przejść przez poniższe fazy,

Fazy Wykonywania Zapytań

  1. Faza parsowania i normalizacji: W tej fazie zapytanie jest sprawdzane pod kątem składni i semantyki. Sprawdza, czy odwołuje się do tabeli i kolumny użyte w zapytaniu istnieć czy nie. Ma również wiele innych zadań do wykonania, ale nie idźmy szczegółowo.

  2. Faza Kompilacji: W tej fazie słowa kluczowe używane w zapytaniach takich jak select, from, where etc są konwertowane do formatu zrozumiałe przez maszynę. Jest to faza, w której interpretowane jest zapytanie i podejmowane są odpowiednie działania. Ma również wiele innych zadań do wykonania, ale nie idźmy szczegółowo.

  3. Plan Optymalizacji Zapytań: W tej fazie drzewo decyzyjne jest stworzony w celu znalezienia sposobów wykonania zapytania. Dowiaduje się o liczbie sposobów, w jakie można wykonać zapytanie i kosztach związanych z każdą z nich wykonania zapytania. Wybiera najlepszy plan wykonania zapytania.

  4. Cache: Najlepszy plan wybrany w planie optymalizacji zapytań jest przechowywany w pamięci podręcznej, dzięki czemu gdy następny czas ten sam zapytanie przychodzi, to nie musi przejść przez fazę 1, fazę 2 I Fazę 3 ponownie. Kiedy następnym razem pojawi się zapytanie, będzie to sprawdzane bezpośrednio w pamięci podręcznej i stamtąd odbierane do wykonania.

  5. Faza Realizacji: W tej fazie dostarczane zapytanie zostanie wykonane, a dane zostaną zwrócone użytkownikowi jako obiekt ResultSet.

Zachowanie API PreparedStatement na powyższych krokach

  1. PreparedStatements nie są kompletnymi zapytaniami SQL i zawierają elementy zastępcze), które w czasie wykonywania są zastępowane przez rzeczywiste dane dostarczone przez użytkownika.

  2. Ilekroć jakiekolwiek przygotowanie zawierające symbole zastępcze są przekazywane do silnika SQL Server, Przechodzi przez kolejne fazy

    1. Faza parsowania i normalizacji
    2. Faza Kompilacji
    3. Plan Optymalizacji Zapytań
    4. Cache (skompilowane zapytanie z symbolami zastępczymi są przechowywane w pamięci podręcznej.)

UPDATE user set username=? i hasło=? WHERE id=?

  1. Powyższe zapytanie zostanie przetworzone, skompilowane z elementami zastępczymi jako specjalne traktowanie, zoptymalizowane oraz get Cached. Zapytanie na tym etapie jest już skompilowane i przekonwertowane w formacie zrozumiałym dla maszyny. Możemy więc powiedzieć, że zapytanie przechowywane w pamięci podręcznej jest wstępnie skompilowane i tylko elementy zastępcze muszą być zastąpione danymi podanymi przez użytkownika.

  2. Teraz w czasie wykonywania, gdy dane dostarczone przez użytkownika są dostarczane, wstępnie skompilowane zapytanie jest pobierane z pamięci podręcznej, a symbole zastępcze są zastępowane danymi dostarczonymi przez użytkownika.

Przygotowanie do pracy

(pamiętaj, że po miejscu posiadacze są zastąpione danymi użytkownika, ostateczne zapytanie nie jest skompilowany/zinterpretowany ponownie i silnik SQL Server traktuje dane użytkownika jako czyste DANE, a nie SQL, który musi być parsowany lub skompilowany ponownie; to jest piękno PreparedStatement.)

Jeśli zapytanie nie musi przechodzić ponownie przez fazę kompilacji, to wszelkie dane wymienione na placeholdery są traktowane jako czyste DANE i nie ma znaczenia dla silnika SQL Server i bezpośrednio wykonuje zapytanie.

Uwaga: Jest to kompilacja Faza po fazie parsowania, która rozumie / interpretuje zapytanie strukturę i nadaje jej sensowne zachowanie. W przypadku PreparedStatement, zapytanie jest skompilowane tylko raz i buforowane skompilowane zapytanie jest odbierane przez cały czas, aby zastąpić dane użytkownika i wykonać.

Ze względu na funkcję jednorazowej kompilacji PreparedStatement, jest wolny od SQL Injection do ataku.

Możesz uzyskać szczegółowe wyjaśnienie za pomocą przykładu proszę.: http://javabypatel.blogspot.in/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html

 64
Author: Jayesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-26 06:39:06

SQL użyty w PreparedStatement jest wstępnie skompilowany na driverze. Od tego momentu parametry są przesyłane do drivera jako wartości dosłowne, a nie wykonywalne części SQL; w ten sposób żaden SQL nie może być wstrzykiwany za pomocą parametru. Innym korzystnym efektem ubocznym Preparedstattements (prekompilacja + wysyłanie tylko parametrów) jest poprawa wydajności podczas wielokrotnego uruchamiania instrukcji nawet z różnymi wartościami parametrów (zakładając, że driver obsługuje Preparedstattements) jako driver nie musi wykonywać parsowania i kompilacji SQL przy każdej zmianie parametrów.

 25
Author: Travis Heseman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-17 13:38:30

I zgaduję będzie to ciąg znaków. Ale parametry wejściowe zostaną wysłane do bazy danych i odpowiednie cast/konwersje zostaną zastosowane przed utworzeniem rzeczywistego polecenia SQL.

Aby dać ci przykład, może spróbować i sprawdzić, czy Obsada/Konwersja działa.
Jeśli to zadziała, może stworzyć z tego ostateczne oświadczenie.

   SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))

Wypróbuj przykład z poleceniem SQL akceptującym parametr liczbowy.
Teraz spróbuj przekazać zmienną łańcuchową (z zawartością liczbową, która jest akceptowalny jako parametr liczbowy). Czy to wywołuje jakiś błąd?

Teraz spróbuj przekazać zmienną łańcuchową (z zawartością, która nie jest akceptowalna jako parametr liczbowy). Widzisz, co się dzieje?

 3
Author: shahkalpesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-17 13:33:12

Przygotowane oświadczenie jest bezpieczniejsze. Konwertuje parametr na określony typ.

Na przykład stmt.setString(1, user); przekonwertuje parametr user na łańcuch znaków.

Załóżmy, że parametr zawiera łańcuch SQL zawierający wykonywalne polecenie : użycie instrukcji prepared nie pozwoli na to.

Dodaje do tego metacharakter (A. K. a. Auto conversion).

To sprawia, że jest bardziej bezpieczny.
 3
Author: Guru R Handa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-15 16:05:54

Jak wyjaśniono w ten post , samo PreparedStatement nie pomoże ci, jeśli nadal łączysz Łańcuchy.

Na przykład jeden napastnik może nadal wykonać następujące czynności:

  • wywołaj funkcję uśpienia, aby wszystkie połączenia z bazą danych były zajęte, co sprawi, że Twoja aplikacja będzie niedostępna
  • wydobywanie wrażliwych danych z DB
  • omijanie uwierzytelniania użytkownika

Nie tylko SQL, ale nawet JPQL czy HQL może być skompromitowane, jeśli nie używasz parametrów bind.

Podsumowując, nigdy nie powinieneś używać konkatenacji łańcuchów podczas budowania poleceń SQL. W tym celu użyj dedykowanego API:

 1
Author: Vlad Mihalcea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-05 19:31:16

SQL injection: gdy użytkownik ma szansę wprowadzić coś, co może być częścią instrukcji sql

Na przykład:

String query = " INSERT INTO students VALUES ('"+user+"') "

Gdy użytkownik wprowadza "Robert"); DROP TABLE; - " jako wejście powoduje SQL injection

Jak przygotowane oświadczenie temu zapobiega?

String query = "INSERT INTO students VALUES('" + ":name"+"') "

Parametry.addValue ("nazwa", użytkownik);

= > gdy użytkownik input again "Robert'); DROP TABLE students– -", łańcuch wejściowy jest wstępnie skompilowany na sterowniku jako wartości dosłowne i myślę, że może być rzucony w następujący sposób:

CAST ('Robert'); DROP TABLE students; – ' AS varchar(30))

Tak więc na końcu łańcuch zostanie dosłownie wstawiony jako nazwa do tabeli.

Http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/

 1
Author: jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 14:05:55

PreparedStatement:

1) Prekompilacja i buforowanie po stronie DB instrukcji SQL prowadzi do szybszego wykonania i możliwości ponownego użycia tego samego polecenia SQL w partiach.

2) Automatyczne zapobieganie atakom SQL injection poprzez wbudowane ucieczki cudzysłowów i innych znaków specjalnych. Zauważ, że wymaga to użycia jednej z metod PreparedStatement setXxx () do ustawienia wartości.

 0
Author: Mukesh Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-18 11:29:18