W rzeczywistości są dwa pytania w jednym. A pytanie z tytułu ma niewiele wspólnego z obawami wyrażonymi przez PO w późniejszych komentarzach.
Chociaż zdaję sobie sprawę, że dla PO liczy się ich konkretny przypadek, dla czytelników pochodzących z Google ważne jest, aby odpowiedzieć na bardziej ogólne pytanie, które można sformułować jako „czy konkatenacja jest tak samo bezpieczna jak przygotowane oświadczenia, jeśli upewnię się że każdy literał, który konkatenuję, jest bezpieczny? ”. Chciałbym więc skoncentrować się na tym ostatnim. A odpowiedź brzmi
Zdecydowanie nie.
Wyjaśnienie nie jest tak bezpośrednie, jak chciałaby większość czytelników, ale postaram się jak najlepiej.
Od dłuższego czasu zastanawiałem się nad tą sprawą, czego efektem był artykuł (choć oparty na środowisku PHP), w którym próbowałem wszystko podsumować. Przyszło mi do głowy, że kwestia ochrony przed wstrzyknięciem SQL często wymyka się niektórym pokrewnym, ale węższym tematom, takim jak ucieczka ciągów, rzutowanie typów i tym podobne. Chociaż niektóre środki można uznać za bezpieczne, gdy są podejmowane samodzielnie, nie ma systemu ani prostej zasady do przestrzegania. To sprawia, że jest to bardzo śliski grunt, zbytnio obciążający uwagę i doświadczenie programisty.
Kwestii iniekcji SQL nie można uprościć do kwestii konkretnego problemu składniowego. Jest szerszy niż zwykły myśleć programista. To także kwestia metodologiczna . Nie chodzi tylko o „Jakie konkretne formatowanie musimy zastosować”, ale także „ Jak to zrobić”.
(Z tego punktu widzenia artykuł Jona Skeeta cytowany w drugiej odpowiedzi radzi sobie raczej źle niż dobrze, ponieważ ponownie szuka dziury w jakimś skrajnym przypadku, koncentrując się na konkretnym problemie składniowym i nie rozwiązując problemu w całości).
Kiedy próbujesz rozwiązać kwestię ochrony nie jako całości, ale jako zestaw różnych problemów składniowych, napotykasz wiele problemów.
- lista możliwych opcji formatowania jest naprawdę ogromna. Oznacza to, że można łatwo przeoczyć niektóre. Lub zmylić je ( na przykład używając znaków ucieczki dla identyfikatora ).
- Konkatenacja oznacza, że wszystkie środki ochrony muszą być wykonywane przez programistę, a nie program. Sam ten problem prowadzi do kilku konsekwencji:
- takie formatowanie jest ręczne. Ręczny oznacza wyjątkowo podatny na błędy. Można po prostu zapomnieć o złożeniu wniosku.
- ponadto istnieje pokusa, aby przenieść procedury formatowania do jakiejś scentralizowanej funkcji, co jeszcze bardziej komplikuje sprawę i psuje dane, które nie trafią do bazy danych.
- gdy zaangażowanych jest więcej niż jeden programista, problemy mnożą się dziesięciokrotnie.
- kiedy używana jest konkatenacja, nie można od razu określić potencjalnie niebezpiecznego zapytania: wszystkie są potencjalnie niebezpieczne!
W przeciwieństwie do tego bałaganu, przygotowane wypowiedzi są rzeczywiście Świętym Graalem:
- można to wyrazić w postaci jednej prostej reguły, której łatwo przestrzegać.
- jest to środek zasadniczo nieodczuwalny, co oznacza, że deweloper nie może ingerować i, dobrowolnie lub niechętnie, zepsuć procesu.
- ochrona przed iniekcją jest tak naprawdę tylko efektem ubocznym przygotowanych instrukcji, których realnym celem jest wytworzenie zdania poprawnego składniowo. A poprawne składniowo stwierdzenie jest w 100% odporne na iniekcje. Jednak potrzebujemy, aby nasza składnia była poprawna pomimo możliwości wstrzyknięcia.
- jeśli jest używany dookoła, chroni aplikację niezależnie od doświadczenia programisty. Powiedzmy, jest coś, co nazywa się wtryskiem drugiego rzędu . I bardzo silne złudzenie, które brzmi „w celu ochrony, unikaj wszelkich danych wprowadzanych przez użytkownika ”. Połączone razem prowadzą do zastrzyku, jeśli deweloper ma swobodę decydowania, co należy chronić, a co nie.
(Myśląc dalej, odkryłem, że obecny zestaw symboli zastępczych nie wystarcza do zaspokojenia rzeczywistych potrzeb i musi zostać rozszerzony, zarówno w przypadku złożonych struktur danych, takich jak tablice, jak i nawet słów kluczowych lub identyfikatorów SQL, które czasami trzeba dodawać do zapytania również dynamicznie, ale programista jest nieuzbrojony w takim przypadku i zmuszony do powrotu do konkatenacji ciągów, ale to kwestia innego pytania).
Co ciekawe, kontrowersje związane z tym pytaniem wywołuje bardzo kontrowersyjny charakter Stack Overflow. Ideą serwisu jest wykorzystanie konkretnych pytań od użytkowników, którzy pytają bezpośrednio, aby osiągnąć cel, jakim jest posiadanie bazy odpowiedzi ogólnego przeznaczenia, odpowiedniej dla użytkowników pochodzących z wyszukiwania . Pomysł nie jest zły sam w sobie , ale zawodzi w takiej sytuacji: gdy użytkownik zadaje bardzo wąskie pytanie , szczególnie po to, aby uzyskać argument w sporze z kolegą (lub zdecydować, czy warto refaktoryzować kod). Podczas gdy większość doświadczonych uczestników próbuje napisać odpowiedź, mając na uwadze misję całego Stack Overflow, dzięki czemu ich odpowiedź jest dobra dla jak największej liczby czytelników, a nie tylko dla PO.