Czy poleganie na sparametryzowanych zapytaniach jest jedynym sposobem ochrony przed wstrzyknięciem SQL?

13

Wszystko, co widziałem w przypadku ataków typu SQL injection, wydaje się sugerować, że sparametryzowane zapytania, szczególnie w procedurach przechowywanych, są jedynym sposobem ochrony przed takimi atakami. Podczas pracy (w średniowieczu) procedury składowane były postrzegane jako kiepska praktyka, głównie dlatego, że były postrzegane jako mniej konserwowalne; mniej testowalne; wysoce sprzężony; i zablokował system w jednym dostawcy; ( to pytanie obejmuje kilka innych powodów).

Chociaż kiedy pracowałem, projekty były praktycznie nieświadome możliwości takich ataków; przyjęto różne zasady w celu zabezpieczenia bazy danych przed różnego rodzaju uszkodzeniami. Reguły te można streścić jako:

  1. Żaden klient / aplikacja nie miała bezpośredniego dostępu do tabel bazy danych.
  2. Wszystkie dostępy do wszystkich tabel odbywały się za pośrednictwem widoków (a wszystkie aktualizacje tabel podstawowych dokonywano za pomocą wyzwalaczy).
  3. Wszystkie elementy danych miały określoną domenę.
  4. Żaden element danych nie mógł być zerowalny - miało to implikacje, które powodowały, że DBA od czasu do czasu zgrzytały zębami; ale został wymuszony.
  5. Role i uprawnienia zostały odpowiednio skonfigurowane - na przykład ograniczona rola dająca tylko widokom prawo do zmiany danych.

Czy zatem zestaw (wymuszonych) reguł takich jak ten (choć niekoniecznie ten konkretny zestaw) jest odpowiednią alternatywą dla sparametryzowanych zapytań w zapobieganiu atakom polegającym na wstrzykiwaniu SQL? Jeśli nie, dlaczego nie? Czy bazę danych można zabezpieczyć przed takimi atakami za pomocą (tylko) określonych środków bazy danych?

EDYTOWAĆ

Podkreślenie pytania zmieniło się nieznacznie w świetle pierwszych otrzymanych odpowiedzi. Pytanie podstawowe bez zmian.

EDYCJA 2

Podejście polegające na sparametryzowanych zapytaniach wydaje się być tylko peryferyjnym krokiem w obronie przed atakami na systemy. Wydaje mi się, że bardziej podstawowa obrona jest pożądana i może sprawić, że poleganie na takich zapytaniach nie będzie konieczne lub mniej krytyczne, nawet w celu obrony przed atakami iniekcyjnymi.

Podejście zawarte w moim pytaniu opierało się na „zbrojeniu” bazy danych i nie miałem pojęcia, czy jest to realna opcja. Dalsze badania sugerują, że istnieją takie podejścia. Znalazłem następujące źródła, które dostarczają wskazówek dla tego rodzaju podejścia:

http://database-programmer.blogspot.com

http://thehelsinkideclaration.blogspot.com

Główne cechy, które wziąłem z tych źródeł to:

  1. Rozbudowany słownik danych w połączeniu z rozbudowanym słownikiem danych bezpieczeństwa
  2. Generowanie wyzwalaczy, zapytań i ograniczeń ze słownika danych
  3. Minimalizuj kod i maksymalizuj dane

Chociaż dotychczasowe odpowiedzi są bardzo przydatne i wskazują na trudności wynikające z pominięcia sparametryzowanych zapytań, ostatecznie nie odpowiadają one na moje pierwotne pytanie (podkreślone teraz pogrubioną czcionką).

Chris Walton
źródło
Nie kupuję argumentów przeciwko procedurom przechowywanym. Po prostu nie są prawdziwe.
Konrad Rudolph
O co chodzi z wymogiem zerowania?
Mark Canlas
2
@Konrad Rudolph - Jeśli napiszesz aplikację na MySQL, a następnie zdecydujesz się na migrację do DB2, czy naprawdę uważasz, że procedury przechowywane będą kompatybilne? Podobnie jeśli chcesz przeprowadzić migrację do SQLLite? Załóżmy również, że zaktualizowałeś system operacyjny - jeśli twoje procedury składowane są skompilowane w C (które są w DB2), prawdopodobnie wszystkie będą wymagały ponownej kompilacji. Są to uzasadnione argumenty - nie absolutne, ale uzasadnione.
Matthew Flynn
@Matthew Duh. Właściwie myślałem o „sparametryzowanych zapytaniach”, czytając to i komentując to. Procedura składowana = cała inna historia.
Konrad Rudolph

