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, strona, papier itp.).
postgresql
security
sql-injection
Am1rr3zA
źródło
źródło
Odpowiedzi:
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:
mniej więcej odpowiednik postgresu:
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 odwiedziny z niewielkich tabel 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.
źródło
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 w tym kanonicznym komiksie XKCD.
W ten sposób otrzymujemy sytuację:
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:
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 zrozumiesz, jak działa SQL-Injection.
Możesz przeczytać więcej o SQL-Injection:
źródło
Tak, do pewnego stopnia.
Same przechowywane procedury nie zapobiegną wstrzyknięciu SQL.
Pozwól mi najpierw zacytować O SQL Injection z OWASP
Musisz oczyścić dane wejściowe użytkownika i nie łączyć instrukcji SQL, nawet jeśli korzystasz z procedury składowanej.
Jeff Attwood wyjaśnił konsekwencje konkatenacji sql w „ Daj mi sparametryzowany SQL lub daj mi śmierć ”
Oto ciekawa kreskówka, która przychodzi mi do głowy, gdy słyszę SQL Injection. Myślę, że masz rację :-)
Zajrzyj do ściągawki SQL Injection Prevention Cheat Sheet , metody zapobiegania są starannie wyjaśnione ...
źródło
Łą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 łączeniem tych ciągów
exec sp_GetUser '
x' AND 1=(SELECT COUNT(*) FROM Client); --
' , '
monkey
'
Na szczęście daje to niepoprawną składnię
Parametryzacja dałaby
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 (przy użyciu skonkatowanego dynamicznego SQL ), wówczas sparametryzowane przechowywane wywołanie proc nadal pozwoli na wstrzyknięcie SQL
Tak więc, jak wykazano, 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 wstrzykiwania SQL.
Możesz sprawdzić Przepełnienie stosu, aby uzyskać więcej informacji na temat parametryzacji
źródło
„Ataki SQL injection zdarzyć, gdy dane wejściowe użytkownika jest niewłaściwie zakodowany. Zazwyczaj wejście użytkownik niektóre dane użytkownik wysyła ze swojego zapytania, czyli wartości w
$_GET
,$_POST
,$_COOKIE
,$_REQUEST
, lub$_SERVER
tablic. Jednak wejście użytkownik może również pochodzić z różnych innych źródła, takie jak gniazda, zdalne strony internetowe, pliki itp. Dlatego naprawdę powinieneś traktować wszystko oprócz stałych (jak'foobar'
) jako dane wprowadzane przez 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
Od OWASP
Z podręcznika PHP
Od Microsoft i Oracle
Przepełnienie stosu
Skaner wtrysku SQL
źródło
Procedury przechowywane nie magicznie zapobiegają iniekcji SQL, ale znacznie ułatwiają zapobieganie. Wszystko co musisz zrobić, to coś takiego (przykład Postgres):
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ąć wstrzykiwania 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):
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:
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:
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 guru Oracle, Toma Kyte'a na temat SQL Injection, aby doprowadzić do sedna sprawy: Linky
źródło
quote_ident()
- ale generalnie najłatwiejszym sposobem napisania odpornego na wstrzyknięcia dynamicznego SQL jest użycieformat()
i użycie symboli zastępczych%I
dla identyfikatorów i%L
literałów. W ten sposób SQL jest znacznie bardziej czytelny niż odpowiednik używający wersji||
iquote_....()
funkcji