it-swarm.dev

Czy procedury przechowywane zapobiegają iniekcji SQL?

Czy to prawda, że ​​procedury przechowywane zapobiegają atakom typu SQL injection na bazy danych PostgreSQL? Zrobiłem trochę badań i odkryłem, że SQL Server, Oracle i MySQL nie są bezpieczne przed iniekcją SQL, nawet jeśli używamy tylko procedur przechowywanych. Jednak ten problem nie występuje w PostgreSQL.

Czy implementacja procedury składowanej w rdzeniu PostgreSQL zapobiega atakom typu SQL injection, czy jest to coś innego? Czy też PostgreSQL jest również podatny na wstrzykiwanie SQL, nawet jeśli używamy tylko procedur przechowywanych? Jeśli tak, pokaż mi przykład (np. Książka, witryna, papier itp.).

84
Am1rr3zA

Nie, procedury składowane nie zapobiegają iniekcji SQL. Oto rzeczywisty przykład (z aplikacji wewnętrznej stworzonej przeze mnie, gdzie pracuję) procedury składowanej, która niestety pozwala na wstrzyknięcie SQL:

Ten kod serwera SQL:

CREATE PROCEDURE [dbo].[sp_colunmName2]   
    @columnName as nvarchar(30),
    @type as nvarchar(30), 
    @searchText as nvarchar(30)           
AS
BEGIN
    DECLARE @SQLStatement NVARCHAR(4000)
    BEGIN
        SELECT @SQLStatement = 'select * from Stations where ' 
            + @columnName + ' ' + @type + ' ' + '''' + @searchText + '''' 
        EXEC(@SQLStatement)
    END      
END
GO

z grubsza odpowiada postgresowi:

CREATE or replace FUNCTION public.sp_colunmName2 (
    columnName  varchar(30),
    type varchar(30), 
    searchText  varchar(30) ) RETURNS SETOF stations LANGUAGE plpgsql            
AS
$$
DECLARE SQLStatement VARCHAR(4000);
BEGIN
    SQLStatement = 'select * from Stations where ' 
            || columnName || ' ' || type || ' ' || ''''|| searchText || '''';
    RETURN QUERY EXECUTE  SQLStatement;
END
$$;

Pomysł dewelopera polegał na stworzeniu wszechstronnej procedury wyszukiwania, ale wynik jest taki, że klauzula WHERE może zawierać wszystko, czego chce użytkownik, umożliwiając wizytę z małe tabele Bobby'ego .

To, czy używasz instrukcji SQL, czy procedury przechowywanej, nie ma znaczenia. Liczy się to, czy Twój SQL używa parametrów lub połączonych ciągów. Parametry zapobiegają iniekcji SQL; połączone łańcuchy umożliwiają wstrzyknięcie SQL.

71
Kyralessa

Ataki typu SQL-Injection to takie, w których niezaufane dane wejściowe są bezpośrednio dołączane do zapytań, umożliwiając użytkownikowi skuteczne wykonanie dowolnego kodu, jak pokazano na ten kanoniczny komiks XKCD.

W ten sposób otrzymujemy sytuację:

 userInput = getFromHTML # „Robert ') Usuń uczniów z tabeli; -„ 
 
 Zapytanie = „Wybierz * spośród studentów, gdzie studentName =” + userInput 

Procedury przechowywane są ogólnie dobrą ochroną przed atakami iniekcyjnymi SQL , ponieważ przychodzące parametry nigdy nie są analizowane.

W procedurze przechowywanej w większości baz danych (i programów nie zapominaj, że wstępnie skompilowane zapytania liczą się jako procedury składowane) wyglądają następująco:

 
 
 utwórz Zapisaną procedurę proo (
 wybierz * spośród studentów, gdzie studentName =: 1 
); 
 

Następnie, gdy program chce uzyskać dostęp, wywołuje foo(userInput) i szczęśliwie pobiera wynik.