Odpowiedzi:

25

Przechowywane procy nie chronią automatycznie przed wstrzyknięciem. A co z tym

CREATE PROC proc
  @id VARCHAR(5)
AS
BEGIN
  EXEC("SELECT * FROM Client WHERE ClientId = " + @id);
END

Korzystanie ze sparametryzowanych zapytań ochroni Cię przed wstrzyknięciem, niezależnie od tego, czy są one przetwarzane czy nie.

Craig
źródło
Dziękujemy za skupienie się na sparametryzowanych zapytaniach, a nie na procesach. Pytam jednak, czy bazę danych można chronić metodami innymi niż takie zapytania - w szczególności metodami ograniczonymi tylko do warstwy bazy danych.
Chris Walton
1
+1 Oprócz tego chciałbym stwierdzić, że przechowywane procy są w większości uważane za bezpieczne, ponieważ jest to jedyny sposób, aby uniemożliwić użytkownikom bezpośredni dostęp do tabel, jednocześnie zachowując sposób na odzyskanie danych. Jest to jedyny sposób na zapewnienie uprawnień opartych na wierszach i kolumnach, gdy użytkownik musi mieć bezpośredni dostęp do bazy danych ze swoim klientem bez żadnych pośrednich działań.
Falcon
2
@Chris - Myślę, że Craig mówi tutaj, że nie możesz zakładać, że procy faktycznie cię chronią. Być może nie jest to pełna odpowiedź, a raczej korekta założenia w tytule.
Jon Hopkins
@Jon - Zmieniłem tytuł pytania i wprowadziłem do niego kilka zmian w świetle poprawki Craiga. Nie wiedziałem o założeniu, które poczyniłem w pytaniu, dopóki nie zacząłem otrzymywać odpowiedzi.
Chris Walton
2
Aby wzmocnić to, co Craig pisze powyżej, patrz databasesecurity.com/dbsec/lateral-sql-injection.pdf , „Boczne wstrzyknięcie SQL: nowa klasa luk w zabezpieczeniach Oracle”
Bruce Ediger
11

Czy zatem zestaw (wymuszonych) zasad, takich jak ta, jest odpowiednią alternatywą dla procedur przechowywanych w zapobieganiu atakom typu SQL injection? Jeśli nie, dlaczego nie?

Nie, ponieważ nakładają raczej ciężką karę na programistów. Podział na przedmioty:

1. Żaden klient / aplikacja nie miała bezpośredniego dostępu do tabel bazy danych.

Użyj ról. Klienci powinni mieć dostęp do bazy danych tylko za pomocą ograniczonej roli, która ma tylko WYBIERZ, WSTAW, AKTUALIZUJ i USUŃ dostęp do tych tabel (i wierszy, jeśli to możliwe), do których potrzebuje dostępu. Jeśli chcesz się upewnić, że żaden klient nie może spamować ani usuwać wszystkich wpisów, użyj interfejsu API do modyfikacji danych.

2. Wszystkie dostępy do wszystkich tabel odbywały się poprzez widoki.

Może to być wszystko, od nieistotnych do ogromnych kosztów wydajności, w zależności od wydajności widoków. To niepotrzebna złożoność, która spowalnia rozwój. Użyj ról.

3. Wszystkie elementy danych miały określoną domenę.

Może być dużo pracy do utrzymania i prawdopodobnie powinien zostać znormalizowany w osobnej tabeli.

4. Żaden element danych nie mógł być zerowalny - miało to implikacje, które powodowały, że DBA czasami zgrzytały zębami; ale został wymuszony.

To po prostu źle. Jeśli programiści nie są w stanie sobie z tym poradzić NULL, masz duże problemy.

Czy bazę danych można zabezpieczyć przed takimi atakami za pomocą (tylko) określonych środków bazy danych?

