2009. március 4., szerda

Webalkalmazások biztonsági hibái - 1. Sessionök kezelése

Betörési tesztjeink során gyakran találkozunk azzal a jelenséggel, hogy a weboldalak fejlesztői ugyanazokat a hibákat követik el újra és újra. Ezen klasszikus hibákat egy több részből álló sorozatban szeretnénk bemutatni.

Mi a session?

Klasszikus definícióban a session olyan objektum, amely elkülöníti az egyes felhasználók tevékenységét. Vannak olyan esetek, amikor fontos a felhasználó azonosítása is (pl. összetett webes dokumentumkezelő rendszerek esetében), de adódhat olyan eset is, amikor annyi a feladat, hogy különítsük el az egyes felhasználóktól érkező kéréseket, a konkrét felhasználó személye lényegtelen (pl. regisztrálást nem igénylő webáruházak, ahol a „kosár” tartalmát tartjuk nyilván).

A sessionkezelés majdhogynem minden webalkalmazás esetén előjön tehát – lássuk, hogy hol szokták elkövetni a fejlesztők a leggyakoribb hibákat.

Nem megfelelő sessionkezelési módszer kiválasztása. Sessionöket (állapotokat) többféleképp is tárolhatunk. Néhány lehetőség:
  • Minden kérés elküldésekor azonosítjuk a felhasználó nevét és a felhasználót hitelesítő adatokat. Hasonlít a módszer a HTTP-s hitelesítés legegyszerűbb formájához - egyszerű, könnyen implementálható, viszont több szempontból is aggályos biztonságilag, ugyanis ekkor szerveroldalon nem tárolunk sessionazonosítót.
  • A szerveroldalon tárolunk mindent, ami a session kezeléséhez szükséges, a felhasználótól a cookie-ban található sessionazonosítót várjuk.
  • Az ASP .NET-ben jelent meg a ViewState funkció, amely egy hidden html paraméterben tartalmaz mindent, ami a session leírásához szükséges, ezt minden kérés mellé elküldi.
A sessionazonosító gyengeségei. Sok esetben tapasztaljuk, hogy hitelesítés után a sessionazonosító az a "titok", ami a felhasználót egyedül azonosítja a webalkalmazás számára. Ez esetben nagyon veszélyes az, ha a sessionazonosító sérülékenységet jelent.
  • A sessionazonosítónak a session azonosításán kívül más funkciója is van. Ilyen eset például az, amikor az alábbi a sessionazonosító: dXNlcj1iZWxhO2FkbWluPW5vO2lkPTIyMzIzMQ== ,ez ugyanis base64-gyel kódolt formája az alábbinak: user=bela;admin=no;id=223231. A támadó megpróbálhatja módosítani a sessionazonosítót (az alkalmazás által értelmezhető formátumban), illegitim horizontális, ill. vertikális jogosultsághoz jutva ezzel.
  • A sessionazonosító nem véletlenszerű, hanem időfüggő. A támadó sok kérés kiadásával felfigyelhet arra, hogy az időbélyeg közvetlenül szerepel a session azonosításában - ez esetben más felhasználók sessionjét is kompromittálhatja azzal, hogy predikálja az érvényes sessionazonosítókat.
  • A session nincs felhasználóhoz rendelve. Sokszor előfordul, hogy a sessionkezelés hanyag implementációjában a szerveren csak az érvényes sessionazonosítókat tároljuk, a hozzájuk tartozó felhasználót nem. Ez főleg akkor hasznáható ki könnyen, ha a sessionazonosító szerkezete kitalálható (pl. a fenti base64-encodinggal készült példában), ugyanis a támadó átírja a felhasználónevet, és mivel a sessionazonosító továbbra is érvényes, más jogosultsági szintet ér el.
  • Hibásan implementált "remember me"-funkció. A legegyszerűbb, naiv implementációban a sessionazonosítót beletesszük egy permanens cookie-ba, aminek jó hosszú lejárati időt adunk meg, amikor pedig a felhasználó visszalátogat az oldalra, visszalép a saját sessionjébe. Ez persze azzal jár, hogy a szerveren nem követjük az aktuális sessionöket (vagy ha követjük is, nagyon nehézkes tárolni az egyes sessioncookie-k lejárati idejét is, és ha lejár, megszüntetni az adott sessionazonosítót. Sokkal egyszerűbb úgy implementálni a funkciót, hogy ha ismeretlen, de értelmesnek tűnő (pl. parszolható) azonosítót kapunk, érvényesnek fogadjuk el). A támadónak itt nincs más dolga, mint készíteni egy parszolható azonosítót.
