background image

56

 

OBRONA

HAKIN9 4/2008

P

rzy tworzeniu bezpiecznych programów 
naley zwróci szczególn uwag na kilka 
istotnych czynników wpywajcych na 

ogólne bezpieczestwo rozwizania. Cay tekst 
bazuje na przykadzie systemu Windows i 
aplikacji pisanych na platformie .NET.
Problem bezpieczeństwa aplikacji jest bardzo 
szeroko omawianym tematem w różnego 
rodzaju opracowaniach. Niemniej jednak 
warto kompleksowo przyjrzeć się tej kwestii. 
Ogólnie przyjętym stwierdzeniem jest potrzeba 
znalezienia złotego środka przy tworzeniu 
poszczególnych rozwiązań. Należy bardzo 
mocno wyważyć bezpieczeństwo z łatwością 
użycia aplikacji przez użytkowników końcowych. 
Każda aplikacja może być bardzo bezpieczna 
i uwzględniać wszystkie możliwe aspekty 
bezpieczeństwa, ale z drugiej strony będzie 
wtedy na pewno niewygodna w obsłudze. Jeśli 
przekształcimy to stwierdzenie, będziemy mogli 
powiedzieć, że programy łatwe w użyciu są 
aplikacjami niebezpiecznymi. No właśnie, ale 
czy aby na pewno tak jest? 

Bezpieczeństwo aplikacji

Bezpieczeństwo to kilka różnego rodzaju 
warstw, a co za tym idzie – różne elementy 
chroniące nasz system. Jeśli przyjrzymy się 
Rysunkowi 1, zobaczymy, w jaki sposób można 
umiejscowić takie warstwy.

Dane i aplikacja to oczywiście kluczowe 

elementy układanki. Oczywiście oba z tych 

ARTUR ŻARSKI

Z ARTYKUŁU 

DOWIESZ SIĘ

o podstawowych zagadnieniach, 

które mogą podnieść 

bezpieczeństwo tworzenia 

i wdrażania aplikacji.

CO POWINIENEŚ 

WIEDZIEĆ

znać podstawową znajomość 

C/C++,

pojęcia związane 

z bezpieczeństwem danych.

elementów posiadają własne zabezpieczenia. 
I tak, dane mogą być szyfrowane przy pomocy 
EFS (Encrypted File System) oraz BitLocker’a
Do zabezpieczeń może być użyty IRM oraz 
RMS, a całość dodatkowo chroniona będzie 
przy pomocy ACL w NTFS. Aplikacja natomiast 
posiada własne zabezpieczenia dostępu, 
dobrze zdefiniowaną architekturę, kod oraz 
różnego rodzaju procedury walidacji.

Idąc dalej – nasz serwer (host) posiada 

zabezpieczenia systemu operacyjnego. Ma 
hasła dostępu do tegoż systemu operacyjnego. 
Dodatkowo jest często aktualizowany 
– wgrywane są zawsze najnowsze poprawki 
bezpieczeństwa. Użytkownicy mają możliwość 
użycia SmartCard z zainstalowanymi 
certyfikatami. 

Kolejny istotny element to cała infrastruktura 

sieciowa. Może być zabezpieczona przy 
pomocy IPSec czy IDS. Krańce sieci 

Stopień trudności

Bezpieczne a 

niebezpieczne 

aplikacje

Aplikacje i ich bezpieczeństwo to nie tylko i wyłącznie proces 

ich tworzenia, to również modelowanie zagrożeń, projektowanie 

rozwiązania oraz architektura. Wszystkie te czynniki składają się 

na stworzenie bezpiecznej lub niebezpiecznej aplikacji. 

Listing 1. 

Przykład przepełnienia bufora

int

 

ryzykowna1

(

char

 

*

 

pLancuch

)

 

{

 

int

 

nLicznik

 

=

 

0

;

 

char

 

pBufor

[

_MAX_PATH

]

;

strcpy

(

pBufor

pLancuch

);

 

for

(;

pBufor

;

 

pBufor

++)

 

if

 

(*

pBufor

 

==

 '\\'

)

 

nLicznik

++;

 

return

 

nLicznik

;

}

background image

57

 

BEZPIECZNE A NIEBEZPIECZNE APLIKACJE

HAKIN9 

4/2008

