Jak zostać ekspertem od SQL Injection – cz.2

Seria o SQL Injection:
Jak zostać ekspertem od SQL Injection – cz. 1
Jak zostać ekspertem od SQL Injection – cz. 2
Jak zostać ekspertem od SQL Injection – cz. 3
Jak zostać ekspertem od SQL Injection – cz. 4
Jak zostać ekspertem od SQL Injection – cz. 5

Witam Cię ponownie w kolejnej części poradnika JAK ZOSTAĆ EKSPERTEM OD SQL INJECTION.
W poprzednim artykule Jak zostać ekspertem od SQL Injection – cz.1 , omówiłem najważniejsze dyrektywy SQL oraz znaki specjalne, które będą Twoim niezbędnikiem na drodze do tego jak zostać ekspertem. 
Poznałeś(łaś) również aż trzy różne metody komentowania kodu SQL, które pozwalają na omijanie systemów wykrywania włamań.
W tej części artykułu opiszę Ci metody wykrywania podatności na ataki typu SQL Injection. Po zidentyfikowaniu nieprawidłowości w działaniu aplikacji zobaczymy w jaki sposób przygotować się do głównej fazy ataku na podstawie zebranych informacji.

SQL Injection – Metody wykrywania podatności

Atakujący może wykorzystać wiele technik informujących go o potencjalnej luce w aplikacji webowej. Atakujący przeszukuje każde z miejsc, do którego może zostać wstrzyknięty kod SQL.

Miejscami takimi są:

1. Pola w formularzach internetowych, również te ukryte, które przenoszą zmienne,
2. Parametry w adresie URL,
3. Wartości pochodzące z ciasteczek (cookies).

W celu identyfikacji podatności atakujący próbuje wysłać różne sekwencje znakowe do serwera takimi metodami, które skrypt obsługuje. Znaki jakie mogą być wysłane w celu identyfikacji podatności to np.:

1. ‘
2. ”
3. )
4. #
5. ­­ /
6. *

W każdym z powyższych przypadków szukane jest niestandardowe zachowanie skryptu, zwracane wyniki, błędy i różnice w stosunku do normalnej pracy aplikacji. Atakujący może wprowadzać również zarezerwowane słowa kluczowe języka SQL, np.:
SELECT, UNION, FROM, WHERE, itd.

Może je wykorzystać wraz z kombinacjami białych znaków zakodowanych w systemie szesnastkowym przy użyciu znaku %. Daje to możliwość wykonania zapytania, nawet gdy aplikacja chroniona jest systemami IPS lub IDS.

Atakujący stara się poznać mechanizmy działania aplikacji webowej próbując:

  1. Zidentyfikować rodzaj bazy danych,
  2. Zrozumieć działanie zapytań języka SQL w danym skrypcie,
  3. Poznać poziom uprawnień użytkownika,
  4. Poznać stopień uprawnień w systemie operacyjnym,
  5. Zrozumieć mechanizmy dynamicznie wyświetlające dane na podstawie zapytań.

Atakujący rozpoznaje rodzaj bazy danych:

  1. Bazując na komunikatach o błędach, wyświetlonych bezpośrednio na stronie WWW,
  2. Poprzez identyfikację serwera WWW, systemu operacyjnego na jakim działa serwer,
  3. Używając do zapytań specyficznych znaków, funkcji, składni występującej jedynie w określonych implementacjach silników bazodanowych. Takim przykładem może być np. funkcja łączenia ciągów znaków – CONCAT, która jest charakterystyczna dla bazy danych MySQL,
  4. Używając funkcji informujących o wersji oprogramowania, takich jak VERSION() oraz @@VERSION.

Atakujący stara się zrozumieć działanie zapytań języka SQL w danym skrypcie:

Skrypty używają różnych konstrukcji zapytań SQL, lecz dla osoby atakującej system bazodanowy MySQL, najistotniejsze jest działanie instrukcji SELECT. Instrukcje INSERT, UPDATE oraz DELETE są mało istotne z wyjątkiem sytuacji, gdy wykorzystują dane z zapytań używających instrukcji SELECT.

