Java wybrane technologiespotkanie nr 14
Bezpieczeństwo
2
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ść
3
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
4
HTTP Basic authenticationMechanizm 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
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
8
Wady/zaletyHTTP Basic authentication
– łatwy w realizacji– wspierany przez wszystkie przeglądarki
HTTP Digest authentication– bezpieczniejszy od Basic auth.
HTTPS Client authentication– najbezpieczniejszy– wspierany przez wszystkie przeglądarki
FORM-based authentication– łatwy w realizacji– wspierany przez wszystkie przeglądarki– łatwo dopasować wygląd formularza
– niebezpieczne, bo Base64 to nie szyfrowanie
– nie można wpłynąć na wygląd okienka dialogowego
– wspierane jedynie przez MS IE 5– nie wymagane przez specyfikacje i
wspierane przez niewiele kontenerów
– wymaga certyfikatów– kosztowna implementacja
– niebezpieczne
9
Deklaratywne zabezpieczanie aplikacji WWW
... <!-- BASIC DIGEST CLIENT-CERT FORM --> <login-config> <auth-method>BASIC</auth-method> <realm-name>mim</realm-name> </login-config>
... <security-role> <description>bla bla bla</description> <role-name>role1</role-name> </security-role> <security-role> <role-name>tomcat</role-name> </security-role> ...
...<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
10
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> ...
11
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()
12
Mapowanie rólPonieważ 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>
13
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
14
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
15
Identity assertion (transitive trust)
16
Autoryzacja w EJBProgramistyczna 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
17
Autoryzacja programistyczna● javax.ejb.EJBContext
– public boolean isCallerInRole(String roleName);
@Statelesspublic 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
18
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>...
19
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>...
20
Autoryzacja deklaratywnaimport 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() { // ... } // ...}
21
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>
...
22
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>
23
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>
24
Wpływanie na propagację ról@RunAs("admins")@Statelesspublic 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>...
25
JAASJava 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
26