Czy parametryzowane polecenie może zatrzymać wszystkie SQL injection?

Jeśli tak, dlaczego wciąż jest tak wiele udanych wstrzyknięć SQL? Tylko dlatego, że niektórzy programiści są zbyt głupi, aby używać sparametryzowanych instrukcji?

Author: kelunik, 2011-07-22

12 answers

Linki, które zamieściłem w komentarzach do pytania, bardzo dobrze wyjaśniają problem. Poniżej podsumowałem swoje odczucia na temat tego, dlaczego problem nadal występuje:

  1. Ci, którzy dopiero zaczynają, mogą nie mieć świadomości SQL injection.

  2. Niektórzy są świadomi SQL injection, ale uważają, że escaping jest (tylko?) rozwiązanie. Jeśli wykonasz szybkie wyszukiwanie w Google php mysql query, pierwsza pojawiająca się strona jest mysql_query strona, na której znajduje się przykład pokazujący interpolacja danych wejściowych użytkownika w zapytaniu. Nie ma wzmianki (przynajmniej nie widzę) o używaniu prepared statements zamiast. Jak powiedzieli inni, istnieje tak wiele samouczków, które używają interpolacji parametrów, że nie jest to naprawdę zaskakujące, jak często jest ona nadal używana.

  3. Brak zrozumienia działania instrukcji parametryzowanych. Niektórzy uważają, że jest to tylko wymyślny sposób ucieczki od wartości.

  4. Inni są świadomi parametryzacji wypowiedzi, ale nie używaj ich, ponieważ słyszeli, że są zbyt powolne. Podejrzewam, że wiele osób słyszało, jak bardzo powolne są sparamteryzowane wypowiedzi, ale nie przeprowadziło żadnych własnych testów. Jak zauważył Bill Karwin w swoim wystąpieniu, różnica w wydajności rzadko powinna być wykorzystywana jako czynnik przy rozważaniu wykorzystania przygotowanych wypowiedzi. Korzyści z przygotować raz, wykonać wiele, często wydają się być zapomniane, podobnie jak poprawa bezpieczeństwa i konserwacja kodu.

  5. Niektórzy używają sparametryzowanych instrukcji wszędzie, ale z interpolacją niezaznaczonych wartości, takich jak nazwy tabel i kolumn, słowa kluczowe i operatory warunkowe. Dynamiczne wyszukiwania, takie jak te, które pozwalają użytkownikom określić wiele różnych pól wyszukiwania, Warunki porównania i kolejność sortowania, są tego doskonałym przykładem.

  6. Fałszywe poczucie bezpieczeństwa podczas korzystania z ORM. ORMs nadal umożliwia interpolację części instrukcji SQL-zobacz 5.

  7. Programowanie to duży i złożony temat, Zarządzanie bazami danych to duży i złożony temat, bezpieczeństwo to duży i złożony temat. Opracowanie bezpiecznej aplikacji bazodanowej nie jest łatwe - nawet doświadczeni programiści mogą zostać Przyłapani.

  8. Wiele odpowiedzi na stackoverflow nie pomaga. Kiedy ludzie piszą pytania, które używają dynamicznego sql i interpolacji parametrów, często brakuje odpowiedzi sugerujących użycie sparametryzowanych wyrażeń. On kilka razy miałem ludzi, którzy odrzucili moją sugestię, aby użyć gotowych wypowiedzi-zwykle z powodu postrzeganej niedopuszczalnej wydajności. Poważnie wątpię, że ci, którzy zadają większość z tych pytań, są w sytuacji, w której dodatkowe kilka milisekund potrzebnych do przygotowania sparametryzowanego Oświadczenia będzie miało katastrofalny wpływ na ich zastosowanie.

 53
Author: Mike,
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
2011-09-05 17:09:04

Kiedy artykuły mówią o parametryzowanych zapytaniach zatrzymujących ataki SQL, nie wyjaśniają naprawdę dlaczego, często jest to przypadek "tak, więc nie pytaj dlaczego" -- prawdopodobnie dlatego, że nie znają siebie. Pewnym znakiem złego wychowawcy jest taki, który nie może przyznać, że czegoś nie wie. Ale dygresję. Kiedy mówię, że to całkowicie zrozumiałe być zdezorientowanym, jest proste. Wyobraź sobie dynamiczne zapytanie SQL

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password

