Jak? Parametry i instrukcja LIKE SQL

80

Piszę funkcję wyszukiwania i wymyśliłem to zapytanie przy użyciu parametrów, aby zapobiec lub przynajmniej ograniczyć ataki typu SQL injection. Jednak gdy uruchamiam go przez mój program, nic nie zwraca:

SELECT * FROM compliance_corner WHERE (body LIKE '%@query%') OR (title LIKE '%@query%')

Czy można używać parametrów w ten sposób? czy też są ważne tylko w takim przypadku, jak:

SELECT * FROM compliance_corner WHERE body LIKE '%<string>%'(gdzie <string>jest obiekt wyszukiwania).

EDYCJA: Konstruuję tę funkcję w VB.NET, czy ma to wpływ na składnię, którą wnieśliście?

Uruchomiłem również tę instrukcję w SQL Server: SELECT * FROM compliance_corner WHERE (body LIKE '%max%') OR (title LIKE% max% ') `i zwraca wyniki.

Anders
źródło

Odpowiedzi:

78

Twój podstawowy kod wizualny wyglądałby mniej więcej tak:

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE '%' + @query + '%') OR (title LIKE '%' + @query + '%')")

cmd.Parameters.Add("@query", searchString)
Jan
źródło
3
Jak wskazał Adam w swojej odpowiedzi, nie chroni to przed wstrzyknięciem SQL. Zapytanie powinno być sparametryzowane.
DOK
6
Czy możesz podać przykład, w którym nie zapobiega to iniekcji SQL? Z moich testów działa dobrze
John
27
Nie jest otwarty do SQLwstrzyknięcia, tylko LIKEzastrzyk. Oznacza to, że użytkownik może wprowadzić znaki specjalne, takie jak % ^i, _które LIKEbędą specjalnie interpretowane. Oznacza to, że użytkownik może nie uzyskać tego, czego oczekuje w przypadku niektórych wyszukiwań. Na przykład wyszukiwanie 'less than 1% fat'może zwrócić wynik 'less than 1% of doctors recommend this - it's full of fat!'.
Alex Humphrey,
1
Zgadzam się, coś podobnego podlega zasadzie „Like Injection”, a szkoda polega tylko na tym, że użytkownik nie otrzymuje tego, czego oczekuje. Czyszczenie zapytań powinno być wykonywane przez cały czas, nawet jeśli jest sparametryzowana. Poleganie tylko na tej ochronie nie jest do końca bezpieczne.
Anthony Mason
1
searchString.Replace("[","[[]").Replace("%","[%]").Replace("_","[_]")Poleciłbym również zrobić , co pozwoli uniknąć iniekcji LIKE (o ile nie używasz klauzuli ucieczki).
8DX
114

Cóż, poszedłbym z:

 Dim cmd as New SqlCommand(
 "SELECT * FROM compliance_corner"_
  + " WHERE (body LIKE @query )"_ 
  + " OR (title LIKE @query)")

 cmd.Parameters.Add("@query", "%" +searchString +"%")
James Curran
źródło
To prawda, zaakceptowana odpowiedź udzielona przez Johna ma nieprawidłową składnię!
Adam
3
Nie jestem pewien, dlaczego jego składnia jest nieprawidłowa, jego rozwiązanie działało dobrze. Mam funkcję, która konstruuje i zwraca instrukcję SQL do użycia w datatable lub czymkolwiek innym.
Anders
1
Dodatkowa uwaga: składnia języka C # przy użyciu MySQLDataAdapter = da = new MySQLDataAdapter ("SELECT * FROM tableA WHERE fieldA = @fieldA"); da.SelectCommand.Parameters.AddWithValue ("@ fieldA", "%" + someValue + "%");
John M
3
Druga odpowiedź (od Johna) też działa, ale rzeczywiście jest podatna na podobne zastrzyki, które MOGĄ dać dziwne wyniki, w zależności od celu twojego pola.
Steven Lemmens
1
Nie powinno być cmd.Parameters.Addsię cmdLoad.Parameters.AddWithValueczy jest jakiś problem? Rozumiem, że odpowiedź Jamesa pochodzi z 2008 roku :)
WTFZane
26

musisz zrobić:

LIKE '%' + @param + '%'

Andrew Bullock
źródło
doskonałe rozwiązanie - dałoby więcej niż +1, jeśli to możliwe! Dzięki
BM,
2

Być może trzeba będzie połączyć znaki% z parametrem, np .:

LIKE '%' || @query || „%”

Edycja: Właściwie to może nie mieć żadnego sensu. Myślę, że mogłem źle zrozumieć twój problem.

Will Wagner
źródło
1

Czasami symbol używany jako symbol zastępczy %nie jest taki sam, jeśli wykonujesz zapytanie z VB, jak podczas wykonywania go z MS SQL / Access. Spróbuj zmienić symbol zastępczy z %na *. To może zadziałać.
Jeśli jednak debugujesz i chcesz skopiować ciąg SQL bezpośrednio w MS SQL lub Access, aby go przetestować, może być konieczna zmiana symbolu z powrotem na %w MS SQL lub Access, aby faktycznie zwracać wartości.

Mam nadzieję że to pomoże

Lalie
źródło
Nie wiem na pewno w 2012 roku, ale to% vs * jest specyficzne dla silników ADO vs DAO. Jeśli używasz DAO lub Current () w Access the Wildcard to *; jeśli używasz ADO z dowolnego kodu, w tym VBA wewnątrz Access, symbol wieloznaczny to%.
Marcelo Scofano Diniz
1

spróbuj też w ten sposób

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE CONCAT('%',@query,'%')  OR  title LIKE CONCAT('%',@query,'%') )")
cmd.Parameters.Add("@query", searchString)
cmd.ExecuteNonQuery()

Użyto Concat zamiast +

Ramgy Borja
źródło