W przeciwieństwie do niektórych systemów bazodanowych takich jak PostgreSQL, w bazie danych MySQL nie można wykonać w jednej linii kilku zapytań oddzielonych średnikiem. Z tego powodu, rzadko zdarza się wykorzystywać instrukcje inne niż SELECT.

Instrukcje SELECT często zawierają warunek WHERE i mogą zawierać klauzule takie jak: HAVING, GROUP BY, ORDER BY.

W celu określenia samej struktury zapytania z instrukcją SELECT, atakujący może wykorzystać błędy generowane na podstawie różnie wprowadzanych zapytań lub różne reakcje działania skryptu.

Dla przykładu, jeżeli dane wprowadzone do skryptu są częścią zapytania zagnieżdżonego, nie można wykorzystać takich klauzul jak np.: GROUP BY, HAVING.

Dla atakującego ważną rolę w poznaniu działających zapytań mają nazwy zmiennych skryptu, pól formularzy, wartości zapisywanych do ciasteczek itd.

Atakujący stara się poznać poziom uprawnień użytkownika: Wykorzystując funkcje takie jak USER() oraz CURRENT_USER() przy pomocy wstrzykniętych zapytań metodą SQL Injection lub Blind SQL Injection, atakujący stara się zrozumieć mechanizmy dynamicznie wyświetlające dane i używając:

  1. możliwie największego zbioru zwracanych rezultatów przez bazę danych,
  2. specjalnie przygotowanych zapytań, które w jakiś sposób zwracają informacje o błędach wykonania lub o poprawnym wykonaniu przez serwer MySQL,
  3. metody ataku Blind Injection, bazującej na zwracanych błędach, zwracanych wartościach tekstowych lub bazując na atakach czasowych,
  4. innych mechanizmów w zależności od konstrukcji samego skryptu.

Atakujący usiłuje poznać strukturę bazy, starając się generować:

1. Błędy spowodowane nieprawidłowymi warunkami grupowania przy użyciu klauzuli GROUP BY

Atakujący może użyć następującego zapytania w celu identyfikacji, czy dana kolumna w tabeli istnieje:
http://host/?param=1′ group by nazwa_kolumny having 1=1/*

Jeżli nazwa kolumny podana jako nazwa_kolumny nie istnieje, zapytanie zwróci błąd. Przy wykorzystaniu klauzuli GROUP BY atakujący może w prosty sposób wyliczyć ilość kolumn, jakie są niezbędne do skonstruowania poprawnego zapytania SQL z użyciem UNION. Przy wykorzystaniu unii, liczba kolumn będąca rezultatem każdego z zapytań składowych musi być równa. Liczbę niezbędnych kolumn można uzyskać przy pomocy grupowania.
Załóżmy, iż zapytanie skonstruowane przez programistę skryptu zwraca jedynie jedną kolumnę. W takim przypadku użycia następującego żądania HTTP:

http://host/?param=1 group by 1
MySQL nie zwróci błędu grupowania, ponieważ wybierana jest tylko jedna kolumna. Natomiast w przypadku żądania:
http://host/?param=1 group by 3
MySQL zwróci błąd grupowania. W taki sposób można enumerować liczbę kolumn w tabeli. W identyczny sposób można się posłużyć inną klauzulą – ORDER BY. Klauzula ta służy do sortowania po określonych polach. Jeżeli wykonamy żądanie:
http://host/? param=1 order by 3
i w tabeli są trzy pola, błąd zapytania nie zostanie zwrócony do skryptu. Enumeracja, która nie bazuje na klauzuli GROUP BY ani ORDER BY może wyglądać następująco:
http://host/?param=1 union select 0,0,0,0,0,0 from tabela
W przypadku różnicy w liczbie kolumn między pierwszym wynikiem zapytania SELECT oraz drugim zostanie zwrócony błąd,

2. Błędy wywołane w przypadku przetwarzania komentarzy