Zdajesz nie potrzebują procedur przechowywanych, wystarczy użyć sparametryzowanych kwerend w funkcję, która wymyka się argumenty, takie jak pg_query_params . Oczywiście, jeśli twoja baza danych jest zapisywalna na całym świecie lub rola klienta ma pełny dostęp do wszystkiego, i tak masz problemy. Ktoś musi przyjść i zdać sobie sprawę z tego, co robi klient, a następnie ugotować klienta w pięć minut, który niszczy (lub gorzej, trucizny) twoją DB.

l0b0
źródło
1
Domena: en.wikipedia.org/wiki/Data_domain
Dan McGrath
+1 za role. W znacznym stopniu przyczyniają się do tego - nie uwzględniłem ról w moim pytaniu, ale były one częścią konfiguracji - w szczególności widokom przypisano ograniczoną rolę, taką jak sugerujesz klientom. Punkt brany pod uwagę przy wydajności wyświetleń. Domeny obejmowały testy walidacyjne - głównie zakresy i długości. Wasze komentarze na temat reguły zerowującej dane są o wiele bardziej uprzejme niż niektórzy o niej słyszeliśmy. Nie stwierdziłem wyraźnie, że uprawnienia zostaną odpowiednio skonfigurowane, chociaż takie było moje założenie.
Chris Walton
6

Nie jestem pewien, czy twoje zasady całkowicie cię chronią.

Pierwszy problem polega na tym, że twierdzisz, że są one egzekwowane, ale oprócz znacznego obciążenia, nigdy nie widziałem doskonałego egzekwowania.

Po drugie, czytam o nich, że takie reguły mogą utrudniać wykorzystywanie, ale nie zapobiegają. Na przykład brak bezpośredniego dostępu do tabel niewiele się zmienia, jeśli widoki umożliwiają dostęp do tych samych danych. Jeśli klient musi coś zrobić, widok musi to ułatwić, a jeśli widok to ułatwia, atakujący może wykorzystać tę samą funkcjonalność / dane.

Pamiętaj też, że nie chodzi tylko o aktualizację lub usuwanie danych. Częścią luki związanej z iniekcją SQL jest zbieranie informacji i dlatego nie obchodzi Cię, czy dane zostały przekazane z powrotem przez widok vCustomers lub leżącą u podstaw tabelę Klienci. Być może uchroniłeś się przed niektórymi słabościami, ale nie wszystkimi. Podobnie, jeśli aktualizacje mogą być dokonywane przez klienta, nawet jeśli za pomocą wyzwalaczy, wówczas można napisać SQL, aby uruchomić wyzwalacze i dokonać aktualizacji.

(Jeśli chodzi o wszystkie aktualizacje dokonywane za pomocą wyzwalaczy, powiem dwie rzeczy: (1) kiedy to przeczytałem, zrobiłem trochę mdłości w ustach i (b) nie lubisz procedur przechowywanych, ponieważ „ jest „mniej konserwowalny, mniej testowalny, wysoce sprzężony i zablokował system w jednym dostawcy”, ale używasz wyzwalaczy, o których można w zasadzie powiedzieć te same rzeczy.)

Wszystko czego potrzebujesz to jedna dziura, która pozwala na wykonanie instrukcji SQL (i nie widzę, aby żadna z tych reguł to uniemożliwiała), a atakujący jest w środku. Być może znajduje się za nimi bardzo nieintuicyjna baza danych, ale jeśli zostaną ustaleni, że to zrobi tylko spowalniaj je, a nie zatrzymuj).

Inną kwestią jest to, że dodajesz złożoność i (jak również ogólne koszty, które ją tworzą), złożoność prowadzi do dziur, które można wykorzystać.

Nie twierdzę, że nie można stworzyć takiego zestawu zasad - więcej, dlaczego miałbyś się przejmować? Wydają się bardziej kłopotliwe i mniej niezawodne niż stosowanie powszechnie akceptowanych metod zapobiegania tego rodzaju atakom.

Jon Hopkins
źródło
+1 za zrozumienie mojego rzeczywistego zapytania w świetle moich dorozumianych, nieświadomych założeń oraz za odpowiednią odpowiedź na nie. Jeśli chodzi o powód, dla którego można się niepokoić - pracuję nad projektem, w którym znaczna część kodu zostanie wygenerowana z odpowiedniego opisu architektury - a część tej architektury opisuje, jak generować procedury dostępu do bazy danych. Nadal pozostaje otwarte, jaki kształt będą miały te wygenerowane procedury.
Chris Walton