korporacyjnej (na rysunku granica sieci) 
zabezpieczone są przy pomocy firewall’a
a użytkownicy łączący się przy pomocy 
VPN, zanim uzyskają dostęp do sieci, 
przechodzą kwarantannę sprawdzającą 
'poprawność' komputera. Mając serwer 
oraz infrastrukturę pozostaje nam 
zapewnienie fizycznego bezpieczeństwa 
– czyli serwerownia ze strażnikami, 
dobrze zamkniętymi drzwiami, 
monitoringiem etc. 

Ostatnim, ale jednym z 

najważniejszych, elementem jest 
świadomość użytkowników (prawników 
firmy). Należy te osoby edukować, mówić 
im, czym jest bezpieczeństwo, 'przestawiać' 
na bezpieczne myślenie (np. stanowczo 
eliminować żółte karteczki z zapisanym 
hasłem, przyklejane pod biurkiem).

Wszystkie te elementy mogą 

wydawać się oczywiste, niemniej jednak 
bardzo często zdarza się, że krytyczne 
aplikacje uruchamiane są 'tymczasowo' 
pod biurkiem administratorów lub 
programistów. Do tego wszystkiego 
dochodzi jeszcze problem analogowo-
cyfrowy, w przypadku którego jedynym 
punktem jest ostatni z wymienionych 
wcześniej – a więc świadomość 
zagrożeń (Rysunek 2 – źródło Internet).

Modelowanie zagrożeń

Modelowanie zagrożeń to rodzaj 
analizy bezpieczeństwa, którego 
celem jest zwiększenie sumarycznego 
bezpieczeństwa aplikacji. Należy przy 

tym pamiętać, że zagrożenie nie oznacza 
słabego punktu. Na sumaryczne 
bezpieczeństwo aplikacji składa się kilka 
czynników: znalezienie luk infrastruktury, 
ocena zagrożeń bezpieczeństwa czy 
określenie środków zaradczych. Na 
czym polegają poszczególne czynniki? 
Jest to przykładowo analiza wszystkich 
możliwych wejść do systemu, w 
szczególności miejsc, w których z 
zewnątrz dostarczane są dane – np. 
API, gniazda, Web Service, pliki czy 
dane wprowadzane bezpośrednio 
przez użytkownika systemu. Następnie 
sprawdzanie zasobów, czyli wszystko, co 
może być potencjalnym źródłem ataku – 
na przykład dane, pliki konfiguracyjne etc. 
Modelowaniu podlega również poziom 
uprzywilejowania, czyli role użytkownika 
potrzebne do wejścia do systemu czy 

uzyskania praw dostępu do zasobów, a 
także sposób autoryzacji. 

Istnieje kilka metod modelowania 

zagrożeń, wśród nich technika STRIDE 
(SpoofingTamperingRepudiation
Information disclosureDenial of service
Elevation of privilege). Poszczególne 
odpowiedniki rodzajów zagrożeń wraz z 
przykładami przedstawia Tabela 1.

Do tego mamy jeszcze ocenę 

zagrożeń DREAD (Damage Potential, 
ReproducibilityExploitabilityAffected 
UsersDiscoverability), czyli kolejno:

•   D – Możliwość zniszczeń,
•   R – Powtarzalność,
•   E – Możliwość wykorzystania,
•   A – Użytkownicy, których dotyczy 

problem,

•   D – Możliwość wykrycia. 

Rysunek 1. 

Warstwy bezpieczeństwa 

systemów

����

���������

��������������������

����

�������������

�����������������������

������������������������

�����������������

Tabela 1. 

Techniki określania zagrożeń STRIDE

Fałszowanie

Fałszowanie wiadomości e-mail 

Powtarzanie uwierzytelniania

Zniekształcanie

Zmiana danych podczas transmisji

Zmiana danych w bazie danych

Zaprzeczanie

Usunięcie istotnych danych i zaprzeczanie temu

Zakup produktu i zaprzeczanie temu

Ujawnianie informacji

Ujawnianie informacji w komunikatach o błędach

Ujawnianie kodu w witrynie sieci Web

Odmowa usługi

Zalewanie usługi sieci Web nieprawidłowymi żądaniami

Zalewanie sieci pakietami SYN

Podwyższanie uprawnień

Uzyskiwanie uprawnień administratora

Używanie zestawu w pamięci GAC do tworzenia konta

Tabela 2. 

Analiza potencjalnych zagrożeń

