Java wybrane technologie spotkanie nr 14 Bezpieczeństwo
Podstawowe pojęcia uwierzytelniania (authentication) autoryzacja (authorization) atrybuty bezpieczeństwa informacji integralność danych (data integrity) poufność (confidentiality) tylko ktoś autoryzowany ma dostęp do danych, ale na wszelki wypadek podsłuchujący nic nie zrozumieją dostępność (availability) audyt (auditing) złośliwy kod (malicious code) wirusy, robaki, trojany i tylne furtki zaokrąglanie transakcji bankowych co robić z ryzykiem: unikać, ograniczać, zaakceptować, przenieść 2
Mechanizmy uwierzytelniania użytkowników w aplikacjach WWW Mechanizmy uwierzytelniania uż. według specyfikacji Serwletów HTTP Basic authentication HTTP Digest authentication HTTPS Client authentication FORM-based authentication 3
HTTP Basic authentication Mechanizm zdefiniowany w specyfikacji HTTP 1.1 Przeglądarka nie wie, że wymagane jest uwierzytelnianie GET /servlet/testservlet HTTP/1.1 Zamiast zasobu odsyłana jest prośba o uwierzytelnienie HTTP/1.1 401 Unauthorized Server: Tomcat/5.0.25 WWW-Authenticate: Basic realm="sales" Content-Length=500 Content-Type=text/html <html> jakiś komunikat </html> Przeglądarka wyświetla okienko z prośbą o zalogowanie Przeglądarka ponawia żądanie do zasobu, dodając zakodowaną przy pomocy Base64 parę login:hasło GET /servlet/salesservlet HTTP/1.1 Authorization: Basic am9objpqamo= Serwer sprawdza nadesłane wartości i albo odsyła zasób, albo ponawia komunikat 401 4
HTTP Digest authentication HTTP Basic authentication z szyfrowaniem przesyłanego loginu i hasła
HTTPS Client authentication komunikacja HTTP jest przepuszczana przez SSL uwierzytelnianie przeprowadza się po nawiązaniu bezpiecznego połączenia między przeglądarką i serwerem
FORM-based authentication Mechanizm podobny do HTTP Basic authentication, ale zamiast okienka przeglądarki login i hasło pobierane jest z formularze Wymagania względem formularza action="j_security_check" pole j_username pole j_password należy używać metody post
Wady/zalety HTTP Basic authentication łatwy w realizacji niebezpieczne, bo Base64 to nie wspierany przez wszystkie przeglądarki szyfrowanie nie można wpłynąć na wygląd okienka dialogowego HTTP Digest authentication bezpieczniejszy od Basic auth. najbezpieczniejszy wspierany przez wszystkie przeglądarki łatwy w realizacji wspierany przez wszystkie przeglądarki łatwo dopasować wygląd formularza wspierane jedynie przez MS IE 5 nie wymagane przez specyfikacje i wspierane przez niewiele kontenerów HTTPS Client authentication wymaga certyfikatów kosztowna implementacja FORM-based authentication niebezpieczne 8
Deklaratywne zabezpieczanie aplikacji WWW <!-- BASIC DIGEST CLIENT-CERT FORM --> <login-config> <auth-method>basic</auth-method> <realm-name>mim</realm-name> </login-config> <login-config> <!-- BASIC DIGEST CLIENT-CERT FORM --> <auth-method>form</auth-method> <form-login-config> <form-login-page>/login.jsp</> <form-error-page>/error.jsp</ </form-login-config> </login-config>2 <security-role> <description>bla bla bla</description> <role-name>role1</role-name> </security-role> <security-role> <role-name>tomcat</role-name> </security-role> 9
Deklaratywne zabezpieczanie aplikacji WWW c.d. <security-constraint> <web-resource-collection> <web-resource-name>kolekcja1</web-resource-name> <url-pattern>/index.html</url-pattern> <url-pattern>/index.jsp</url-pattern> <http-method>get</http-method> <http-method>post</http-method> <!-- wszystkie pozostałe metody są niezabezpieczone --> <!-- zamiast wymieniać wszystkie metody można nie podać żadnej --> </web-resource-collection> <auth-constraint> <role-name>role1</role-name> <!-- * oznacza wszystkie role wymienione w deskryptorze --> </auth-constraint> <user-data-constraint> <!-- NONE INTEGRAL CONFIDENTIAL --> <transport-guarantee>confidential</transport-guarantee> </user-data-constraint> </security-constraint> 10
Programistyczne zabezpieczanie aplikacji WWW Przydatne metody HttpServletRequest: String getauthtype() null HttpServletRequest.BASIC_AUTH, HttpServletRequest.FORM_AUTH, HttpServletRequest.CLIENT_CERT_AUTH, HttpServletRequest.DIGEST_AUTH java.security.principal getuserprincipal() //w znaczeniu zlecaniodawca String getremoteuser() boolean isuserinrole(string) Wylogowanie użytkownika (tylko dla metody FORM) session.invalidate() 11
Mapowanie ról Ponieważ w podejściu programistycznym nazwy ról są na stałe wpisane w kodzie, żeby skonfigurować aplikację po napisaniu należy zmapować je na rzeczywiste role używane przez kontener <servlet> <security-role-ref> <role-name>alamakota</role-name> <role-link>tomcat</role-link> </security-role-ref> </servlet> 12
Czy nie lepiej wszystko zrobić samemu Opracowywanie nowych algorytmów kryptograficznych, protokołów uwierzytelniania, systemów kontroli dostępu wymaga lat doświadczenia Łatwo coś przeoczyć Dużo kosztownej pracy, z której mało pożytku 13
Nie tylko dobra aplikacja Konfiguracja aplikacji zmiana domyślnych haseł Konfiguracja serwera aplikacji zmiana domyślnych haseł poprawna konfiguracja usług serwera (np. JNDI) Konfiguracja sieci ataki typu man-in-the-middle ataki typu denial-of-service 14
Identity assertion (transitive trust) 15
Autoryzacja w EJB Programistyczna vs Deklaratywna deklaratywnie mamy mniej pracy ale nie da się condition-based-authorization np. zatwierdźzamówienie(wartość < 1000PLN) ale nie da się instance-level-authorization np. tylko operacje na studentach wydziału MIMUW 16
Autoryzacja programistyczna javax.ejb.ejbcontext public boolean iscallerinrole(string rolename); @Stateless public class EmployeeManagementBean { @Resource private SessionContext ctx; } // public void modifyemployee(string employeeid) throws SecurityException { if (!ctx.iscallerinrole("administrators")) { throw new SecurityException(); } else { //jakieś operacje na pracowniku } } public java.security.principal getcallerprincipal(); wiedząc kim jest użytkownik możemy np. korzystać z ustawień, które zapamiętał w swoim profilu 17
Deklarowanie używanych ról @Stateless @DeclareRoles({"administrators"}) public class EmployeeManagementBean { s// } <enterprise-beans> <session> <ejb-name>employeemanagementbean</ejb-name> <!-- Deklarujemy, że ta rola jest używana w kodzie --> <security-role-ref> <description>blah blah blah</description> <role-name>administrators</role-name> </security-role-ref> </session> </enterprise-beans> 18
Mapowanie ról <enterprise-beans> <session> <ejb-name>employeemanagementbean</ejb-name> <security-role-ref> <description>ala ma kota</description> <role-name>administrators</role-name> <role-link>admins</role-link> </security-role-ref> </session> <assembly-descriptor> <security-role> <description>trelemorele</description> <role-name>admins</role-name> </security-role> </assembly-descriptor> </enterprise-beans> 19
Autoryzacja deklaratywna import javax.annotation.security.*; @Stateless //domyślna rola pozwalająca na wykonanie metody @RolesAllowed({"administrators"}) public class EmployeeManagementBean implements EmployeeManagement { //przesłania domyślną rolę @RolesAllowed({"managers"}) public void modifysubordinate() { // } //przesłania domyślną rolę @RolesAllowed({"employees" }) public void modifyself(string name) { // } //brak ograniczeń na wołającego @PermitAll public String getmyname() { // } //obowiązuje domyślna rola public Collection getallemployees() { // } } //nikt nie może wołać tej metody //ma większy sens w deskryptorze @DenyAll public void modify401kplan() { // } // 20
Autoryzacja deklaratywna <assembly-descriptor> <method-permission> <role-name>administrators</role-name> <!--na poziomie beana--> <method> <ejb-name>employeemanagement</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>managers</role-name> <!--na poziomie metod--> <method> <ejb-name>employeemanagement</ejb-name> <method-name>modifysubordinate</method-name> </method> <method> <ejb-name>employeemanagement</ejb-name> <method-name>modifyself</method-name> </method> </method-permission> 21
Autoryzacja deklaratywna <method-permission> <role-name>employees</role-name> <!--na poziomie przeciążonych metod--> <method> <ejb-name>employeemanagement</ejb-name> <method-name>modifyself</method-name> <method-params>string</method-params> </method> </method-permission> <!-- jeżeli używamy beana napisanego przez kogoś innego, można zrezygnować z niektórych metody --> <exclude-list> <description>fiu bździu</description> <method> <ejb-name>employeemanagement</ejb-name> <method-name>cośniepotrzebnego</method-name> <method-params>string</method-params> </method> </exclude-list> </assembly-descriptor> 22
Autoryzacja deklaratywna Kontener automatycznie wykonuje sprawdzanie i przy próbie nadużycia zgłasza java.rmi.accessexception Również tu należy zadeklarować używane role @DeclareRoles({"aaa", "bbb", }) <assembly-descriptor> <security-role> <description>aaa</description> <role-name>aaa</role-name> </security-role> <security-role> <description>bbb</description> <role-name>bbb</role-name> </security-role> </assembly-descriptor> 23
Wpływanie na propagację ról @RunAs("admins") @Stateless public class MójKońTrojański { // } <enterprise-beans> <session> <ejb-name>employeemanagement</ejb-name> <security-identity> <run-as> <role-name>admins</role-name> </run-as> </security-identity> </session> <assembly-descriptor> <security-role> <description>służy do</description> <role-name>admins</role-name> </security-role> </assembly-descriptor> </enterprise-beans> 24
JAAS Java Authentication and Authorization Service składnik Java SE (od wersji 1.4) standardowy mechanizm logowania się do systemu bez zwracania uwagi na aktualnie używany mechanizm możliwość konfiguracji bez zmiany kodu klienta możliwość dopasowania do praktycznie każdego systemu bezpieczeństwa, np. użytkownicy i hasła składowane w bazie danych czy LDAP uwierzytelnianie na podstawie certyfikatów integracja z NIS kontrola dostępu na podstawie IP 25
26