Blind SQL Injection z wykorzystaniem regexpów
Przeglądając wczoraj różne informacje trafiłem na dokument Blind Sql Injection with Regular Expressions Attack. Temat jest ciekawy, jedno z głównych pytań, które mnie się nasunęło brzmi – ale po co. Po chwili przyszła jednak refleksja – może i ma to sens.
Temat sql injection poruszałem już wiele razy, między innymi w moim przewodniku po bezpieczeństwie aplikacji internetowych (na przykład tutaj: Lekcja 7: (blind) SQL injection). Cała koncepcja blind sql injection sprowadza się do tego, by zadawać pytania, które dają odpowiedź tak/nie i na podstawie tej odpowiedzi dowiedzieć się czegoś, o obiekcie, o który pytamy. A że tym obiektem są zwykle dane, zwykle dane tekstowe, chodzi o ich poznanie. Dokładnie tak, jak miało to miejsce w tym wyzwaniu.
Oczywiście zadanie to można zrealizować szybciej, lub wolniej. Przykładowo odgadnięcie wartości test może wyglądać tak:
Czy pierwsza litera to A –> NIE Czy pierwsza litera to B –> NIE Czy pierwsza litera to C –> NIE (...) Czy pierwsza litera to Z –> NIE Czy pierwsza litera to a –> NIE (...) Czy pierwsza litera to t –> TAK
Takie podejście jest skrajnie nieefektywne. Na podstawie prawdopodobieństwa występowania poszczególnych znaków w danym języku można oszacować ile zapytań trzeba wykonać w celu odgadnięcia określonej litery.
Oczywiście prawie nikt w ten sposób nie postępuje. Weźmy taki dopuszczalny i uszeregowny zakres znaków:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
Zamiast pytać po kolei, można szybciej (to tylko przykład):
Czy pierwsza litera jest większa niż A –> NIE Czy pierwsza litera jest większa niż o –> TAK Czy pierwsza litera jest większa niż o –> TAK Czy pierwsza litera jest większa niż u –> NIE (...) Czy pierwsza litera to t –> TAK
Po prostu zawężamy przedział, w którym może wystąpić nasze rozwiązanie przy każdym pytaniu zmniejszając go o połowę. Takie rozwiązanie jest zdecydowanie bardziej efektywne.
Pomysł opisany we wspomnianym dokumencie jest podobny, przy czym zamiast relacji większy/mniejszy wykorzystywane są wyrażenia regularne. Przykładowo:
Czy pierwsza litera zawiera się w [A-Z] –> NIE Czy pierwsza litera zawiera się w [a-o] –> NIE Czy pierwsza litera zawiera się w [p-u] –> TAK (...)
Pewną różnicę można znaleźć w przykładzie z wartością hasha w postaci heksadecymalnej. Tam dopuszczalne były znaki 0123456789abcdef. Korzystając z wyrażeń regularnych może odrobinę łatwiej jest operować na takim zakresie, choć jest to również możliwe przy pomocy “klasycznej” relacji większy/mniejszy rozbudowanej do kilku warunków.
Ogólnie rzecz biorąc wydaje mi się, że wydajność (ilość potrzebnych zapytań) podejścia wykorzystującego wyrażenia regularne i tego bazującego na relacji większy/mniejszy będzie zbliżona. Przecież to tak naprawdę to samo podejście, tylko realizowane przy pomocy dwóch różnych narzędzi.
Mogę sobie jednak wyobrazić sytuację, w której podejście oparte na wyrażeniach regularnych będzie wydajniejsze. Może ono bazować na:
- prawdopodobieństwie wystąpienia określonego znaku w danym języku,
- prawdopodobieństwie wystąpienia określonego znaku w danym języku, pod warunkiem, że wcześniej wystąpił określony znak (który już znamy),
Dzięki takiej dodatkowej wiedzy podejście wykorzystujące wyrażenia regularne może być bardziej efektywne. Oczywiście tu również można korzystać z relacji mniejszy/większy/równy, ale zapisanie takich warunków z wykorzystaniem wyrażeń regularnych będzie po prostu łatwiejsze i krótsze. To drugie nie jest bez znaczenia, czasami ilość znaków, które atakujący ma do dyspozycji jest ograniczona. Sam natknąłem się w trakcie testów na kilkanaście takich przypadków, w których sqlmap nie dał rady wyeksploitować podatności właśnie dlatego, że miał tendencję do budowania nieco zbyt rozbudowanych zapytań SQL.
Oryginał tego wpisu dostępny jest pod adresem Blind SQL Injection z wykorzystaniem regexpów
Autor: Paweł Goleń