MySQL posiada funkcjonalność przetwarzania specjalnie spreparowanych komentarzy. Jeśli w komentarzach /**/ po znaku pierwszej gwiadzki, pojawi się znak wykrzyknika, zapytanie takie zostanie przetworzone przez serwer bazodanowy. Wykorzystywane jest to do poznania wersji bazy danych. Atakujący może posłużyć się następującym żądaniem HTTP do serwera WWW:
http://host/?param=1/*!50024 and ­*/
Jeżeli serwer bazodanowy jest w wersji >= 5.0.24 wynik zapytania będzie zawierał błąd wykonania, ponieważ do zapytania zostanie dołączony znak ­, który spowoduje błąd. Wykonanie zapytania z tak skonstruowanym komentarzem wygląda następująco:
if(version >= 5.0.24) { dodaj ‘and ­’ do zapytania }

3. Błędy niezgodności typów danych

Jeżeli tabela zawiera wszystkie pola typu całkowitego, następujące żądanie HTTP spowoduje powstanie błędu po stronie serwera bazodanowego:
http://host/?param=1 union select ‘abc’,1,2,3

Ciąg ‘abc’ jest typu tekstowego, więc zapytanie zwróci błąd typów. Inny sposób na wykorzystanie informacji o błędach, to użycie zapytania zagnieżdżonego, np.:
http://host/?param=1 and 1 in (select ‘xyz’)

Podzapytanie zwróci ciąg xyz, natomiast zapytanie nadrzędne cyfrę 1 co spowoduje powstanie błędu niezgodności typów. W podobny sposób można stwierdzić, czy pola są wartości całkowitego używając bardzo dużych liczb, które wychodzą poza zakres – np. 65535. Jeśli nie przekroczymy zakresu i serwer nie zwróci błędu mamy do czynienia z typem całkowitym,

4. Błędy związane z niepoprawnie podanymi nazwami tabel lub pól

Jeśli atakujący ma pewność, że aplikacja jest podatna na atak, lecz nie zna nazw pól tabeli może posłużyć się następującym żądaniem HTTP:
http://host/?param=­1 union select ‘xyz’ from tabela

Jeżeli pole xyz nie istnieje w tabeli, zostanie zwrócony błąd wykonania zapytania. Tą metodą atakujący może przygotować słownik z określonymi słowami i metodą brutalną próbować podstawiać kolejno słowa, aż do zidentyfikowania prawidłowej nazwy kolumny. Po natrafieniu na prawidłową nazwę, zawartość kolumny zostanie wyświetlona. W podobny sposób można przeprowadzić atak na nazwy tabel w bazie danych. Przykładem specjalnie spreparowanego żądania HTTP do serwera WWW może być:
http://host/?param=1 union select null from szukana_tabela

Do zapytania doklejana jest wartość nieokreślona NULL, czyli taka, która jest niejako neutralna pod względem typu. Można ją łączyć z różnymi typami danych. W przypadku pobierania danych z nieistniejącej tabeli zostanie zwrócony błąd zapytania, co może informować atakującego o braku takiej tabeli w bazie. W tym przypadku atakujący może również przygotować słownik z potencjalnymi nazwami tabel w celu automatyzacji ataku typu brute force.

Używając ataku Blind SQL Injection, atakujący stara się poznać strukturę bazy:

1. Atakujący może posłużyć się wieloma odmianami warunków logicznych

Z operatorami: and, or itd. wraz z różnymi wariantami symboli ograniczających ciąg znaków. Takimi przykładami fragmentów wstrzykiwanych zapytań oraz warunków logicznych mogą być:

a) admin’­­
b) ‘ or 0=0
c) ­­ ” or 0=0
d) ­­ or 0=0
e) ­­ ‘ or 0=0 #
f) ” or 0=0#
g) or 0=0 #
h) ‘ or ‘x’=’x
i) ” or “x”=”x
j) ‘) or (‘x’=’x
k) ‘ or a=a­­
l) ‘) or (‘a’=’a
m) “) or (“a”=”a
n) abc” or “a”=”a
o) abc” or 1=1
p) ­­ abc’ or 1=1
r) ­­ abc’ or ‘a’=’a
s) abc’) or (‘a’=’a
t) abc”)or(“a”=”a
u) ‘ or ”=’
v) …