Więc proste SQL injection byłoby po prostu umieścić nazwę Użytkownika jako ' lub 1=1-- To skutecznie zrobi zapytanie sql:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password

To mówi select all customers where they ' re username is blank (") or 1=1, which is a boolean, Equatorial to true. Następnie używa -- do komentowania reszty zapytania. Więc to po prostu wydrukować całą tabelę klienta, lub zrobić, co chcesz z nim, jeśli logowania, to loguje się z uprawnieniami pierwszego użytkownika, który często może być administratorem.

Teraz parametryzowane zapytania robią to inaczej, z kodem like:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'

parameters.add("User", username)
parameters.add("Pass", password)

Gdzie nazwa użytkownika i hasło są zmiennymi wskazującymi na skojarzoną nazwę użytkownika i hasło

W tym momencie możecie myśleć, że to niczego nie zmienia. Z pewnością możesz jeszcze wpisać w pole username coś takiego jak nikt lub 1=1'--, skutecznie wykonując zapytanie:
sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

I to wydaje się być słusznym argumentem. Ale myliłbyś się.

Sposób działania zapytań parametryzowanych polega na tym, że zapytanie SQL jest wysyłane jako zapytanie, a baza danych wie dokładnie, co to zapytanie zrobi, i dopiero wtedy wstawi nazwę użytkownika i hasła tylko jako wartości. Oznacza to, że nie mogą wykonać zapytania, ponieważ baza danych już wie, co zrobi zapytanie. Tak więc w tym przypadku szukałby nazwy użytkownika "Nikt lub 1=1' -- " i pustego hasła, które powinno być fałszywe.

Nie jest to jednak kompletne rozwiązanie, a walidacja danych wejściowych nadal będzie musiała zostać wykonana, ponieważ nie spowoduje to innych problemów, takich jak jak XSS atakuje, jak można jeszcze umieścić javascript w bazie danych. Następnie, jeśli zostanie to odczytane na stronie, wyświetli to jako normalny javascript, w zależności od dowolnej walidacji wyjściowej. Tak naprawdę najlepszą rzeczą do zrobienia jest nadal używać walidacji danych wejściowych, ale używając parametryzowanych zapytań lub procedur składowanych, aby zatrzymać wszelkie ataki SQL.

 34
Author: Josip Ivic,
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-10-09 08:34:44

Dobre pytanie. Odpowiedź jest bardziej stochastyczna niż deterministyczna i postaram się wyjaśnić mój pogląd, używając małego przykładu.

Istnieje wiele referencji w sieci, które sugerują nam użycie parametrów w naszych zapytaniach lub użycie procedury składowanej z parametrami w celu uniknięcia SQL Injection (SQLi). Pokażę Ci, że procedury przechowywane (na przykład) nie są magicznym kijem przeciwko SQLi. Odpowiedzialność nadal spoczywa na programistach.

Rozważ następujący serwer SQL Procedura składowana pobierająca wiersz użytkownika z tabeli 'Users':

create procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
           'from Users '+
           'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
execute(@sql)

Możesz uzyskać wyniki, podając jako parametry nazwę użytkownika i hasło. Załóżmy, że hasło jest w dowolnym tekście (dla uproszczenia tego przykładu), normalne wywołanie będzie brzmiało:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [dbo].[getUser] 
   @name = 'admin'
  ,@pass = '!@Th1siSTheP@ssw0rd!!'
GO

Ale tutaj mamy złą technikę programowania używaną przez programistę wewnątrz procedury składowanej, więc atakujący może wykonać następujące czynności:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [TestDB].[dbo].[getUser] 
   @name = 'admin'
  ,@pass = 'any'' OR 1=1 --'
GO

Powyższe parametry zostaną przekazane jako argumenty do procedura składowana i polecenie SQL, które zostanie ostatecznie wykonane to:

select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'

..które zwróci wszystkie wiersze od użytkowników

Problem polega na tym, że nawet my kierujemy się zasadą "Create a stored procedure and pass the fields to search as parameters". Dzieje się tak dlatego, że po prostu kopiujemy naszą złą praktykę programowania wewnątrz procedury składowanej. Rozwiązaniem problemu jest przepisanie naszej procedury składowanej w następujący sposób:

alter procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = @name and usrPass = @pass

What I am trying to powiedzmy, że programiści muszą najpierw dowiedzieć się, czym jest atak SQLi i jak można go wykonać, a następnie odpowiednio zabezpieczyć swój kod. Ślepe przestrzeganie "najlepszych praktyk" nie zawsze jest bezpieczniejszym sposobem... i może właśnie dlatego mamy tak wiele "najlepszych praktyk" - zawodzi!

 9