Sessionazonosító kiadása a hálózaton. Gyakori hiba, hogy a sessionazonosítót nem cookie-ban, vagy POST paraméterként adja át a kliens, hanem egyszerűen beleteszi az URL-be GET paraméterként: user.jsp?SESSID=lwjer23rayxcyxcydfsef. Miért jelent ez problémát? Egyrészt azért, mert a sessionazonosítók triviálisan kompromittálódnak a legitim használat során is: a böngészők átadják külső képek, állományok, oldalak stb. letöltésekor a kiadott HTTP-kérés fejlécében a referer mezőben. A támadónak nincs más dolga, mint (fórum esetén pl.) feltenni egy saját szerveren lévő képet, és a webszerver logjaiból kibányászni az aktuálisan érvényes sessionazonosítókat.

Gyakori hiba az is, hogy performanciaokokból HTTP-s felületű a nem hitelesített felhasználók által elérhető oldal, viszont HTTPS-en keresztül működik a belépés után elérhető felület. Ez esetben elenyésző azon oldalak száma, amelyek új sessionazonosítót adnak belépéskor a felhasználónak: leggyakrabban egyszerűen módosítják a session szerveroldali leírását azzal, hogy ezentúl Gipsz Jakab felhasználóhoz tartozik.

Szintén jellemző, hogy a HTTPS-en elérhető oldal tartalmaz elemeket (pl. tracking kód, vagy céglogo), amelyek HTTP-n keresztül érhetőek el. Ez esetben szintén kompromittálódhat a sessionazonosító.

A sessionkezelés megvalósításának logikai hibái. Gyakori baki az, hogy nem ellenőrzi az alkalmazás logikája azt, hogy egy felhasználónak csak egy sessionje lehet. Mivel minden azonosításon sikeresen átment a felhasználó, hacsak nem fordított külön gondot az alkalmazás készítője, a felhasználóhoz két külön session és két külön sessionazonosító is tartozni fog. Ez egyrészt legitim használat során nagyon ritkán fordul elő, másrészt versenyhelyzet kialakítása is nagyon egyszerű (pl. a felhasználó az A sessionben elkezd egy többlépcsős folyamatot, pl. új felhasználó felvitelét, és a B sessionben módosítja az A session első lépésben felvitt adatait).

Session lezárása. Meglepő, de a legtöbb hiba itt fordul elő. Sokszor előfordul, hogy a készítők egész egyszerűen megfeledkeznek(!) a sessionök lezárásáról, tehát nincs ilyen funkció az alkalmazásban.

Másrészről tipikus problémát jelent a lezárással kapcsolatosan az, ha a logout funkció egyszerűen törli a felhasználó cookie-jának tartalmát: ez esetben a session továbbra is él, ha a támadó ismeri az azonosítót. Nagyon egyszerűen meg lehet győződni erről: a logout után nyomjunk egy back-et a böngészőben, és küldjük újra az adatokat. Ha ekkor visszaenged az alkalmazás a belépés utáni felületre, hibás a sessionkezelés.

Látható, hogy ilyen "egyszerű" témánál is, mint a sessionkezelés, mennyi a hibázási lehetőség... a sorozat következő részében a felhasználók azonosításával összefüggő tipikus hibákat vesszük sorra.

3 megjegyzés:

  1. Az miért számít problémának, hogyha megengedett egy felhasználó több session-el?

    VálaszTörlés
  2. Esetleg még kiegészíteném azzal, hogy adatbázisban nem jó munkamenet azonosítókat tárolni, mert SQL injection-el, vagy az adatbázis más módon történő lopásával kinyerhető. A jelszót sem véletlenül hash-eljük, ugyanígy, ha a permanent cookie-hoz tartozó azonosítót adatbázisban tároljuk, akkor azt is hash-elni kell. A session id-t is lehetne hash-elve tárolni az adatbázisban, csak baromi lassú lenne úgy a rendszer. A legjobb beszórni a memóriába, amennyiben erre van lehetőség. Én legalábbis így gondolom.

    VálaszTörlés

Kommentek