Oczywiście nie wyczerpuje to możliwego zbioru kombinacji, z racji chociażby, że w warunkach tych mogą pojawić się różne, nie wymienione powyżej znaki komentarzy końca linii,

2. W przypadku, gdy skrypt nie zwraca żadnego rezultatu.

Dodatkowo w żaden sposób nie informuje o błędzie, bądź też o poprawnym wykonaniu zapytania, atakujący może wykorzystać funkcję BENCHMARK do przeprowadzenia ataku. Następujący scenariusz jest możliwy do wykorzystania:
http://host/?param=1 and if(haslo in(select haslo from tabela), benchmark(900000,md5(‘0′)),’FALSE’)
W przypadku, gdy w tabeli znajduje się pole o nazwie haslo, skrypt uruchomi testowanie zapytania i zawiesi na chwilę swoje działanie. Jeśli chcemy poznać nazwę tabeli w bazie możemy posłużyć się następującym żądaniem HTTP:
http://host/?param=1 and 1 in(select 1 from tabela)
W przypadku, gdy tabela o nazwie tabela istnieje w bazie, żaden błąd nie zostanie zwrócony.

3. W przypadku ataków Blind SQL Injection

Możliwe jest wykorzystanie różnych mechanizmów, podobnych do tych z klasycznego ataku SQL Injection, lecz bez możliwości otrzymania pełnych komunikatów o błędzie. Atakujący bazuje jedynie na dwóch zwracanych wartościach logicznych: PRAWDA oraz FAŁSZ. Na tej podstawie możliwe jest odczytywanie określonych informacji, lecz jest to na pewno trudniejsze niż w przypadku klasycznego ataku. W zależności od konstrukcji samego skryptu można wykorzystać fakt przekierowania na inna stronę, na przykład na stronę główną serwisu, gdy zapytanie wywoła błąd składni SQL. Takie zachowanie jest opisane w kolejnych rozdziałach niniejszej pracy oraz zilustrowane przykładami. Podczas wykorzystania ataku, możliwe jest wykorzystanie systemowych tabel, zawierających loginy, zaszyfrowane hasła użytkowników, dane konfiguracyjne itp. Szczególnie ważne dla atakującego są tabele mysql.usermysql.host oraz mysql.db.

Podsumowanie – SQL Injection

W tej części poznałeś kilka wybranych i bardzo ciekawych informacji jak wykryć SQL Injection – kolejny bardzo ważny krok na drodze do zostania Ekspertem od SQL Injection:

  • Zastosowanie klauzul having oraz group by
  • Funkcję benchmark() i jej zastosowanie w Blind SQL Injection’
  • Różne mechanizmy interpretacji “Prawda” “Fałsz” w Blind SQL Injection
  • Zastosowanie zapytań zagnieżdżonych
  • Warianty tak bardzo popularnego or 1=1  

Co w kolejnej części

W kolejnym artykule z tej serii Jak zostać ekspertem SQL Injection – cz.3 dowiesz się w jaki sposób ominąć zabezpieczenia przed SQL Injection.

Będziemy już mogli “bawić” się zdobytą do tej pory wiedzą – stosując różne warianty ataków.

Poznasz co może wskazywać na zabezpieczenie a co jest po prostu tylko wadliwych przeprowadzeniem testu.

Jeśli spodobał Ci się ten artykuł – podziel się nim proszę z innymi – udostępniając go, a dzięki temu będziemy mogli dotrzeć z wiedzą do większej liczby odbiorców.

Zostaw swój komentarz lub podziel się ze mną swoimi uwagami.

5 1 vote
Ocena artykułu
Subscribe
Powiadom o
guest
0 komentarzy
Inline Feedbacks
View all comments
0
Zależy mi na Twojej opinii poniżej 😀x