www.hakin9.org
hakin9 Nr 11/2007
62
Obrona
T
echnologia ta pozwala na tworzenie bo-
gatych, atrakcyjnych wizualnie interfej-
sów użytkownika, które mogą pracować
w dowolnym środowisku – w przeglądarkach in-
ternetowych, na różnych urządzeniach i na róż-
nych systemach operacyjnych (np. Apple Macin-
tosh). Podobnie jak w przypadku WPF (Windows
Presentation Foundation), technologii prezenta-
cyjnej stworzonej wraz z .NET Framework 3.0,
podstawą Silverlight jest język XAML (eXtensible
Application Markup Language). Technologia ta,
pomimo tego, że jest ciągle w fazie rozwojowej
(w chwili obecnej dostępne są dwie wersje
Silverlight – 1.0 RC, czyli kandydat do wersji osta-
tecznej oraz wersja 1.1 alfa), staje się coraz bar-
dziej popularna i wciąż rośnie liczba serwisów
używających jej do celów prezentacji treści. Przy
tej okazji bardzo często padają pytania o bezpie-
czeństwo aplikacji opartych o Silverlight, głównie
ze względu na obsługę wielu platform. Artykuł
ma na celu wprowadzenie i ogólne przedstawie-
nie modelu bezpieczeństwa tej technologii.
Trudne początki, czyli wstęp
do modelu bezpieczeństwa
Jak wiadomo, już od samego początku założe-
niem nowej technologii było stworzenie minimal-
nego silnika do uruchamiania aplikacji opar-
tych o Silverlight, czyli de facto o .NET.
Silverlight zawiera bardzo mocno okrojoną
wersję CLR (Common Language Runtime).
Całość zajmuje ok. 5 MB. Znając podstawy
programowania w .NET Framework oraz obję-
tość wszystkich bibliotek i powiązań, można
się zastanawiać, jak to wszystko działa –
a w szczególności, jak rozwiązane są aspekty
bezpieczeństwa. Przecież każdy programista,
który pisał bezpieczne aplikacje, musiał poz-
nać różnorodne aspekty takich narzędzi, jak
Bezpieczeństwo
Silverlight
Artur Żarski
stopień trudności
Podczas konferencji MIX’07, która odbyła się na początku
maja 2007 roku w Las Vegas, została pokazana nowa technologia
prezentacji zawartości stron WWW. Jest nią Silverlight,
która z założenia ma działać na różnorodnych platformach.
Z artykułu dowiesz się
• nowości w modelu bezpieczeństwa technologii
Silverlight i jego aspektów istotnych dla progra-
misty.
Co powinieneś wiedzieć
• czytelnik powinien mieć wiedzę na temat tworze-
nia bezpiecznych aplikacji na platformie .NET,
• znać pojęcia takie jak CAS, kod przeźroczy-
sty, kod krytyczny oraz podstawowe elemen-
ty przestrzeni nazw System.Security.
Bezpieczeństwo Silverlight
hakin9 Nr 11/2007
www.hakin9.org
63
caspol.exe i specyfikę bezpieczeń-
stwa opartego na uprawnieniach
kodu (CAS – Code Access Security).
Bardzo dobrą informacją dla wszyst-
kich, którzy spędzili długie godziny
na rozgryzaniu działania tego roz-
wiązania oraz wszystkich jego usta-
wień jest to, że dla Silverlight po
prostu przestało ono istnieć. Stan-
dardowy CAS znany z pełnej wersji
.NET został wycofany.
W CoreCLR (tak nazywa się
CLR w Silverlight) nie znajdziemy już
uprawnień, poziomów zabezpieczeń
oraz przejść po stosie zabezpie-
czeń. Przestrzeń nazw System.Se-
curity została bardzo mocno ogra-
niczona. Wnikliwi programiści, któ-
rzy wykonają dekompilację biblioteki
mscorlib.dll, zauważą jednak, że kla-
sa
SecurityPermission
nadal istnie-
je. O co więc chodzi? Jeśli nasza bi-
blioteka zawiera jakiś niesprawdzo-
ny kod, wtedy kompilator wywoła fla-
gę
RequestMinimum
dla właściwości
SkipVerification
.
Model bezpieczeństwa w Co-
reCLR, który musi zastąpić CAS,
może zostać opisany następująco:
• każdy kod użytkownika, który
uruchamiany jest w CoreCLR,
jest zupełnie przeźroczysty,
• kod platformy (charakterystycz-
ny dla danego systemu opera-
cyjnego) może zawierać dwa
rodzaje kodu: przeźroczysty i kry-
tyczny. Jest on odpowiedzialny
za umożliwienie uruchomienia
przeźroczystego kodu w taki
sposób, aby miał on bezpieczny
dostęp do różnych usług syste-
mowych.
Reasumując, oznacza to, że w mo-
delu bezpieczeństwa CoreCLR apli-
kacje Silverlight nie mogą zawierać
kodu, który nie jest zweryfikowany
i mogą wywoływać tylko i wyłącznie
metody API, które są przeźroczyste
lub krytyczne.
Zagłębiamy się
w szczegóły
No dobrze, ale czym właściwie jest
kod przeźroczysty? Jest to taki kod,
który nie może wykonać żadnej ak-
cji skutkującej odwołaniem do sto-
su uprawnień. A dokładniej, prze-
źroczysty kod nie może w żaden
sposób spowodować sprawdzenia
zabezpieczeń, które zakończy się
sukcesem (może natomiast zakoń-
czyć się niepowodzeniem). Przeci-
wieństwem jest kod krytyczny, któ-
rego biblioteki mogą zawierać kom-
binacje kodu krytycznego i przeźro-
czystego. Pojedyncze metody mo-
gą być przeźroczyste lub krytycz-
ne, jednak nie mogą łączyć obu ro-
dzajów kodu.
Ograniczenia dla kodu przeźro-
czystego:
• nie może wykorzystywać atrybu-
tu LinkDemand,
• nie może wywoływać Assert
w CAS,
• nie może zawierać nieweryfiko-
walnego kodu,
• nie może wywoływać natywne-
go kodu przy użyciu P/Invoke lub
COM Interop,
• nie może zapewniać dostępu
do kodu krytycznego lub da-
nych tam, gdzie nie jest to po-
trzebne.
Na początku tekstu mówiliśmy, że
w Silverlight nie ma CAS, więc o co
chodzi w pierwszych dwóch ograni-
czeniach? Przecież bez Code Ac-
cess Security nie można wywołać
Assert, a nawet zwykłego LinkDe-
mand. Póki nie mamy koncepcji żą-
dań w Silverlight, którego mecha-
nizm wywołania nie jest właściwy,
zamiast tego wywołujemy wyjątek
klasy
MethodAccessException
– o ile
kod przeźroczysty próbuje złamać
ustalone zasady. Najbardziej inte-
resujące jest ostatnie ograniczenie.
W przypadku, gdy kod przeźro-
czysty próbuje bezpośrednio wy-
wołać kod krytyczny, to wywołany
będzie wyjątek klasy
MethodAccess-
Exception
. Niemniej jednak więk-
szość z interesujących nas usług
wymaga implementacji jako kod
krytyczny (np. dostęp do systemu
plików). Jeśli mamy do czynienia
z takim właśnie przypadkiem, to jak
Silverlight może uzyskać dostęp do
tego typu usług?
Wspominałem wcześniej o tym,
że dostęp do plików oraz wszelkie
operacje wejścia/wyjścia powinny
być implementowane jako bezpie-
czny kod. Aby mieć możliwość trwa-
łego przechowywania danych, mu-
simy posiadać jakąś warstwę dla ko-
du krytycznego, który będzie mógł
być wywoływany. W Silverlight tą
krytyczną warstwą jest
Isolated-
Storage
. Kiedy aplikacja Silverlight
wywołuje
IsolatedStorage
, wtedy
API sprawdza żądanie, aby mieć
pewność, że aplikacja żąda prawi-
dłowego pliku i że nie jest prze-
kroczony dla niej tzw. przydział
(ang. quote). Jest to analogiczne do
modelu wywołań w systemie ope-
racyjnym (patrz Tabela 1).
Podobnie jak aplikacje urucha-
miane na MacOS i Windows nie
mogą odwoływać się bezpośred-
nio do jądra systemu operacyjnego
bez przejścia przez powłokę wywo-
łań systemowych, tak też aplikacje
Silverlight nie mogą bezpośrednio
wywoływać krytycznego kodu bez
przejścia przez bezpieczną powło-
kę krytyczną. W Silverlight cały kod
jest standardowo przeźroczysty (i to
odróżnia go od CLR w wersji desk-
top, gdzie cały kod z definicji jest
krytyczny).
Tabela 1.
Przykłady zastosowania IsolatedStorage
System operacyjny
CoreCLR
Przykład IsolatedStorage
Kod w trybie użytkownika
Kod przeźroczysty
Aplikacja Silverlight
Wywołanie systemowe
Bezpieczne krytyczne API
System.IO.IsolatedStorage
Kod jądra
Krytyczne API
System.IO.FileStream
hakin9 Nr 11/2007
www.hakin9.org
Obrona
64
Kod platformy może być prze-
źroczysty, krytyczny oraz bezpie-
czny krytyczny (ang. safe critical).
CoreCLR automatycznie wykryje
kod platformy, wiedząc, skąd ła-
dowana jest biblioteka (bibliote-
ki platformy muszą być ładowane
z katalogu, w którym jest zainsta-
lowany Silverlight) oraz poprzez
sprawdzenie klucza publicznego,
którym ta biblioteka została pod-
pisana. Tylko i wyłącznie biblioteki
podpisane specyficznym kluczem,
którym podpisuje je Microsoft, bę-
dą traktowane jako biblioteki plat-
formy.
Jeśli metoda w bibliotece plat-
formy jest opisana atrybutem
Secu
rityCriticalAttribute
, oznacza to,
że zawiera ona kod krytyczny. Kod
przeźroczysty nie może wywołać
żadnej metody kodu krytycznego
– nawet, jeśli jest ona publiczna.
Każda próba złamania tej reguły
spowoduje wywołanie wyjątku
Me-
thodAccessException
.
Listing 1. pokazuje konstruktor
dla klasy FileStream w Silverlight 1.1.
Jest on krytyczny (widać to w linii 5),
ponieważ został opisany atrybutem
SecurityCriticalAttribute.
Podobnie jest z każdą metodą
w klasie Marshal – są one również
krytyczne, dopóki będą opisane atry-
butem
SecurityCriticalAttribute
(li-
nia 4 na Listingu 2).
Każda metoda w bibliotece plat-
formy oznaczona atrybutem
Securi
tySafeCriticalAttribute
jest oczy-
wiście bezpieczna krytyczna (safe
critical). Kod aplikacji może wywoły-
wać te metody, dopóki kod przeźro-
czysty może wywoływać bezpiecz-
ny kod krytyczny. Przykładem kry-
tycznego API jest metoda Isolated-
StorageFileStream.Write (linia 6 na
Listingu 3).
Ciekawostką jest fakt, że atrybut
SecuritySafeCriticalAttribute
jest
w rzeczywistości połączeniem dwóch
atrybutów z pełnej wersji .NET:
Secur
ityCriticalAttribute
oraz
SecurityT
reatAsSafeAttribute
.
Potrzeba jawnego określania
metod atrybutami SecurityCritical
oraz
SecurityTreatAsSafe
stała się
powszechna, dlatego też stworzo-
no atrybut
SecuritySafeCritical
.
Dzięki stosowaniu tego atrybutu
skracamy czas pisania aplikacji,
a dodatkowo zmniejszamy wielkość
metadanych. Jeśli metoda nie po-
siada ani atrybutu
SecurityCritical
,
ani atrybutu
SecuritySafeCritical
,
wtedy musi być ona przeźroczy-
sta. Jeśli metoda jest widoczna dla
kodu aplikacji, oznacza to, że apli-
kacja ma możliwość wywołania
jej – ponieważ przeźroczysty kod
ma zawsze możliwość wywołania
innego transparentnego kodu.
Dokładnie tak samo jest w sy-
tuacji, w której aplikacja Silverlight
chciałaby być sprytna i opisać się
jednym z atrybutów
SecurityCritical
lub
SecuritySafeCritical
. W tym mo-
mencie nie wydarzy się nic, ponie-
waż CLR wie, że kod aplikacji musi
być przeźroczysty.
Bardzo ważnym jest fakt, że re-
guły te nie zastępują standardowych
reguł dostępu (Public, Private, Inter-
nal), ale je dopełniają. Dlatego też
kod aplikacji nie może wywoływać
wewnętrznych metod w bibliotekach
systemowych – nawet, jeśli są one
przeźroczyste.
Tabela 2. pokazuje wszystkie te
zależności.
Dziedziczenie
Na koniec jeszcze kilka słów na te-
mat dziedziczenia w Silverlight. Na
początek określmy jednak logicz-
ny porządek pomiędzy poziomami
transparentności:
•
przeźroczysty (aplikacja i platfor-
ma),
Listing 1.
Przykład konstruktora dla klasy FileStream
1
.
method
public
hidebysig
specialname
rtspecialname
2
instance
void
.
ctor
(
string
path
,
3
valuetype
System
.
IO
.
FileMode
mode
)
cil
managed
4
{
5
.
custom
instance
void
System
.
Security
.
SecurityCriticalAttribute
::
.
ctor
()
=
(
01
00
00
00
)
6
7
// ...
8
}
Listing 2.
Przykład metody w klasie Marshal
1
.
class
public
abstract
auto
ansi
sealed
beforefieldinit
System
.
Runtime
.
Inte
ropServices
.
Marshal
2
extends
System
.
Object
3
{
4
.
custom
instance
void
System
.
Security
.
SecurityCriticalAttribute
::
.
ctor
()
=
(
01
00
00
00
)
5
6
// ...
7
}
//
end
of
class
System
.
Runtime
.
InteropServices
.
Marshal
Listing 3.
Metoda IsolatedStorageFileStream.Write.
1
.
method
public
hidebysig
virtual
instance
void
2
Write
(
uint8
[]
buffer
,
3
int32
offset
,
4
int32
count
)
cil
managed
5
{
6
.
custom
instance
void
System
.
Security
.
SecuritySafeCriticalAttribute
::
.
ctor
()
=
(
01
00
00
00
)
7
8
// ...
9
}
Bezpieczeństwo Silverlight
hakin9 Nr 11/2007
www.hakin9.org
65
•
bezpieczny krytyczny (tylko plat-
forma),
•
krytyczny (tylko platforma).
Ale jak się to ma do dziedziczenia?
Otóż kolejność ta jest bardzo istot-
na, kiedy chcemy określić czy da-
na klasa może pochodzić z kla-
sy rodzica. Każda klasa może po-
chodzić z innej, ale tylko i wyłącz-
nie z takiej, która jest na takim sa-
mym lub wyższym poziomie hierar-
chii. Nie może ona nigdy pocho-
dzić z niższej klasy bazowej w hie-
rarchii. Oznacza to, że klasy kry-
tyczne mogą pochodzić z innych
dowolnego typu, podczas gdy kla-
sy transparentne mogą pochodzić
tylko i wyłącznie z innych transpa-
rentnych.
Kolejną istotną kwestią jest moż-
liwość przeciążania metod wirtu-
alnych podczas dziedziczenia. Kie-
dy chcemy przeciążać metody, war-
to je wcześniej pogrupować we-
dług różnych poziomów bezpieczeń-
stwa:
•
przeźroczysty oraz bezpieczny
krytyczny kod,
•
kod krytyczny.
Po pogrupowaniu metod w taki wła-
śnie sposób zauważyć można, że
kod przeźroczysty ma dostęp do
wszystkiego, podczas gdy kod kry-
tyczny ma dostęp do grupy z pozio-
mu drugiego. Te same reguły sto-
suje się podczas implementacji in-
terfejsów. Wszystkie te reguły dzie-
dziczenia można opisać za pomo-
cą następujących zasad:
•
typy mogą pochodzić tylko z ty-
pów bazowych, które są przeźro-
czyste,
•
tylko przeźroczyste lub bezpiecz-
ne krytyczne metody mogą być
nadpisywane,
•
tylko transparentne lub krytycz-
ne-bezpieczne metody interfej-
su mogą być implementowane.
Podsumowanie
Jak widać, model bezpieczeństwa
Silverlight znacznie odbiega od tego,
który znamy z pełnej wersji .NET Fra-
mework. Został on znacznie uprosz-
czony, dzięki czemu jest łatwiejszy
w implementacji. Ważne jest, aby pro-
gramista zwracał uwagę na wszyst-
kie wymienione kwestie. l
Tabela 2.
Zależności przy stosowaniu różnych atrybutów i możliwość
wywoływania metod
Atrybut
bezpieczeństwa
Rodzaj
Możliwość
wywołania
przez kod
aplikacji
(jeśli metoda
jest widoczna)
Kod aplikacji
-
Przeźroczysty
Tak
Platforma
None
Przeźroczysty
Tak
Platforma
SecuritySafe
Critical
Bezpieczny
krytyczny
Tak
Platforma
SecurityCritical
Krytyczny
Nie
O autorze
Autor jest pracownikiem firmy Microsoft. Na co dzień zajmuje się m. in. tworze-
niem rozwiązań w oparciu o SQL Server w różnych aspektach – bazy relacyjne,
usługi integracyjne, usługi analityczne. Jest certyfikowanym administratorem baz
danych (MCDBA). W wolnych chwilach pasjonat fotografii.
Kontakt z autorem: arturz@microsoft.com