Zagrożenie

D R

E

A

D Razem

Ocena

Napastnik uzyskuje poświadczenia

3

3

2

2

2

12

Wysoka

Wstrzyknięcie poleceń SQL

3

3

3

3

2

14

Wysoka

Tabela 3. 

Przydatne przełączniki oraz dodatkowe biblioteki

Przełącznik/Biblioteka

Uwagi

/GS: Przepełnienie stosu 

Skuteczność 100% 

/GS: Przekierowanie wskaźnika, zmiana 

wartości EBP 

Skuteczność niska (chyba że trafi na adres 

zwrotny) 

RTC: stos niezerowy 

Pomoc przy śledzeniu 

PREfast: analizator kodu 

Pożyteczny; dodatkowe ostrzeżenia 

SAL:dodatkowe adnotacje (_deref, _ecount 

…)

Duża skuteczność; wykrycie „losowych” 

błędów; pomoc w analizie 

Application Verifier 

Dobry pomocnik testera 

ACGP: rozrzucenie kodu w segmencie 

Duża skuteczność; wykrycie „losowych” 

błędów 

background image

OBRONA

58

 

HAKIN9 4/2008

BEZPIECZNE A NIEBEZPIECZNE APLIKACJE

59

 

HAKIN9 

4/2008

Do każdej z kategorii należy przypisać 
odpowiednią wagę zagrożenia – np. 
Wysokie (3), Średnie (2) oraz Niskie 
(1). Analizując potencjalne zagrożenia 
możemy określić jego ocenę. Przykład 
znajduje się w Tabeli 2.

Proces modelowania zagrożeń został 

opisany przez Microsoft już jakiś czas 
temu i przedstawia się następująco:

•   Zidentyfikować zasoby – czyli 

określenie typów danych, które mogą 
być interesujące dla napastników.

•   Stworzyć przegląd architektury – 

analiza komponentów pod względem 
wejść aplikacji. 

•   Dekompozycja aplikacji – analiza 

funkcji aplikacji (każdej z osobna) i 
określenie ścieżek przepływu danych.

•   Identyfikacja zagrożeń – określenie 

potencjalnych błędów w aplikacji 
oraz potencjalnych miejsc ataku.

•   Dokumentacja zagrożeń – spisanie 

wszystkich zagrożeń.

•   Ocena poziomu zagrożenia 

– określenie możliwości wykrycia 
i wystąpienia poszczególnych 
zagrożeń.

Wewnątrz firmy Microsoft stosowana 
jest metodologia Security Development 
Lifecycle. Wykorzystywana ona była 
między innymi przy tworzeniu SQL 
Server 2005, systemów Windows Vista 
oraz Windows Server 2008. Zgodnie z 
tą metodyką należy zwrócić uwagę na 
pewne zasady:

•   Okresowe OBOWIĄZKOWE szkolenia 

z zakresu bezpieczeństwa dla 
WSZYSTKICH zaangażowanych w 
proces tworzenia aplikacji.

•   Doradca bezpieczeństwa dla 

KAŻDEGO komponentu.

•   Modelowanie zagrożeń jako część 

procesu projektowego.

•   Przeglądy bezpieczeństwa i 

testowanie przewidziane w 
harmonogramie projektu.

•   Zdefiniowanie i stosowanie metryk 

bezpieczeństwa dla zespołów 
projektowych.

Trochę praktyki

Oprócz ogólnych elementów 
bezpieczeństwa systemu 
informatycznego, baczną uwagę należy 
również zwrócić na sposób pisania 
kodu naszej aplikacji. Warto zwrócić 
uwagę na: 

•   Bezpieczeństwo w projektowaniu 

i implementacji – jest to proces 
kładący nacisk na bezpieczeństwo 
oprogramowania, który również 
podlega modelowaniu zagrożeń. 
Szczególną uwagę należy 
zwrócić na audyt kodu oraz testy 
bezpieczeństwa. 

•   Bezpieczne wartości domyślne 

– dzięki którym minimalizujemy 
możliwy obszar sposobów ataku 
(attack surface).

•   Bezpieczna instalacja – warto 

również zwrócić uwagę na ten 

Rysunek 3. 

Dekompozycja aplikacji

������

�����������

����

���������

�������

�����������

�����������

���������

�����

��

���������

�����������

������������

�������

����

������������

�������������

�����������

�����

Rysunek 2. 

Problem analogowo-cyfrowy

background image

OBRONA

58

 

HAKIN9 4/2008

BEZPIECZNE A NIEBEZPIECZNE APLIKACJE

59

 

HAKIN9 

4/2008

aspekt, aby wykorzystać mechanizmy 
systemu operacyjnego i .NET 
Framework (np. CAS – Code Access 
Security).

Przykładów niebezpiecznego kodu 
jest wiele – najbardziej popularnym 
z nich jest przepełnienie bufora. 
Jest to zazwyczaj główna przyczyna 
problemów, spotykana najczęściej w 
przypadku kodu natywnego (C/C++
oraz API systemu operacyjnego. 
Ogólnie rzecz ujmując, polega na 
nadpisaniu „za dużym” parametrem 
stosu lub sterty, przepełnienia licznika 
czy też przekroczenia zakresu tablicy. 
Stosowanie pewnej grupy dobrze 
opisanych funkcji (do których można 
zaliczyć strcpy, gets, scanf, sprintf, strcat 
i inne) zwiększa ryzyko powstawania 
przepełnień bufora, dlatego ich 
stosowanie jest gorąco odradzane. 
Przykład błędu przedstawiony jest na 
Listingu 1.

Na Listingu 1 w kodzie od razu 

widać słaby punkt — parametr pBufor 
może zostać przepełniony, jeśli bufor 
wskazywany przez pLancuch jest dłuższy 
niż 

_ MAX _ PATH

.

Można oczywiście wykryć część 

tego typu problemów, wykorzystując 
odpowiednie przełączniki kompilatora i 
biblioteki przedstawione w Tabeli 3.

W przypadku kodu zarządzanego 

mamy pewnego rodzaju automat 
zabezpieczający przed przepełnieniem 
bufora, wyjściem poza zakres tablicy 
czy też nieprawidłowym kodem 
wykonywalnym. 

Gotowce

pomagające w pracy

Rozwiązaniem potencjalnych problemów 
może być Enterprise Library stworzone 
przez Microsoft przez grupę Patterns & 
Practices (http://msdn2.microsoft.com/
en-us/library/aa480453.aspx
). 

Enterprise Library to zestaw różnego 

rodzaju bloków aplikacji (funkcjonalnych). 
Bloki te są opisanymi gotowymi 
rozwiązaniami oraz kawałkami kodu, 
który należy tylko wstawić do własnej 
aplikacji wg zaleceń bez konieczności 
tworzenia własnych takich rozwiązań. 
Wśród gotowych bloków możemy 
znaleźć między innymi: Caching
CryptographyData AccessException 
HandlingLoggingSecurityValidation
Policy Injection. W naszym przypadku 
istotne będą dwa bloki: Cryptography 
Application Block oraz Validation 
Application Block. Należy pamiętać, 
że nie jest to rozwiązanie wszystkich 
problemów, ale warto się mu przyjrzeć, 
ponieważ jest po prostu pożyteczne dla 
programistów.

Podsumowanie

Jak widać (i jak wiadomo), problem 
bezpiecznych bądź niebezpiecznych 
aplikacji jest nader złożony. Wyróżnić 
można bardzo wiele aspektów tworzenia 
bezpiecznych aplikacji, na które należy 
zwrócić uwagę. Przede wszystkim są to: 
dobrze zdefiniowany proces tworzenia 
aplikacji, edukacja zespołu programistów, 
zachowanie jakości kodu oraz stworzenie 
bezpiecznej architektury.

Jednym z najistotniejszych punktów 

tworzenia rozwiązania jest również 
kodowanie. Dla przykładu bardzo 
wiele funkcji z biblioteki języka C jest 
potencjalnie niebezpiecznych np.: 

gets

strcpy

strcat

sprintf(“%s”)

Warto zwrócić uwagę na środki 
wspomagające tworzenie bezpiecznego 
kodu, czyli przede wszystkim pozwalające 
na automatyczny code review, statyczną 
analizę kodu – np. 

FxCop

. No i oczywiście 

testy. Testy, testy i jeszcze raz testy na 
występowanie różnych luk zabezpieczeń. 

Artur Żarski

Jest pracownikiem firmy Microsoft. Na co dzień 

zajmuje się m.in. tworzeniem 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).

Kontakt z autorem: arturz@microsoft.com

R

E

K

L

A

M

A