Procedura przechowywana nie jest magiczną obroną przed SQL-Injection, ponieważ ludzie są w stanie pisać złe procedury przechowywane. Jednak wstępnie skompilowane zapytania, niezależnie od tego, czy są przechowywane w bazie danych, czy w programie, są znacznie trudniejsze do otwarcia luk bezpieczeństwa (, jeśli rozumiesz, jak działa SQL-Injection.

Możesz przeczytać więcej o SQL-Injection:

46

Tak, do pewnego stopnia.
Same przechowywane procedury nie zapobiegną wstrzyknięciu SQL.

Pozwól mi najpierw zacytować o SQL Injection od OWASP

Atak polegający na wstrzyknięciu SQL polega na wstawieniu lub „wstrzyknięciu” zapytania SQL za pośrednictwem danych wejściowych od klienta do aplikacji. Udany exploit iniekcji SQL może odczytywać poufne dane z bazy danych, modyfikować dane bazy danych (Wstaw/Aktualizuj/Usuń), wykonywać operacje administracyjne na bazie danych (takie jak zamknięcie DBMS), odzyskać zawartość danego pliku obecnego w pliku DBMS system, aw niektórych przypadkach wydaje polecenia do systemu operacyjnego. Ataki polegające na wstrzykiwaniu SQL są rodzajem ataku polegającego na wstrzykiwaniu, w którym polecenia SQL są wstrzykiwane do danych wejściowych płaszczyzny danych w celu wykonania określonych poleceń SQL.

Musisz oczyścić dane wejściowe użytkownika i nie łączyć instrukcji SQL, nawet jeśli używasz procedury składowanej.

Jeff Attwood wyjaśnił konsekwencje łączenia sql w „ Daj mi sparametryzowany SQL lub daj mi śmierć

Poniżej znajduje się ciekawa kreskówka, która przychodzi mi na myśl, gdy słyszę SQL Injection alt text Myślę, że masz rację :-)

Spójrz na SQL Injection Prevention Cheat Sheet , metody zapobiegania są starannie wyjaśnione ...

29
CoderHawk

Łączenie ciągów jest przyczyną wstrzyknięcia SQL. Można tego uniknąć za pomocą parametryzacji.

Procedury przechowywane dodają dodatkową warstwę bezpieczeństwa, wymuszając niepoprawną składnię podczas konkatenacji, ale nie są „bezpieczniejsze”, jeśli użyjesz w nich, na przykład, dynamicznego SQL.

Tak więc powyższy kod jest spowodowany przez konkatenację tych ciągów

  • exec sp_GetUser '
  • x' AND 1=(SELECT COUNT(*) FROM Client); --
  • ' , '
  • monkey
  • '

Daje to niepoprawną składnię, na szczęście

Parametryzacja dałaby

exec sp_GetUser 'x'' AND 1=(SELECT COUNT(*) FROM Client); --' , 'monkey'

To znaczy

  • @UserName = x' AND 1=(SELECT COUNT(*) FROM Client); --
  • @Password = monkey

Teraz w powyższym kodzie nie będzie żadnych wierszy, ponieważ zakładam, że nie masz użytkownika x' AND 1=(SELECT COUNT(*) FROM Client); --

Jeśli przechowywany proc wyglądał tak (używając konkatenowanego dynamicznego SQL ), to sparametryzowane przechowywane wywołanie proc nadal pozwoli na wstrzyknięcie SQL