Author: Andreas Venieris,
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-10-10 20:10:13

Tak, użycie gotowych wyrażeń zatrzymuje wszystkie iniekcje SQL, przynajmniej teoretycznie. W praktyce sparametryzowane wyrażenia mogą nie być prawdziwymi, przygotowanymi wyrażeniami, np. PDO w PHP domyślnie emuluje je, więc jest to otwarte na atak typu edge case .

Jeśli używasz prawdziwych gotowych wypowiedzi, wszystko jest bezpieczne. Cóż, przynajmniej tak długo, jak nie połączysz niebezpiecznych SQL w zapytaniu jako reakcja na nie jest w stanie przygotować nazwy tabel na przykład.

Jeśli tak, to dlaczego czy nadal jest tak wiele udanych wstrzyknięć SQL? Tylko dlatego, że niektórzy programiści są zbyt głupi, aby używać sparametryzowanych instrukcji?

Tak, edukacja jest tu głównym punktem, a stare podstawy kodu. Wiele samouczków używa ucieczki, a tych nie można łatwo usunąć z sieci, niestety.

 5
Author: kelunik,
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-05-23 11:54:53

Unikam absolutów w programowaniu; zawsze jest wyjątek. Gorąco polecam procedury przechowywane i Obiekty poleceń. Większość mojego zaplecza jest z serwerem SQL, ale od czasu do czasu gram z MySql. Istnieje wiele zalet procedur przechowywanych, w tym buforowanych planów zapytań; tak, można to osiągnąć za pomocą parametrów i wbudowanego SQL, ale to otwiera więcej możliwości dla ataków iniekcyjnych i nie pomaga w oddzielaniu problemów. Dla mnie jest to również dużo łatwiejsze aby zabezpieczyć bazę danych, ponieważ moje aplikacje generalnie mają uprawnienia do wykonywania tylko dla wspomnianych procedur składowanych. Bez bezpośredniego dostępu do tabeli / widoku o wiele trudniej jest cokolwiek wstrzyknąć. Jeśli użytkownik aplikacji jest zagrożony, ma tylko uprawnienia do wykonania dokładnie tego, co zostało wcześniej zdefiniowane.

Moje dwa centy.
 3
Author: Derek,
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-10-14 16:17:23

Nie powiedziałbym "głupi".

Myślę, że tutoriale są problemem. Większość samouczków SQL, książek, cokolwiek wyjaśnia SQL z wartościami inlined, nie wspominając o parametrach bind w ogóle. Ludzie uczący się z tych samouczków nie mają szansy nauczyć się tego dobrze.

 2
Author: Markus Winand,
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
2011-07-22 05:37:38

Ponieważ większość kodu nie jest pisana z myślą o bezpieczeństwie i zarządzaniu, biorąc pod uwagę wybór między dodaniem funkcji (szczególnie czegoś widocznego, co można sprzedać) a bezpieczeństwem/stabilnością/niezawodnością (co jest znacznie trudniejsze do sprzedania), prawie zawsze wybierają te pierwsze. Bezpieczeństwo jest problemem tylko wtedy, gdy staje się problemem.

 2
Author: evil otto,
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
2011-07-22 06:10:20

Czy parametryzowane polecenie może zatrzymać wszystkie SQL injection?

Tak, o ile twój sterownik bazy danych oferuje symbol zastępczy dla każdego możliwego literału SQL. Większość gotowych sterowników instrukcji tego nie robi. powiedzmy, że nigdy nie znajdziesz symbolu zastępczego dla nazwy pola lub tablicy wartości. Co sprawi, że programista wróci do ręcznego dostosowywania zapytania, używając konkatenacji i ręcznego formatowania. z przewidywanym wynikiem.

Dlatego zrobiłem mój Mysql wrapper dla PHP, który obsługuje większość liter, które mogą być dodawane do zapytania dynamicznie, w tym tablice i identyfikatory.

Jeśli tak, dlaczego wciąż jest tak wiele udanych wstrzyknięć SQL? Tylko dlatego, że niektórzy programiści są zbyt głupi, aby używać sparametryzowanych instrukcji?

Jak widzisz, w rzeczywistości jest to po prostu niemożliwe, aby wszystkie Twoje zapytania zostały sparametryzowane, nawet jeśli nie jesteś głupi.

 2
