Narzędzia osobiste
Start > Aktualności > Security blog > SQLi- mit bezpiecznych procedur

SQLi- mit bezpiecznych procedur

Czy Ty jesteś bezpieczny? Przed czym należy się bronić?

O SQL Injection można znaleźć w Internecie wiele materiałów, zakładam więc, że czytelnik ma już podstawową wiedzę z tego zakresu, a mianowicie wie:

- co znaczy zwrot SQL Injection

- jak manipulować danymi w bazie danych za pomocą zapytań SQL przemycanych w przekazywanych danych wejściowych.

Jeżeli terminologia nie jest jeszcze znana, polecam zapoznanie się z tematyką: http://www.owasp.org/index.php/SQL_injection, http://www.owasp.org/index.php/Guide_to_SQL_Injection, http://www.governmentsecurity.org/articles/SQLinjectionBasicTutorial.php).
Szczególnie polecam strony OWASP, ponieważ nie powielają one mitu, o którym będę pisał poniżej, a który jest powielany  na wielu forach, blogach itp.

Mit, którym chciałbym się zająć, jest o tyle niebezpieczny, że daje pozorne poczucie bezpieczeństwa, a jednocześnie jest ukrytą miną, na którą ktoś wcześniej, czy później trafi. Tyle, że w tym przypadku ofiarą będzie umieszczający tę minę.

Mit ten brzmi: „korzystanie ze Stored Procedures zabezpiecza przed SQL Injection”.

Dla wielu programistów jest oczywiste, że najlepszym zabezpieczeniem przed SQL Injection jest skorzystanie z używanych w większości serwerów bazodanowych procedur przechowywanych w bazie danych, wywoływanych z parametrami, przekazywanymi przez klienta wywołującego procedurę. Jest to prawda w 50% (a więc nie jest to prawda), ponieważ błędnie napisana procedura może się okazać równie niebezpieczna, co konkatenowany skrypt SQL zaszyty w kodzie aplikacji. Może nawet bardziej niebezpieczna, ponieważ zapytanie generowane dynamicznie w kodzie, w przeciwieństwie do procedury, nie sprawia wrażenia bezpiecznego.

W przykładzie posłużę się procedurami składowanymi (stored procedures) oferowanymi przez SQL Server.

Załóżmy, że mamy w bazie danych tabelę AppUsers:

 

 

 

Tabela przechowuje dane użytkowników naszej aplikacji. Jedno z pól (pole IsAdmin) informuje, czy użytkownik jest administratorem. Na podstawie flagi ustawionej w tym polu aplikacja daje dostęp do panelu administracyjnego, w którym zalogowany użytkownik może zarządzać aplikacją, użytkownikami, uprawnieniami itp.

W części publicznej aplikacji mamy jakąś listę użytkowników, którą można przeszukiwać. Dla uproszczenia przykładu przyjmijmy, że będzie to wyszukiwanie według loginu użytkownika. W sytuacji, kiedy w filtrze wyszukiwania nie zostaną wprowadzone żadne dane, wówczas prezentowana jest lista wszystkich użytkowników. W przeciwnym razie w bazie będą wyszukiwani użytkownicy, których login zawiera litery podane w zapytaniu. Programista w tej sytuacji postanawia skorzystać z procedury SQL, ponieważ jest przekonany, że to zabezpieczy go przed problemem SQL Injection. Umieszcza więc w bazie danych procedurę:

CREATE PROCEDURE [dbo].[USP_UsersSearchSafe]

@username varchar(400) = NULL

AS

DECLARE @sql nvarchar(4000)

SET @sql = ' SELECT Id, Username, IsAdmin, LastLogon ' +

              ' FROM AppUsers '

