10 Bezpieczeństwo w Javie, Podstawy programowania
[ Pobierz całość w formacie PDF ]
Jacek Rumi
ń
ski - J
ę
zyk JAVA – Rozdzia
ł
1
0
Rozdział 10 Bezpieczeństwo w Javie
1
0.
1
Bezpiecze
ń
stwo programów i danych
1
0.2 Bezpiecze
ń
stwo w Javie
1
0.3 Obs
ł
uga zasad bezpiecze
ń
stwa w Javie
1
0.4 Kryptografia
1
0.4.
1
Kryptografia w Javie
1
0.4.2 Skróty wiadomo
ś
ci
1
0.4.3 Kod autentyczno
ś
ci wiadomo
ś
ci - MAC
1
0.4.4 Klucze i podpis cyfrowy
1
0.4.5 Kodowanie danych
10.1 Bezpieczeństwo programów i danych
Termin "bezpieczeństwo" ("security") można przykładowo opisać poprzez
funkcjonalność programów, które powinny być:
- wolne od wrogich podprogramów - program nie powinien utrudniać pracy w danym
środowisku oraz powinien być wolny od niezamierzonych podprogramów np.
wirusów;
- "nieinwazyjne" - programy nie powinny mieć dostępu do informacji prywatnych
przechowywanych na komputerze lokalnym lub w sieci (kontrolowany dostęp do
zasobów prywatnych),
- autoryzowane - programy powinny umożliwiać ustalenie i potwierdzenie tożsamości
autora i danych,
- kodowane - programy powinny umożliwiać kodowanie danych,
- kontrolowane - programy powinny umożliwiać tworzenie rejestrów operacji
związanych z zagrożeniem bezpieczeństwa (np. pliki typu *.log),
- sterowane - programy powinny być zabezpieczone przed wykorzystywaniem zbyt
dużej ilości zasobów,
- certyfikowane - programy powinny spełniać wymagania i uzyskiwać certyfikaty
bezpieczeństwa np. C2 czy B1 według systemu opracowanego dla rządu USA i
innych.
10.2 Bezpieczeństwo w Javie
Środowisko Java 1.0 udostępniało pierwsze dwa elementy. Kolejne wersje
Javy wprowadzały dodatkową funkcjonalność programów i tak JAVA 2 umożliwia
spełnienie funkcjonalności zgodnie z pierwszymi pięcioma punktami, z tym, że
kodowanie danych dostępne jest tylko dla obywateli USA i Kanady (ograniczenia
eksportowe) poprzez rozszerzenie JCE (Java Cryptography Engine). Model
bezpieczeństwa tworzony dla aplikacji Javy ewaluował poprzez kolejne wersję
platformy. Począwszy od wersji 1.0 opracowano model, który później nazwano
"piaskownicą". Odwołanie się do piaskownicy ukazuje analogię programu Javy do
dziecka bawiącego się w piaskownicy. Dziecko w piaskownicy ma ograniczony
dostęp do otoczenia (wyznaczany przez rozmiar piaskownicy) oraz ma do dyspozycji
określone zabawki (zasoby). Tak samo program Javy umieszczony w danym
systemie bezpieczeństwa ma takie możliwości jakie daje mu ten system. W wersji 1.0
programy Javy, lub bardziej ogólnie kody dzielone są na zaufane i niezaufane. Kod
zaufany to ten, który znajduje się w lokalnym systemie; kod niezaufany to ten, który
10-3
Jacek Rumi
ń
ski - J
ę
zyk JAVA –
Jacek Rumi
ń
ski - J
ę
zyk JAVA – Rozdzia
ł
1
0
pochodzi ze zdalnych urządzeń (np. z sieci). Kod zaufany ma pełny dostęp (pełny w
sensie danego systemu operacyjnego - jeśli np. plik nie jest do odczytu przez danego
użytkownika w danym systemie operacyjnym, to plik ten będzie również niedostępny
przez kod Javy) do zasobów, kod niezaufany ma dostęp taki, na jaki zezwala mu
"piaskownica". Standardowo wszystkie applety uruchamiane są w obrębie jakiejś
aplikacji np. Netscape, HotJava, appletviewer; które tworzą "piaskownicę" dla danego
appletu. W wersji Java1.0 wszystkie applety nie mają dostępu do zasobów lokalnych,
co jest uwarunkowane przez model bezpieczeństwa tej platformy Javy. Jako
ciekawostkę można podać, że przyczyną dla której nie tworzono dostępu dla
appletów do lokalnych zasobów plików nie był aspekt bezpieczeństwa, lecz fakt, że
docelowo w propagowanej przez Suna technologii komputerów sieciowych takich
zasobów po prostu być nie powinno. Dla aplikacji uruchamianych lokalnie można
również stworzyć programy, które będą ustalać dla nich "piaskownicę". Wówczas
docelowa aplikacja będzie wywoływana jako atrybut programu ustalającego
bezpieczeństwo. Można więc zarówno zdalnie jak i lokalnie ustalić prawa dostępu do
zasobów plików, co jest niezwykle przydatne, szczególnie dla programów
pracujących z danymi chronionymi (np. w medycynie). W wersji JDK 1.1
wprowadzono zmianę w modelu bezpieczeństwa polegającą na tym, że tzw.
podpisany elektronicznie kod (aplet) jest traktowany jako kod zaufany, a co za tym
idzie ma dostęp do lokalnych zasobów komputera. Podpisane kody wraz z kluczami
są dostarczane do systemu w pliku spakowanym JAR. Platforma Java 2 wprowadza
liczne zmiany związane z bezpieczeństwem. Nowy model bezpieczeństwa
przyjmowany przez tą platformę zakłada, że każdy kod (lokalny i zdalny, podpisany
czy nie) podlega kontroli zasad bezpieczeństwa (policy). W Javie 2 nie istnieje już
wbudowany mechanizm dzielący kod na zaufany i niezaufany. Każdy kod podlega
kontroli względem ustawień zasad bezpieczeństwa, które to zasady są spisywane w
plikach konfiguracyjnych JRE lub definiowanych przez użytkownika plikach zasad
bezpieczeństwa. Po kontroli zasad bezpieczeństwa dany kod uzyskuje określone
uprawnienia wynikające z ustawień zasad bezpieczeństwa. Przykładowo aplet A
podpisany prze X może mieć dostęp do plików w lokalnym systemie plików, dający
mu prawo zapisu pliku o nazwie: pliktest. Domyślnie przyjęto, że zasady
bezpieczeństwa dają uprawnienia programom tak jak to było w modelu 1.0, tzn.
zasady bezpieczeństwa dla apletów uniemożliwiają im dostęp do lokalnego zasobu
plików. Określone jest to poprzez fakt, że dla aplikacji nie instalowany jest
automatycznie system zarządzania bezpieczeństwem, tak jak to ma miejsce dla
apletów. W celu uruchomienia aplikacji z działającym systemem zarządzania
bezpieczeństwem należy wywołać interpreter (java) z opcją -Djava.security.manager.
Wówczas aplikacje podlegają takiej samej kontroli bezpieczeństwa jak aplety
poprzez pliki konfiguracyjne ustawień bezpieczeństwa.
Java 2 wprowadza jako rozszerzenia pojęcia "piaskownica" pojęciem "dziedzina".
Otóż w czasie wykonywania kodu, kody grupowane są w grupy kodów
(pochodzących z tego samego źródła - CodeBase) o tych samych prawach dostępu.
Grupy te zwane dalej dziedzinami oznaczają określony zakres dostępu do zasobów
(według ustalonych zasad bezpieczeństwa). Ustalając więc zakres bezpieczeństwa
można uzyskać informację (obiekt klasy PermissionCollection) wywołując metodę
getPermissions() klasy Policy.
Podsumowując można wskazać następujące elementy związane z ustalaniem
zakresu bezpieczeństwa dla aplikacji Javy:
10-4
Jacek Rumi
ń
ski - J
ę
zyk JAVA –
Jacek Rumi
ń
ski - J
ę
zyk JAVA – Rozdzia
ł
1
0
- weryfikacja kodu: weryfikator B-kodu sprawdza czy klasy Javy spełniają prawa
języka Java (klasy zestawu core API nie są sprawdzane);
- ładowanie klas: jeden lub więcej systemów ładowania klas wprowadza wszystkie
klasy, które nie są częścią core API (do wersji Java 2, ładowanie klas wprowadzało
klasy których nie było w ustawieniu CLASSPATH);
- kontrola dostępu: od Javy 2 kontroler dostępu umożliwia lub zabrania dostępu do
systemu operacyjnego;
- zarządzanie bezpieczeństwem: system zarządzania bezpieczeństwem był
szczególnie istotny w wersjach wcześniejszych niż 2, ponieważ zarządzał on
dostępem do zasobów komputera. Od wersji Java 2 system zarządzania
bezpieczeństwem odwołuje się bezpośrednio do kontrolera dostępu;
- pakiet java.security: umożliwia dostęp do powyższych systemów (poprzez szereg
klas i interfejsów np. AccessController, SecurClassLoader) oraz dostarcza szeregu
narzędzi do tworzenia podpisów cyfrowych, kluczy, certyfikatów;
- baza danych kluczy: zbiór kluczy używanych przez system zarządzania
bezpieczeństwem i kontrolera dostępu do sprawdzania podpisów elektronicznych
związanych z podpisanymi plikami klas Javy.
W Javie 2 należy w sposób szczególny omówić kontroler dostępu ponieważ
większość zagadnień bezpieczeństwa jest z nim związana. Kontroler dostępu
(AccessController) jest zbudowany w oparciu o cztery zasadnicze elementy:
- CodeSource; reprezentacja źródła pochodzenia kodu;
- Permissions; reprezentacja uprawnień dostępu;
- Policies; reprezentacja wszystkich uprawnień, które powinny być nadane dla
danego kodu - określenie zasad bezpieczeństwa;
- Protection Domains; reprezentacja konkretnego źródła i wszystkich uprawnień mu
nadanych.
10.3 Obsługa zasad bezpieczeństwa w Javie
Zasady bezpieczeństwa dla platformy Javy są spisane w plikach
konfiguracyjnych. Podstawowym plikiem konfiguracyjnym jest plik java.security
umieszczony standardowo w katalogu <JRE_home>/lib/security. Plik ten zawiera
informacje o lokalizacji pliku zasad bezpieczeństwa, o możliwości tworzenia
własnych (w katalogu domowym) plików zasad bezpieczeństwa, o możliwości
uruchamiania JVM z dodatkowym plikiem bezpieczeństwa ( -
Djava.security.policy=własnyplikbezpieczeństwa), o typie magazynu kluczy oraz o
dostawcy i lokalizacji pakietu mechanizmów bezpieczeństwa (np. algorytmy
kodowania wiadomości, algorytmy generacji podpisów elektronicznych, itp.).
Lokalizacja plików zasad bezpieczeństwa w pliku java.security jest ustalana poprzez
podanie linii typu policy.url.n=URL; gdzie n jest kolejnym plikem zasad, a URL
adresem URL do tego pliku. Pierwszym plikiem zasad bezpieczeństwa jest plik
java.policy znajdujący się w tym samym katalogu co java.security. Ponieważ jest to
pierwszy, domyślny plik zasad to w pliku java.security ustawiona jest następująca
linia konfiguracji: policy.url.1=file:${java.home}/lib/security/java.policy. Jako drugi plik
zasad bezpieczeństwa podaje się plik ustawień dla aktualnego użytkownika (z jego
katalogu domowego) policy.url.2=file:${user.home}/.java.policy. Dalej można tworzyć
dodatkowe pliki zasad bezpieczeństwa, które mogą być dodawane według
omówionej zasady do pliku java.security. Podstawowy plik zasad bezpieczeństwa
10-5
Jacek Rumi
ń
ski - J
ę
zyk JAVA –
Jacek Rumi
ń
ski - J
ę
zyk JAVA – Rozdzia
ł
1
0
(oraz inne) zawiera wskazanie na magazyn kluczy (koniecznych przy potwierdzaniu
podpisanych kodów) oraz szereg pozycji zawierających CodeSource (źródło kodu),
identyfikator podpisu (jeśli taki jest użyty), oraz zestaw uprawnień (Permissions).
Poniżej zaprezentowano zawartość pliku standardowego java.policy:
// Standard extensions get all permissions by default
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
// default permissions granted to all domains
grant {
// Allows any thread to stop itself using the java.lang.Thread.stop()
// method that takes no argument.
// Note that this permission is granted by default only to remain
// backwards compatible.
// It is strongly recommended that you either remove this permission
// from this policy file or further restrict it to code sources
// that you specify, because Thread.stop() is potentially unsafe.
permission java.lang.RuntimePermission "stopThread";
// allows anyone to listen on un-privileged ports
permission java.net.SocketPermission "localhost:1024-", "listen";
// "standard" properies that can be read by anyone
permission java.util.PropertyPermission "java.version", "read";
permission java.util.PropertyPermission "java.vendor", "read";
permission java.util.PropertyPermission "java.vendor.url", "read";
permission java.util.PropertyPermission "java.class.version", "read";
permission java.util.PropertyPermission "os.name", "read";
permission java.util.PropertyPermission "os.version", "read";
permission java.util.PropertyPermission "os.arch", "read";
permission java.util.PropertyPermission "file.separator", "read";
permission java.util.PropertyPermission "path.separator", "read";
permission java.util.PropertyPermission "line.separator", "read";
permission java.util.PropertyPermission "java.specification.version", "read";
permission java.util.PropertyPermission "java.specification.vendor", "read";
permission java.util.PropertyPermission "java.specification.name", "read";
permission java.util.PropertyPermission "java.vm.specification.version", "read";
permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
permission java.util.PropertyPermission "java.vm.specification.name", "read";
permission java.util.PropertyPermission "java.vm.version", "read";
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};
Ustawienia plików zasad bezpieczeństwa odbywają się poprzez edycję tekstowych
plików za pomocą edytora lub poprzez standardowe narzędzie dostarczane z Java 2
10-6
Jacek Rumi
ń
ski - J
ę
zyk JAVA –
Jacek Rumi
ń
ski - J
ę
zyk JAVA – Rozdzia
ł
1
0
tzn. policytool. Policytool jest aplikacją JAVY umożliwiającą tworzenie i edycję plików
zasad bezpieczeństwa. Zanim zaprezentowane zostaną przykłady należy odnieść się
do wymienionych wcześniej elementów kontrolera dostępu. W świetle znanych już
metod ustalania zasad bezpieczeństwa w plikach konfiguracyjnych łatwo
wytłumaczyć znaczenie czterech wymienionych elementów kontrolera dostępu. Po
pierwsze obiekt klasy CodeBase reprezentuje kod (źródło), który jest lub będzie
związany z określonymi uprawnieniami. Po drugie dla abstrakcyjnej klasy Permission
istnieją końcowe klasy oznaczające konkretne uprawnienia. Te końcowe klasy
uprawnień charakteryzują się trzema cechami: typem - oznaczającym w nazwie klasy
typ uprawnień z nią związanych np. FilePermission, SocketPermission; nazwą -
określającą cel z którym związane są dane uprawnienia (element String oznaczający
URL, plik, itp.); akcją – określającą rodzaj uprawnień dla danego typu (np. dla
FilePermission: read, write, execute,delet; dla SocketPermission: accept, listen,
connect, resolve). Obiekt klasy końcowej np. FilePermission nie nadaje uprawnień w
systemie operacyjnym (np. plikowi nie nadawane są uprawnienia w systemie
operacyjnym lecz w środowisku Javy). Klasy końcowych uprawnień (oprócz
BasicPermission-przydatna przy implementacji własnych typów uprawnień- i
SecurityPermission) znajdują się poza pakietem java.security i są umieszczane w
pakietach związanych z typem uprawnień np. FilePermission jest w pakiecie java.io;
SocketPermission jest w pakiecie java.security, itd. Ponieważ elementarne
uprawnienia mogą być mnogie dla danego typu uprawnień (np. ustawiany jest
dostęp do odczytu plików z katalogu /tmp oraz drugie uprawnienie dostęp do odczytu
plików z katalogu /java/test) stworzono klasę PermissionCollection, której obiekty
reprezentują zbiór uprawnień.
Obiekty klasy Permissions reprezentują natomiast kolekcję obiektów klasy
PermissionCollection. W ten sposób można pogrupować różne uprawnienia, które
później zostaną przydzielone konkretnemu kodowi w celu stworzenia dziedziny
uprawnień. Po trzecie klasa Policy ustala odwzorowanie pomiędzy kodem źródłowym
a uprawnieniami. Obiekt klasy Policy jest inicjowany głównie poprzez interpretacje
plików zasad bezpieczeństwa (java.policy). Zasady bezpieczeństwa są więc ustalane
zewnętrznie względem kodu. Po czwarte przydzielenie konkretnemu kodowi
CodeSource grupy uprawnień Permissions powoduje stworzenie dziedziny
uprawnień (obiekt klasy ProtectionDomain). Obiekt klasy ProtectionDomain
reprezentuje więc scaloną część w pliku konfiguracyjnym zasad bezpieczeństwa
wydzieloną poprzez fragment: grant CodeBase SignedBy {Permissions}(przykładowo
w powyższym pliku java.policy).
Omawiając elementy związane z uprawnieniami w Javie warto podkreślić
elastyczność określania celu działania danego uprawnienia. Cel działania danego
uprawnienia np. FilePermission może być ustalony poprzez podanie konkretnego
elementu lub poprzez wykorzystanie różnych znaków zastępczych. Przykładowo dla
uprawnień FilePermission możliwe są następujące kody sterujące:
file (oznacza konkretną nazwę pliku w bieżącym katalogu);
directory (oznacza konkretną nazwę katalogu);
directory/file (oznacza konkretną nazwę pliku w danym katalogu);
directory/* (oznacza wszystkie pliki w danym katalogu);
* (oznacza wszystkie pliki w bieżącym katalogu);
directory/- (oznacza wszystkie pliki w danym katalogu i jego podkatalogach);
- (oznacza wszystkie pliki w bieżącym katalogu i jego podkatalogach);
"<<ALL FILES>>" (oznacza wszystkie pliki w systemie plików).
10-7
Jacek Rumi
ń
ski - J
ę
zyk JAVA –
[ Pobierz całość w formacie PDF ]