To nie do końca jest wpis techniczny. W trakcie korespondencji z Karolem przy rozwiązywaniu wyzwania (jak na razie tylko Karol mu podołał, zapraszam do dalszej zabawy: http://bootcamp.threats.pl/lesson08/, zadanie jest proste - wystarczy się zalogować) zauważyłem, że chyba nie do końca dobrze wyjaśniłem koncepcję blind sql injection. Spróbuję to trochę lepiej wyjaśnić.
O blind sql injection
W przypadku "normalnego" sql injection rezultat zapytania jest wypisywany w jakiś sposób na ekran. Tutaj można dyskutować czy injection, którego działanie opiera się na wystąpieniu błędu i wypisaniu tego błędu w komunikacie jest jeszcze przypadkiem "normanlnym", czy już nie. W przypadku blind sql injection sytuacja jest taka, że nie widać wyniku zapytania. Jak w takim razie odczytać dane?
Jedna z baz danych nazywa się Oracle, nie jeden raz przyszło mi w niej wykorzystać blind sql injection, co jest pewną ironią, bo znaczenie słowa oracle to... wyrocznia. Termin wyrocznia bardzo dobrze oddaje istotę sposobu wykorzystania blind sql injection, przy czym od razu zaznaczam, że w żaden sposób blind sql injection nie jest ograniczone do bazy danych Oracle, ani baza ta w żaden sposób nie jest w sposób szczególny narażona na wystąpienie/wykorzystanie tej podatności. Po prostu takie bardzo luźne skojarzenie.
Wyrocznie miały to do siebie, że swoje proroctwa podawały w sposób kompletnie niezrozumiały, przynajmniej dla mnie, dość konkretnego, ścisłego człowieka. Nie to, bym z usług wyroczni korzystał, ale... Z drugiej strony można się bawić w zgadywanie co druga osoba ma na myśli, przy czym cała zabawa odbywa się w oparciu o zadawanie pytań, na które możliwa jest odpowiedź TAK lub NIE. Trzeba tak konstruować pytania, by na podstawie odpowiedzi TAK/NIE uzyskać jak najwięcej informacji.
Dokładnie w taki sposób można wykorzystać blind sql injection. Co prawda nie jesteśmy w stanie zobaczyć wyników zapytania, ale jednak w jakiś sposób możemy wnioskować o jego rezultacie. Przy czym cały czas mowa o przypadkach, gdy zapytanie (a waściwie jego rezultat) można sporwadzić do wartości TAK lub NIE. W ramach ćwiczeń polecam przykad http://bootcamp.threats.pl/lesson07/ oraz tekst, który na ten temat napisałem: Bootcamp: (blind) SQL injection.
W tym przykładzie zapytanie (zapewne) wygląda mniej więcej tak:
SELECT * FROM tabela WHERE id=$id;
Wartość $id jest brana z żądania przychodzącego od klienta i nie jest poddawana walidacji, w związku z czym możliwe jest doklejenie własnego kodu SQL. W normalnym przypadku, gdy poda się właściwą wartość parameru $id rezultatem jest wyświetlenie się żądanej wiadomości. Stan ten możemy uznać za TAK. Rozbudowując ten przypadek przekazanie wartości postaci 2 AND 1=1 nadal będzie spełniało warunek TAK, ponieważ 2 jest prawidłowym identyfikatorem treści, natomiast 1=1 jest prawdą. Z kolei 2 AND 1=0 będzie skutkowało odpowiedzią NIE, która w tym przypadku wyraża się poprzez brak wyświetlenia (treści) wiadomości.
W przypadku ogólnym rozróżnienie odpowiedzi zależy tylko od naszej pomysłowości. Nie zawsze jest możliwość uzyskania tak oczywistego rozróżnienia, jak w omawiamym przykładzie, czy w wyzwaniu. Czasami taka wiadomość jest nam (zupełnie niezamierzenie) przekazywana przez system/aplikację na przykład w czasie odpowiedzi na nasze żądanie. Ja z kolei często wykorzystuję technikę celowego wywołania błędu w bazie danych, moim "ulubionym" sposobem jest wywołanie błędu dzielenia przez 0. Po prostu konstruuję (pod)zapytanie postaci:
SELECT 1/0 WHERE 1=0 SELECT 1/0 WHERE 1=1
W przypadku, gdy warunek w WHERE jest prawdziwy, można liczyć na to, że wystąpi błąd aplikacji, w innym przypadku błędu nie będzie. Jest to wystarczające do rozróżnieni, czy odpowiedź systemu to TAK czy NIE. Akurat tej techniki nie ma co próbować w przypadkusqlite (i kilku innych baz, pisałem na ten temat również tu: Niespodzianka - w ORDER BY też da się zrobić SQL Injection...).
Gdy zna się już sposób na rozróżnienie odpowiedzi TAK od odpowiedzi NIE wyzwanie polega głównie na zadawaniu odpowiednich pytań. Jakie pytania jest zadawać najlepiej? To już zależy od konkretnej sytuacji i tego, czego się chcemy dowiedzieć. Przykładowo błąd w (pod)zapytaniu postaci:
SELECT * FROM nazwa_tabeli
...mówi nam, że takiej tabeli NIE MA. Można wykorzystać to do określenia struktury bazy danych, ale skuteczność/wydajność tego rozwiązania jest mocno znikoma, głównie dlatego, że zależy od szczęścia, czy trafi się w odpowiednią nazwę tabeli. Oczywiście może nam chodzić o sprawdzenie, czy istnieje tabela o określonej nazwie i w takim przypadku może się okazać, że właśnie takie zapytanie najszybciej doprowadzi nas do celu.
W przypadku odczytywania danych z bazy danych, które są przechowywane (lub rzutowane w naszym zapytaniu) na jakąś wartość tekstową mamy do czynienia tak naprawdę z sytuacją, gdy chcemy poznać wartość jakiegoś łańcucha znaków. Na "hakerskich" filmach czasami dane (głównie hasła) pojawiają się "literka po literce". O ile w przypadku dobrze hashowanych haseł jest to bzdura, o tyle w przypadku blind sql injection nasze podejście rzeczywiście tak wygląda (a przynajmniej może tak wyglądać). To, co należy zrobić w celu poznania wartości danych, to "po prostu" określenie jaki znak występuje na pozycji pierwszej, drugiej, trzeciej..., piętnastej...
Jak takie określenie można zrobić? Podstawowe rozwiązanie, które "rzuca się" do głowy, to wykonanie serii zapytań, które mówią mniej więcej tyle:czy to A, czy to B, czy to C, ..., czy to g..., (...). Nie jest to jednak rozwiązanie efektywne. Zamiast tego można wykorzystać relację typu większy, mniejszy równy odnośnie samych znaków, lub ich kodów ASCII. Jeśli szukamy literki d, to w alfabecie jest ona "dalej" niż literka a, ale "bliżej" (czyli jest mniejsza) niż literka g. Zawężająć w ten sposób zakres w końcu dojdziemy (szybciej niż sprawdzając sekwencyjnie) o jaką literę chodzi. O tym z kolei pisałem tu: Blind sql injection - dlaczego bisekcja.
Podsumowując: cała idea blind sql injection opiera się na uzyskaniu stanu, w który możliwe będzie odróżnienie odpowiedzi TAK od NIE, a następnie na zadawaniu takich pytań, by w oparciu o te odpowiedzi móc dojść do tego, o czym "myśli" nasza wyrocznia. Proste?
Jeśli pojęcie koniunkcji nie jest Wam obce, doskonale wiecie, że jest ona przemienna. Przemienna, czyli a i b == b i a (że to w taki sposób zapiszę). W zasadzie jest to prawda. Prawie. A prawie robi różnicę.Jedną z cech koniunkcji jest fakt, że jeśli pier
Przesłany: Jul 19, 10:48