In search this blog

Loading

czwartek, 24 listopada 2011

SQL Injection


SQL Injection in java Applet

Przedstawiona tutaj aplikacja demonstruje jak można dokonywać ataków SQL Injection. W aplikacji będzie można przetestować sposoby tych ataków, podejrzeć wygenerowane zapytanie do bazy danych. Baza danych to MySQL.


Tutaj przedstawię kod tworzący tabelę, którą będziemy używać do ataków z wykorzystaniem technik SQL Injection.


  1. CREATE TABLE  `sqlinjection`.`test` (  
  2.   `id` bigint(20) NOT NULL,  
  3.   `login` varchar(50) DEFAULT NULL,  
  4.   `password_` varchar(50) DEFAULT NULL,  
  5.   PRIMARY KEY (`id`),  
  6.   UNIQUE KEY `login` (`login`)  
  7. )  
  8.   
  9. INSERT INTO `sqlinjection`.`test` (`id`, `login`, `password_`) VALUES ('1''root''tajne');  
  10. INSERT INTO `sqlinjection`.`test` (`id`, `login`, `password_`) VALUES ('2''adas''fajne');  
  11. INSERT INTO `sqlinjection`.`test` (`id`, `login`, `password_`) VALUES ('3''ktos''xxx');  
  12. INSERT INTO `sqlinjection`.`test` (`id`, `login`, `password_`) VALUES ('4''ania''nie powiem');  
Teraz przedstawię formułę zapytań jakie będziemy atakować i omówić w nich zawarty błąd.

  1. select id from test where login like 'login' and password_ like 'password'  
  2. select id from test where login = 'login' and password_ = 'password'  
  3. select login from test where id = 'id'  
  4. select id, login, password_ from test where id = 'id' limit 1  
Pierwsze zapytanie można obejść na kilka sposobów ja zaprezentuje tutaj ten, który wykorzystuje błąd użycia polecania LIKE. Używając takiego zapytania do wyciągnięcia z bazy danych jakiś informacji gdzie wymagane jest dokładne dopasowanie ciągu znaków. Narażamy się na atak przy użyciu znaku oznaczającego dowolny znak w MySQL tym znakiem jest %. Teraz znając login, a nie znając hasła jesteśmy wstanie ominąć podanie hasła. Czyli np. login = root, password = %. Efektem tego będzie zalogowanie się jako root. Teraz można sprawdzić działanie tego przykładu na zamieszczonej poniżej aplikacji.

Drugie zapytanie jest już odporne na atak z zastosowaniem znaku zastępującego dowolny znak. Więc w jaki sposób obejść tego typu zapytanie? A no trzeba pozbyć się drugiej części zapytania. Jak tego dokonać, w MySQL mamy komentarz jedno liniowy i jest nim "#" lub "--" przy użyciu tych dwóch znaków jesteśmy w stanie pozbyć się części zapytania sprawdzającej hasło. Wstrzyknięcie komentarza do zapytania pozostawiam bez przykładu. Wskazówka jest taka że należy czytać błąd generowany przy złej próbie wstrzyknięcia kodu.

W zapytaniu trzecim znamy id użytkownika i po podaniu id zostaje nam zwrócona nazwa usera. W tym zapytaniu należy podmienić wynik. Zapytanie zwraca nazwę użytkownika a my chcemy aby nam zwróciło hasło dla danego usera. Tego typu atak możemy przeprowadzić z wykorzystaniem polecenia UNION. Mianowicie należy zanegować pierwsze zapytanie a następnie wstrzyknąć zapytanie zwracające to co my chcemy. Jedna uwaga liczba kolumn musi się zgadzać. Ze względu na to ze tego typu atak jest ciut trudniejszy poprę go prostym przykładem. Kod który należy wstrzyknąć w zapytanie będzie miał np. tego typu wygląd:


  1. 2' and 1 = 2 union select password from test -- wy komentowana część   
W wyniku dostaniemy wszystkie hasła zawarte w tabeli.

Nasza tabela nie zawiera z byt wiele rekordów więc jest dość łatwo przyporządkować hasło do loginu. Zapytanie zwraca tylko dane z jednej kolumny podmieniając zapytanie nadal musimy dbać o to aby dostać wynik tylko z jednej kolumny. Wiec co jeżeli chcemy dostać więcej kolumn w wyniku, z pomocą przychodzi nam funkcja CONCAT(). Zadaniem tej funkcji jest łączenie ciągów znaków. Zastępując w naszym zapytaniu pole password na tą właśnie funkcje możemy w wyniku dostać hasła z przyporządkowanymi do nich loginami, CONCAT(login,char(44),password). Funkcja CHAR() jako parametr przyjmuje kod ASCII danego znaku. 44 reprezentuje przecinek a 32 to spacja.


Te trzy zapytania pokazują jak można w łatwy sposób obejść hasło lub też wyciągnąć z bazy danych to co chcemy podmieniając zapytanie. W czwartym zapytaniu chcemy sami określić ile pól jest wyciąganych z bazy danych przez zapytanie. Najlepiej jest to zacząć testować bez podglądania zapytania. A następnie wypisanie tego co uznamy za potrzebne dla nas. Więc co wiemy a czego nie wiemy. Na pewno wiemy ze wynikiem zapytania jest wypisany login wiemy również, że mamy do czynienia z select'em. Nie wiemy jaka jest tylko liczba pól wyciąganych z bazy. Więc postępujemy podobnie jak wcześniej, należy się pozbyć zapytania pierwszego i przy użyciu union sprawdzić ile pól jest wyciąganych z bazy. Wiemy również, że mając w zapytaniu pierwszym określoną liczbę wyciąganych pól, które muszą się zgadzać w zapytaniu union select, więc jeśli nasza liczba będzie różna to serwer zwróci nam błąd. Teraz należy tylko sprawdzić to co napisałem, wiec:

  1. select (cos tu jest iles) from test (cos tam) and 1 = 2 union select 1 --   
  2. select (cos tu jest iles) from test (cos tam) and 1 = 2 union select 1,2 --   
  3. select (cos tu jest iles) from test (cos tam) and 1 = 2 union select 1,2,3 --  
  4. select (cos tu jest iles) from test (cos tam) and 1 = 2 union select 1,password,3 --    
Jak widać po zapytaniach metodą prób i błędów sprawdzamy ile pól wyciąganych jest w zapytaniu. Zapytanie pierwsze i drugie zwrócą nam błąd serwera co mów nam że nie zgadliśmy ilości pól. Zapytanie trzecie zwraca nam odpowiedz którą jest liczba 2. Mówi to nam ze właśnie pole na drugim miejscu jest wyświetlane. Można więc śmiało zamienić naszą liczbę na nazwę kolumny, można również użyć funkcji CONCAT() do łączenia wyniku.

SQL Injection in java Applet






stat4u stat4u

Brak komentarzy:

Prześlij komentarz

Powered By Blogger