...
SET @sql = 'SELECT userName from users where userName = ''' + 
               @UserName + 
               ''' and userPass = ''' +
               @Password +
               ''''
EXEC (@sql)
....

Tak więc, jak pokazano, konkatenacja łańcuchów jest głównym wrogiem dla wstrzykiwania SQL

Procedury przechowywane dodają enkapsulację, obsługę transakcji, zmniejszone uprawnienia itp., Ale nadal mogą być nadużywane do iniekcji SQL.

Możesz sprawdzić Przepełnienie stosu, aby uzyskać więcej informacji na temat parametryzacja

12
gbn

„Ataki typu SQL injection mają miejsce, gdy dane wejściowe użytkownika jest nieprawidłowo zakodowane. Zazwyczaj dane wejściowe użytkownika to niektóre dane wysyłane przez użytkownika za pomocą zapytania, tj. Wartości w $_GET, $_POST, $_COOKIE, $_REQUEST lub $_SERVER tablice. Jednak dane wejściowe użytkownika mogą również pochodzić z wielu innych źródeł, takich jak gniazda, zdalne strony internetowe, pliki itp. Dlatego naprawdę powinieneś traktować wszystko oprócz stałych (lubić 'foobar') jako dane wejściowe użytkownika . "

Niedawno dokładnie badałem ten temat i chciałbym podzielić się z innymi dość interesującym materiałem, dzięki czemu ten post jest bardziej kompletny i pouczający dla wszystkich.



Z YouTube


Z Wikipedii


Z OWASP


Od PHP Podręcznik


Od Microsoft i Oracle


Przepełnienie stosu


Skaner iniekcji SQL

10
Ilia Rostovtsev

Procedury przechowywane nie magicznie zapobiegają iniekcji SQL, ale znacznie ułatwiają zapobieganie. Wszystko, co musisz zrobić, to coś takiego (przykład Postgres):

CREATE OR REPLACE FUNCTION my_func (
  IN in_user_id INT 
)
[snip]
  SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]

Otóż ​​to! Problem pojawia się tylko podczas tworzenia zapytania poprzez konkatenację ciągów (tj. Dynamiczny SQL), a nawet w takich przypadkach możesz być w stanie powiązać! (Zależy od bazy danych.)

Jak uniknąć wstrzyknięcia SQL w zapytaniu dynamicznym:

Krok 1) Zadaj sobie pytanie, czy naprawdę potrzebujesz dynamicznego zapytania. Jeśli sklejasz ciągi znaków, aby ustawić dane wejściowe, prawdopodobnie robisz to źle. (Istnieją wyjątki od tej reguły - jeden wyjątek dotyczy raportowania zapytań w niektórych bazach danych, możesz mieć problemy z wydajnością, jeśli nie zmusisz go do kompilacji nowego zapytania przy każdym wykonaniu. Ale zbadaj ten problem, zanim w niego wejdziesz. )

Krok 2) Zbadaj właściwy sposób ustawienia zmiennej dla określonego RDBMS. Na przykład Oracle pozwala wykonać następujące czynności (cytowanie z ich dokumentów):

sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE ' 
           || v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!

Tutaj nadal nie łączysz danych wejściowych. Jesteś bezpiecznie wiążący! Brawo!

Jeśli twoja baza danych nie obsługuje czegoś takiego jak powyższe (mam nadzieję, że żadna z nich nie jest jeszcze taka zła, ale nie byłbym zaskoczony) - lub jeśli nadal naprawdę musisz połączyć swoje dane wejściowe (jak w przypadku „czasami” zgłaszania zapytań jako Wskazałem powyżej), musisz użyć właściwej funkcji ucieczki. Nie pisz tego sam. Na przykład postgres udostępnia funkcję quote_literal (). Więc biegniesz:

sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);

W ten sposób, jeśli in_name jest czymś przebiegłym, np. „[Snip] lub 1 = 1” (część „lub 1 = 1” oznacza zaznaczenie wszystkich wierszy, pozwalając użytkownikowi zobaczyć pensje, których nie powinien!), To quote_literal zapisuje tyłek przez utworzenie wynikowego ciągu:

SELECT salary FROM employees WHERE name = '[snip] or 1=1'

Nie zostaną znalezione żadne wyniki (chyba że masz pracowników o naprawdę dziwnych nazwiskach).

To jest sedno tego! Teraz pozwólcie, że zostawię wam link do klasycznego postu autorstwa guru Oracle, Toma Kyte'a, na temat SQL Injection, aby doprowadzić do sedna sprawy: Linky

2
MWDB