2012-11-01 10 views
7

Ugryzł mój pierwszy błąd eskapcji sql (dawno już był spóźniony), gdy próbowałem wykonać poniższe zapytanie PostgreSQL z wartością zawierającą apostrof, np. O'Brien korzystając FreePascal i ŁazarzaCzy istnieje biblioteka do czyszczenia parametrów zapytań dla PostgreSQL lub SQL ogólnie dla FreePascal i Delphi?

SQL.Add(format('select * from zones where upper(zn_name) >= %s and upper(zn_name) < %s order by zn_name',[sQuote(zoneMin), sQuote(zoneMax)])); 

W kwerendzie powyżej SQuote to funkcja, która owija ciąg w apostrofach. Czy istnieje jakaś standardowa biblioteka do czyszczenia parametrów zapytań SQL dla Lazarus/FreePascal lub Delphi?

+0

Możesz użyć funkcji "QuotedStr" (spróbuj sql-inject that ...). – kobik

Odpowiedz

16

Twoja aplikacja jest narażona na poważną klasę problemów bezpieczeństwa o nazwie SQL injection. Zobacz http://bobby-tables.com/.

Pewnie, O'Brian powoduje błąd, ale co z ');DROP SCHEMA public;--? Lub ');DELETE FROM users;--? Pierwsza nie powinna zadziałać, ponieważ Twoja aplikacja powinna być nigdy nie być działać jako administrator lub użytkownik, który jest właścicielem tabel, ale niewielu projektantów aplikacji dokłada wszelkich starań, aby to zrobić i często uruchamia uprzywilejowanych użytkowników w produkcji. Druga będzie działać w większości aplikacji; spójrz na koniec postu, aby poznać szczegóły.

Najprostszym i najlepszym środkiem zapobiegawczym jest użycie parametryzowane oświadczenia* w bibliotece klienta. Zobacz this example dla Delpi:

To use a prepared statement, do something like this: 

query.SQL.Text := 'update people set name=:Name where id=:ID'; 
query.Prepare; 
query.ParamByName('Name').AsString := name; 
query.ParamByName('ID').AsInteger := id; 
query.ExecSQL; 

(nigdy nie używałem Delphi i ostatni pisał kod Pascal 1995; Ja tylko przytoczyć przykład podany).

Co teraz robisz, to interpolacja ciągów znaków parametrów. To jest bardzo niebezpieczne. Można to zrobić bezpiecznie tylko wtedy, gdy masz solidną funkcję dla , powołując się na literały SQL, która nie tylko huczy w cudzysłów na każdym końcu, ale także obsługuje inne ucieczki, podwaja podwojenie itp. Jest to podejście ostateczne; to jest zdecydowanie lepiej użyć sparametryzowanej instrukcji.


Oto rozszerzenie przykładu, który podałem powyżej. Powiedzieć robisz zupełnie zwyczajne wstawkę użytkownika przez nazwę użytkownika, gdzie „Fred” stanowi przykład wejście nazwa_użytkownika przez klienta:

INSERT INTO users (user_name) VALUES ('Fred'); 

Teraz niektóre nieprzyjemne osoba wysyła nazwę użytkownika ');DELETE FROM users;--. Nagle aplikacja jest uruchomiona:

INSERT INTO users (user_name) VALUES ('');DELETE FROM users;--'); 

który po rozwinięciu jest:

INSERT INTO users (user_name) VALUES (''); 
DELETE FROM users; 
--'); 

lub innymi słowy wkładkę, która wstawia ciąg pusty (choć może równie łatwo umieścić doskonale poprawną nazwę użytkownika) , a następnie instrukcja DELETE FROM users; - usunięcie wszystkich wierszy w users - następnie komentarz, który nic nie robi. Splat. Są twoje dane.


* Parametryzowane statemments są czasami błędnie określane jako sporządzanych sprawozdań.Jest to niepoprawne, ponieważ przygotowana instrukcja niekoniecznie jest sparametryzowana, a sparametryzowana instrukcja niekoniecznie jest przygotowywana. Zamieszanie powstało, ponieważ interfejsy baz danych wielu języków nie zapewniają sposobu na użycie sparametryzowanych instrukcji bez użycia gotowych instrukcji.

+2

Co więcej, podobny projekt bibliotek istnieje dla PHP (pierwsze kroki do opanowania) i wszystkich innych języków skryptowych. Rozwiązuje również problemy z ucieczką napisów, inną reprezentacją DATE i tym podobne. Parametry "dezynfekcji" są zastąpione przez ad hoc "ubogim człowiekiem" dla wyraźnego rozdzielenia parametrów. Jeśli zamiast tego zobaczysz czyjś kod z "sanitizacją", najprawdopodobniej nie dostał nowoczesnej biblioteki lub po prostu nie uzyskał bezpieczeństwa. –

+0

Zadałem to pytanie, ponieważ wiem, że jest to pole minowe nawet dla tych, którzy myślą, że mają problem z połączeniem. Wiem o sparametryzowanych zapytaniach, ale chcę wiedzieć, czy są one bezpieczne, że niektórzy bardziej kompetentni ludzie mogą ich oszukać. – vfclists

+2

@vfclists Właściwe użycie sparametryzowanych zapytań absolutnie zapobiegnie atakom SQL injection *, chyba że dynamiczny SQL zostanie wykonany w bazie danych *, powiedzmy przez instrukcję PL/pgSQL 'EXECUTE'. Jeśli używasz dynamicznego SQL w DB, musisz również zabezpieczyć się przed iniekcją SQL tam, ostrożnie używając specyfikatora formatów 'format'' 'I I' i 'WYKONAJ ... USING'. Zobacz tę wcześniejszą odpowiedź na ten problem: http://stackoverflow.com/a/12995424/398670. –

Powiązane problemy