Bezpieczeństwo web (część 4) – SQL Injection I

W poprzednich wpisach zajęliśmy się mapowaniem zawartości strony. Na tym etapie, powinno być jasne, jakiego typu ataki potencjalnie mogą być wykonane na stronie.

SQL Injection wciąż jest jednym z najczęściej spotykanych ataków. Może wydawać się to dziwne, ale często programiści nie zdają sobie sprawy z zagrożenia albo po prostu luki w bezpieczeństwie powstają w miarę ewolucji kodu. Moim zdaniem jest to największe ryzyku, gdy kod jest bardzo często zmieniany i czasami można coś przeoczyć. Nie zawsze również da się korzystać z parametryzowanych zapytań i wtedy niestety trzeba stworzyć zapytanie dynamicznie. Atak SQL Injection polega na takim zmanipulowaniu danych wejściowych, że powstanie nowe zapytanie, zwracające dowolne dane z bazy danych.

1. SQL Injeciton w Select

Zacznijmy od klasycznego przykładu. Załóżmy, że mamy wyszukiwarkę na stronie i zwracamy dane na podstawie wpisanej nazwy artykułu:

SELECT * FROM Articles WHERE Name= ‘fraza’ and
Published=1

To co znajduje się jako wartość kolumny ‘Name’ może być przekazywane za pomocą URL, np.:

www.test.com\articles?name=’fraza’

Problem w tym, że bez walidacji użytkownik może “wstrzyknąć” tak spreparowaną frazę, że powstanie zupełnie nowe zapytanie.  Co się stanie, jak użytkownik poda następującą frazę?

fraza’ OR 1=1 —

Po podstawieniu, zapytanie będzie wyglądać:

SELECT * FROM Articles WHERE Name= ‘fraza’ OR 1=1 –‘ and
Published=1

Podanie apostrofu spowoduje, że następna część frazy zostanie potraktowana jako zapytanie. Powyższy przykład pokazał jak wyświetlić wszystkie artykuły (OR 1=1)  zamiast tylko tego konkretnego.

Innymi słowy, atak SQL Injection jest możliwy, gdy dane pochodzą z zewnętrznego źródła (query string, formularz itp) i nie są one odpowiednio formatowane przed włączeniem je w dynamiczne zapytanie.

2. INSERT INTO

SQL Injection nie ogranicza się tylko do SELECT.  Załóżmy, że mamy następujący INSERT INTO:

INSERT INTO Articles (name, author,priority) Values (‘nazwa’,’Piotr Z’,5)

Jeśli nazwa pochodzi z zewnętrznego źródła, wtedy można wstrzyknąć:

nazwa’,’Piotr’,9999)–

Spowoduje to, że wyjściowe zapytanie to:

INSERT INTO Articles (name,author,priority) Values (nazwa’,’Piotr’,9999)–‘,’Piotr Z’,5)

Czyli będziemy w stanie zmienić jakiekolwiek wartości, nawet te, które były wcześniej zawsze stałymi.

3. UPDATE\DELETE

Analogicznie, Update jest narażony na taki sam atak. Rozważmy aktualizację hasła:

UPDATE Users SET Password=’new password’ WHERE user = ‘piotr’ and password
=’old password’

Zapytanie powinno zmienić hasło wyłącznie jeśli poda się prawidłową nazwę użytkownika oraz hasło (tylko wtedy jest dopasowany rekord w bazie). A co jeśli podamy jako nazwę admin’–? Powstanie wtedy:

UPDATE Users SET Password=’new password’ WHERE user = ‘admin’–‘ and password
=’old password’

W łatwy sposób unikniemy autentykacji i  zmienimy hasło dla administratora.

5. Klauzula OrderBy

Dane wyświetlane np. w formie tabel, zwykłe mogą być sortowane. Programiści myśląc, że napiszą bardziej elegancki kod, czasami wstrzykują nazwę kolumny i kierunek sortowania bezpośrednio  w zapytanie, tzn.:

SELECT * FROM Articles OrderBy Author DESC

Stosując powyższe wskazówki czyli podając jako nazwę kolumny np. Author ASC –, możemy modyfikować dowolnie kod.

6. Wstrzykiwanie napisów oraz typów liczbowych.

Nie znając architektury wewnętrznej trzeba w jakiś sposób sprawdzić z jakimi typami danych mamy do czynienia. Powyższe przykłady opierały się głównie na manipulowaniu tekstem poprzez dodane apostrofu. Często jednak możliwe jest wstrzyknięcie typów liczbowych np.:

SELECT * FROM Data where Page = 5.

Jeśli numer strony pochodzi od użytkownika, warto spróbować wstrzyknąć np. 3+3. Jeśli spowoduje to wyświetlenie strony 6, znaczy, że aplikacja jest podatna na kolejne ataki. Można nawet spróbować wstrzyknąć 71-ASCII(‘A’). Jeśli zostanie wyświetlona szósta strona (71-65), wtedy wiemy, że kolejne ataki można przeprowadzić.

Leave a Reply

Your email address will not be published.