IF @username IS NOT NULL

   SET @sql = @sql + ' Where Username LIKE '''+ @username +''''

Exec (@sql)


Wydaje się, że wszystko jest bezpieczne, ponieważ skorzystał z procedury, natomiast teraz wyobraźmy sobie, że w polu tekstowym użytkownik o loginie „user1” wprowadzi poniższy kod SQL:

';update AppUsers set IsAdmin=1 where Username='user1';--

Po przesłaniu powyższego zapytania do mechanizmu wyszukiwawczego, nasz mechanizm wyszukiwawczy „w promocji” dorzuca użytkownikowi „user1” uprawnienia administratora. Gdyby zapytanie było wykonywane 6 grudnia, można by zrezygnować z klauzuli „where” i wówczas wszyscy użytkownicy w prezencie mikołajkowym dostaliby administracyjne uprawnienia.

Nie trzeba wyrafinowanej analizy, żeby odkryć, co jest przyczyną podatności na SQL Injection, mimo zastosowania procedury SQL.

W powyższym przykładzie procedura została napisana dokładnie w taki sam sposób, w jaki byłaby ona zapisana, gdyby programista zaszył ją wewnątrz kodu aplikacji, tzn. zapytanie SQL jest konkatenowane i ewaluowane , natomiast sam przekazany parametr nie jest odseparowany od logiki zapytania. Zapytanie to nie różni się zbytnio od zapytań typu:

„Select * from products where Id=” + Input[„id”]

Przy korzystaniu z procedur SQL ważne jest, żeby uświadomić sobie, że przez zagrożeniami nie chroni sam fakt skorzystania z procedury. Przed wszelkiego rodzaju problemami chroni tylko DOBRZE NAPISANY KOD, niezależnie od tego, czy znajduje się on w aplikacji, czy też w bazie danych.

Przejdźmy więc do tego mitycznego stworzenia o nazwie DOBRZE NAPISANY KOD. Jak powinien wyglądać w naszym przykładzie, żeby wyeliminować podatność na SQL Injection.

CREATE PROCEDURE [dbo].[USP_UsersSearchReallySafe]

@username varchar(400) = NULL AS

DECLARE @sql nvarchar(4000)

SET @sql = ' SELECT Id, Username, IsAdmin, LastLogon ' +

              ' FROM AppUsers '

IF @username IS NOT NULL

   SET @sql = @sql + ' Where Username LIKE @username '

Exec sp_executesql @sql, N'@username varchar(400)',@username

 

Na czym więc polega różnica. Otóż w tym przypadku skorzystaliśmy możliwości oferowanych przez zapytania parametryzowane, dzięki czemu parametry przekazywane do zapytania SQL (dane wejściowe) zostały całkowicie odseparowane od składni zapytania. Jedyną niedogodnością jest, że w tym przypadku wywołanie przygotowanego zapytania SQL jest trochę bardziej skomplikowane, ponieważ musimy skorzystać ze specjalnej procedury sp_executesql, a także musimy jeszcze raz przekazać parametry do tej procedury. W tym przypadku jednak dużo bardziej przejrzyste jest przygotowanie samego zapytania SQL, dlatego w sumie wychodzimy na remis. Z tą różnicą, że w tym drugim przypadku mamy naprawdę bezpieczną procedurę.

Jaką konkluzję chciałbym więc zawrzeć w podsumowaniu? Chyba taką, że nawet „the best practice” może być przyczyną problemów, jeżeli będzie zastosowana bezrefleksyjnie...

I że ŹLE NAPISANY KOD zawsze jest zagrożeniem, niezależnie od tego, gdzie został umieszczony.

rusk


Produkty
  • eProcurement
    (PDF 438 kb)

    Elektroniczny Obieg Wniosków Zakupowych
  • more:portal
    (PDF 0,5 MB)

    Kompetencje oraz doświadczenia WebService w zakresie wdrażania portali korporacyjnych.
  • more:arena
    (PDF 1,7 MB)

    Aplikacja do prowadzenia zaawansowanych negocjacji z klientem oraz do planowania sprzedaży.
  • Portal Absolwent
    (PDF 1,87 MB)

    System dla Biur Karier, przeznaczony do komunikacji pomiędzy Uczelniami, Pracodawcami oraz Studentami i Absolwentami.