Author: Your Common Sense,
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-10-10 05:48:04

Pierwsza moja odpowiedź na twoje pierwsze pytanie: tak, o ile wiem, używając parametryzowanych zapytań, zastrzyki SQL nie będą już możliwe. Jeśli chodzi o Twoje następujące pytania, nie jestem pewien i mogę tylko wyrazić swoją opinię na temat powodów:

Myślę, że łatwiej jest" po prostu " napisać ciąg zapytania SQL poprzez połączenie kilku różnych części (może nawet zależnych od logicznych kontroli) wraz z wartościami, które mają być wstawione. To tylko tworzenie zapytania i wykonywanie go. Kolejna zaleta czy możesz wydrukować (echo, output lub cokolwiek innego) ciąg zapytania sql, a następnie użyć tego ciągu do ręcznego zapytania do silnika bazy danych.

Podczas pracy z przygotowanymi wypowiedziami zawsze masz co najmniej jeden krok więcej: Musisz zbudować swoje zapytanie (w tym oczywiście parametry) Musisz przygotować zapytanie na serwerze Musisz powiązać parametry z rzeczywistymi wartościami, których chcesz użyć dla zapytania Musisz wykonać zapytanie.

To trochę więcej pracy (i nie tak proste do zaprogramowania) szczególnie dla niektórych "szybkich i brudnych" prac, które często okazują się bardzo długotrwałe...

Pozdrawiam,

Box

 2
Author: TomS,
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-10-14 13:44:57

Aby chronić swoją aplikację przed SQL injection, wykonaj następujące kroki:

Krok 1. Ogranicz wejście. Punkt 2. Użyj parametrów z procedurami składowanymi. Punkt 3. Użyj parametrów z dynamicznym SQL.

Zobacz http://msdn.microsoft.com/en-us/library/ff648339.aspx

 1
Author: Fahad Hussain,
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
2011-07-22 05:37:47

SQL injection jest podzbiorem większego problemu wtrysku kodu, gdzie Dane i Kod są dostarczane na tym samym kanale, a dane są mylone z kodem. Parametryzowane zapytania zapobiegają temu, tworząc zapytanie używając kontekstu o to, czym są dane, a czym jest kod.

W niektórych szczególnych przypadkach nie jest to wystarczające. W wielu Dbmsach możliwe jest dynamiczne wykonywanie SQL z procedurami składowanymi, wprowadzając wadę SQL injection na poziomie DBMS. Wywołanie takiego przechowywanego procedura wykorzystująca parametryzowane zapytania nie uniemożliwi użycia SQL injection w procedurze. Inny przykład można zobaczyć w ten post na blogu .

Częściej Programiści nieprawidłowo wykorzystują tę funkcjonalność. Zwykle kod wygląda mniej więcej tak po poprawnym wykonaniu:

db.parameterize_query("select foo from bar where baz = '?'", user_input)

Niektórzy programiści łączą ze sobą łańcuchy znaków, a następnie używają parametryzowanego zapytania, które w rzeczywistości nie czyni wspomnianego rozróżnienia danych / kodu, które zapewnia gwarancje bezpieczeństwa, których szukamy:

db.parameterize_query("select foo from bar where baz = '" + user_input + "'")

Prawidłowe użycie parametryzowanych zapytań zapewnia bardzo silną, ale nie nieprzenikalną ochronę przed atakami SQL injection.

 1
Author: Daniel Crowley,
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-06-21 16:45:50

Nawet jeśli przygotowane deklaracje są właściwie wykorzystywane w całej aplikacji internetowej kod, błędy SQL injection mogą nadal istnieć, jeśli komponenty kodu bazy danych konstruują zapytania od użytkowników w sposób niebezpieczny. Poniżej znajduje się przykład procedury składowanej, która jest podatna na SQL Wtrysk w parametrze @ name:

CREATE PROCEDURE show_current_orders
(@name varchar(400) = NULL)
AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
‘searchstring = ‘’’ + @name + ‘’’’;
EXEC (@sql)
GO

Nawet jeśli aplikacja przekazuje podaną przez użytkownika wartość name do przechowywanego procedura w sposób bezpieczny, sama procedura łączy to bezpośrednio do dynamiczne zapytanie i dlatego jest podatne.

 0
Author: Hadid Graphics,
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-08-15 17:18:10