WebBiztonság

LakatA biztonságra törekvés azt jelenti, hogy felkészülünk olyan eseményekre amikre nem lehet felkészülni. A webfejlesztők általában nem szeretnek azon gondolkozni, hogy az alkalmazásuk hogyan használható ki. A támadók viszont igen.

Azt hiszem senkinek nem kell magyarázni, hogy egy webalkalmazás támadók lehetséges célpontjává válhat. Alkalmazásunk maga lehet egy támadás célpontja vagy akár eszköze is. Egyiket sem kívánjuk magunknak. A web nyitottsága és népszerűsége pedig azt fogja eredményezni, hogy a mi alkalmazásunk is hamar célponttá válhat. Bevallom nem gondoltam volna, hogy valamikor egy ilyen leírásokat tartalmazó weblap is támadások célpontjává válhat. De kb fél év után elkezdődött. Megjegyzésként érkező spamek, xss támadások, és beoltások, sajnos néhány sikeres betörés is volt már. Senki nem lehet nyugodt, hogy nála úgy sem fognak próbálkozni.

A támadók lehetséges céljai

  • valamilyen adatot meg akar szerezni (jelszót, hitelkártya azonosítót)
  • valamit tönkre akar tenni (pl leállítani a szolgáltatásunkat)
  • valamit meg akar változtatni (pl az alkalmazásunk viselkedését)

Ha a támadó eléri a célját akkor kisebb-nagyobb mértékű kárt tud okozni. Kártyaszámlánk lenullázástól kezdve egy kellemetlen üzenet megjelenítéséig elég széles skálán mozoghatnak a saját problémáink. Ezen felül egy nem jól megtervezett alkalmazást kihasználhatnak spam küldésére, vagy akár a teljes webszerver leállásához, ami elérhetetlenné tehet más alkalmazásokat is.

Felkészülés a védekezésre

belépési pontok meghatározása
a belépési pontok alkalmazásunk azon részei ahol adatot lehet bevinni a rendszerbe. Ezek az általános webalkalmazások esetében az input mezők, file feltöltések, adatbázis módosítások és cookiek, ajax alkalmazások esetében pedig ezen felül az xhr lekérések egy része és a drag ‘n drop interfészek.
biztonsági szint meghatározása
egy adminisztrátori joggal rendelkező userben jobban bízunk, mint egy mezeiben. Az adminisztrátorok sokkal több mindenhez férnek hozzá mint a többiek – ettől adminisztrátorok. Azt kell itt átgondolnunk, hogy mely user csoportok mihez férjenek hozzá.
lehetséges támadási célpontok beazonosítása
Mi az amit a támadó megcélozhat? Mik az érzékeny adatok?

Csatoljuk be a biztonsági öveket

belépési pontok
Input mezők, file feltöltések, adatbázisbeli módosítások, cookiek, ajax hívások és drag ‘n drop interfészek. Ezek a problémás kütyüjeink. És igen, ne feledkezzünk meg még egyről. Maga az URL. A legfőbb elv a validálás. Minden bejövő adatot ellenőriznünk kell.

Nem bízhatunk a bejövő adatokban, mivel nem tudhatjuk, hogy honnan származnak. A pozitív ellenőrzés szabálya: tudjuk, hogy milyen adatot várunk, és azt ellenőrizzük, hogy a bejövő adat megfelel-e a mintának. A kliens oldali ellenőrzéssel biztonsági szempontból az a bajunk, hogy nem tudhatjuk a szerveren, hogy a beérkezett adat validált-e már vagy sem, hiszen egy saját formmal vagy url átírással bármilyen adatot oda tudunk adni a szerver oldali scriptnek. A támadónk első körben biztosan valami fura inputtal fog próbálkozni.

Itt előkerül a szerver oldal. Mit reagál az alkalmazásunk egy nem várt paraméterre? Kiszolgál mindenféle kérést a szerver? Mit reagál ha egy elvileg csak ajax-szal meghívható scriptet valaki közvetlenül meghív? Kiszolgálja az alkalmazás a kérést ha mondjuk GET helyett POST-ban érkezik a kérés? Ezek mind olyan kérdések amelyeket a belépési pontok elemzésénél meg kell válaszolnunk.

A legérzékenyebb inputjaink az azonosításhoz, beléptetéshez használtak. A weben nem látjuk, hogy ki ül az alkalmazásunk másik végén, nem tudunk retina azonosítást vagy ujjlenyomatot vizsgálni. Az azonosítás az esetek elsöprő többségében egy jelszó és egy név megadásával történik. Sajnos a jelszó többnyire titkosítás nélkül, sima szövegként jut el a szerverig.

biztonsági szint
Az alkalmazásnak a biztonság érdekében az alábbiakat kell tennie: a usereket azonosítania kell, különböző hozzáférési jogosultságokat kell kezelnie, a hibákat és a kivételeket megfelelően kell kezelnie és végül a háttérrendszert is kell ellenőriznie.

Ezt a pontot nehezíti maga a JavaScript, mivel a javascript közvetlenül letöltődik a böngészőbe és könnyedén elolvasható bárki által.

Szabályozni kell, hogy a be nem lépett userek illetve a különböző jogosultsági szinteken lévő userek milyen erőforrásokhoz férhetnek hozzá.

A webalkalmazások különböző fázisokon mennek keresztül, mint a fejlesztés, a tesztelés, és az éles működés. Mindhárom szakaszban különböző biztonsági szinteket alkalmazunk. Az első kettőben bizonyára ki fogjuk íratni a hibaüzeneteket, míg az éles rendszerben célszerű ezt nem tenni. Ez megint egy olyan pont amit szeretünk elfelejteni. A legkényelmesebb megoldás egy alkalmazás szintű konfigurációs beállítás, vagy az éles szerveren egy olyan beállítás ami elnyeli a hibaüzeneteket. Ha ezt tesszük akkor nem fogunk egy frissítés során elfeledkezni erről a kis “apróságról”. Márpedig egy hibaüzenet olyan információkat adhat ki egy támadónak amit jobb nem megadni neki.

Kockázatos eseményeinket loggolni kell. Ilyenek a be és kijelentkezések, a sikeresek és a sikertelenek, a felhasználók adataiban bekövetkező változások, jelszóváltoztatások, az elvárthoz képest más metódusok használata, pl GET helyett POST, nem várt paraméterek érkezése és a nem várt események bekövetkezése.

Persze itt is be kell lőnünk a megfelelő szintet. Pár évvel ezelőtt írtam egy alkalmazást ahol az sql parancsok 50%-a loggolás volt az éles futási környezetben. Hm, hát gyorsan kiderült, hogy némi teljesítménybeli problémával kell szembenéznem.

Az elérhetőség szabálya így szól: a rendszerünk annyira azért ne legyen biztonságos, hogy senki se tudja használni.

támadási célpontok
Vegyük utolsóként magát a támadás célpontját. Mint fentebb leírtam ezek egyrészt lehetnek érzékeny adatok akár a szerveren akár a kliens oldalon (session azonosítók, jelszavak, hitelkártya adatok). Másrészt lehet maga az alkalmazásunk, azaz annak működésének befolyásolása vagy megakadályozása. Harmadrészt lehet a futási környezetünk a szerveren, amiben zavart okozva a szerveren lévő más alkalmazásokat kívánnak korrumpálni. Negyedrészt pedig egy az alkalmazásunktól független külső célpont, melynek megtámadásában a mi alkalmazásunk valamilyen biztonsági szempontból gyenge pontját használják ki.

Tanácsok általánosságban

  • Hozzáférési jogosultságok: az a jó ha minden user csak annyit tud megtenni amit feltétlenül muszáj neki, és annál többet nem. A fő probléma az adminisztratív interfészek képbe lépésével kezdődnek, és ezek lesznek a támadók fő célpontjaik. Az adminisztratív interfészeket mindig elkülönítetten kell kezelni a normál interfészektől.
  • Nem megfelelő azonosítás vagy session kezelés: ki csatlakozott az alkalmazásunkhoz? A jó jelszó nehezen megjegyezhető, így kevesen választanak ilyet, vagy a user egy postiten a monitorra tűzheti a jelszavát. Ha user ilyet tesz egy támadó könnyen bejuthat és akkor már az alkalmazásunkon múlik, hogy mit tud ott megtenni. A session ellopható, fontos, hogy lejárat után törölve legyenek.
  • XSS: cross site scripting segítségével a támadó valahogyan bejuttat egy ártalmas kódot a szerverre és a következő látogatók már ezt a tartalmat kapja meg, és a saját böngészőjéből kap a támadó érzékeny adatokat, mint session adatok, azonosítók vagy jelszavak. Escapeléssel egyszerűen kivédhető. Ezzel loptak már hitelkártyaadatokat, de lehet, hogy annyit érnek el vele, hogy egy népszerű oldalról átírányul az összes látogató a támadóéra.
  • Buffer túlterhelés: a legismertebb biztonsági probléma. Előidézhető úgy, hogy egy olyan inputba ami nem ellenőrzi a bevitt adatok hosszát nagyobb adatmennyiséget tolunk be mint amit az azt kezelő adattipus elbír. Rossz esetben az alkalmazás elpusztul és a támadó olyan jogosultságokat szerezhet mint amilyen az alkalmazásunkat hívó programnak volt.
  • Beoltások: Akkor válnak elérhetővé ha alkalmazásunk SQL parancsokat, shell scipteket vagy más programokat hív meg (például e-mailt küld). Escapelni kell a bejövő inputokat.
  • Nem megfelelő hibakezelés: még ha az alkalmazásunk meg is pusztul valahogy olyan kevés adatot kell kiadnunk a futási környezetünkről amilyen keveset csak lehet. Ezek az információk mind mind plussz infomrációk a támadóink számára. Az alkalmazásunkban pedig jobb ahhoz tartani magunkat, hogy az alapértelmezés mindig az elutasítás legyen.
  • Nem biztonságos tárolás: érzékeny adatokat titkosítva tároljunk és ne használjunk saját titkosító algoritmust. Részesítsük előnyben ahol a lehet a vissza nem fejthető algoritmusokat.
  • Túlterhelés: Lehet, hogy mindent elkövettünk, hogy az alkalmazásunk biztonságos legyen, de mondjuk kikerül a lapunk egy népszerű oldalra linkként és hirtelen több százszorosára ugrik fel a látogatottság. Itt akkor előjöhetnek a futási környezetünk gyenge pontjai, mint a memória, a sávszélesség, a fájlkezelés, az adatbázis kapcsolatok száma, a threadek, a loggolási mechanizmus, a file és adatbázis tárolási kapacitás. Bármelyik is szűknek bizonyul az alkalmazásunk megfeküdhet, és ezzel a támadónk elérhetetlenné teheti az alkalmazásunkat.
  • Nem biztonságos konfiguráció: A szerverünk konfigurációját általában rábízzuk a rendszergazdára. Biztonságos ez?
  • Kockázatok a böngészőben. Egy ismert hibán keresztül akár jól biztosított webalkalamzás is korrumpálható.

És konkrétumokban

  • A legfontosabb, hogy a biztonsági kérdések olyanok mint a dokumentáció. Ha a végére hagyjuk akkor sose fogjuk megcsinálni. Építsük be magunkba a biztonsági szemléletet, gondoljunk rá a tervezési fázistól kezdve, építsük be a megvalósítási fázisokba. Mindig teszteljünk biztonsági szempontból. Minél érzékenyebb a szolgáltatásunk, annál fontosabb a biztonsági tesztelés. Ahogy az alkalmazásunk kikerül a webre lesznek emberek (robotok) akik 0-24-ben fogják az alkalmazásunk biztonsági rétegét tesztelni. Ha van neki olyanja.
  • Ha az alkalmazásunk küld e-mailt akkor a headerek beoltását szűrjük. Ha egy user tetszőleges e-mail címre küldhet levelet, akkor a címzett megadásánál elég egy ilyesmit megadni ahhoz, hogy az alkalmazásunk egy gyönyörű kis spamküldő szolgáltatássá változzon: bendeguz@sehol.se\nBCC: egyspammelt@valahol.va, ketspammelt@valahol.va. Remélem senki nem innen veszi majd a módszert 🙂 Szóval amit tehetünk, hogy a szerver oldalon megvizsgáljuk a bejövő inputot. A reguláris kifejezések nagy nagy szerephez jutnak ezekben a vizsgálatokban és ellenőrzésekben. Amit ezen kívül érdemes mindig megtennünk azok az újsor és hasonló rizikós karakterek keresgetése.
  • Kényszerítsük a usert nehezen kitalálható jelszó használatára. A google mail egyáltalán nem tolakodóan ezt teszi. A jelszó nem lehet azonos a usernévvel még úgy sem, hogy belekerül pár nagy betű, nem lehet túl rövid és nem állhat csak számokból. Ügyes és praktikus megoldás. Kockázatosabb alkalmazásban kényszeríthetjük a usert rendszeres jelszó változtatásra is.
  • Gondoskodjunk arról, hogy a sessionök el legyenek dobva amikor már nincs rájuk szükség. A session életideje egy kényes kérdés. Jártam már úgy, hogy mire kitöltöttem egy repjegy megrendelést a rendszer kiléptetett és kezdhettem mindent előről. Ha viszont túl hosszú inaktivitás után is él a session akkor az is problémák forrása lehet.
  • Ne bízzunk a userben. Lehet, hogy a userünk ártatlan, de ha gondatlan, akkor jelszavával egy kevésbé ártatlan támadó könnyedén bejuthat a rendszerbe.
  • Ne bízzunk a bejövő adatokban. Escapeljünk, validáljunk, ellenőrizzünk és szűrjünk. Mindig és mindenhol. Főleg a szerver oldalon.
  • Figyeljük a futási környezetünk biztonsági javításait. Vonatkozik ez a webszerverre, az adatbázis szerverre és a többi környezeti elemre. Ez egy olyan elem amit nem tudunk mindig teljes mértékben befolyásolni. A mai napig több szerveren látom, hogy a PHP register globals-ja be van kapcsolva. Ha jól emlékszem 4-5 éve nem javasolt ennek a használata.
  • Az éles futási környezetben használjunk saját hibaüzeneteket, ne hagyjuk, hogy az alapértelmezett hibaüzenetek megjelenjenek.
  • Ahol lehet használjunk az adatforgalomra titkosított csatornát.
  • Érzékeny adatokat tároljunk mindig titkosítottan.
  • Nézzünk utánna a szerver beállításoknak, ne legyünk biztosak benne, hogy a rendszergazda mindent jól állított be. Ott van például a register globals. Bizonyára a rendszergazdák tudják, hogy biztosabb kikapcsolni. Mégis lehetnek más körülmények amik arra késztetik őket, hogy bekapcsolják szerver szinten. Ha ez a helyzet legalább gondoskodjunk róla, hogy az alkalmazásunk kikapcsolja magának.
  • Bizonyos esetekben kérhetjük a usert, hogy azonosítsa újra magát, így ha a támadó egy ellopott sessionnal került be, akkor itt már nem fogja tudni azonosítani magát.
  • Határozzunk meg olyan eseményeket aminek bekövetkezéséről értesítjük a usert. Ezek alkalmazásfüggő események lesznek, de a jelszóváltoztatás, vagy a több egymást követő sikertelen belépési kísérlet esélyes jelöltek lesznek arra, hogy a usert kiértesítsük róla.
  • Escapeljük a userek által bevitt megjelenítésre kerülő adatokat. Egy hozzászólásban érkezhet xss támadás, vagy valaki akár véletlenül is betehet egy </div> tagot, ami az oldalunk széteséséhez vezethet.
  • Ne adjunk át url paraméterben, vagy post-ban SQL tábla vagy oszlopneveket.
  • A szerveren csak azok a könyvtárak, fileok legyenek írhatóak amelyeknek feltétlenül annak kell lennie.

A böngészők a same origin policy-t alkalmazzák a biztonság növelésére. Ez azt mondja ki, hogy egy webalkalmazás egyes részeinek ugyanarról a domainról, ugyanarról a portról kell érkezniük ugyanazon protocollon keresztül. Ezért van az, hogy egy ajax alkalmazás nem kommunikálhat más szerverrel mint ahonnan maga az alkalmazás származik.

Nincs feltörhetetlen alkalmazás. Bárhogyan is igyekszünk biztonsági oldalon lesznek réseink, amiket egy eléggé elszánt támadó meg fog találni. Az viszont rajtunk múlik, hogy mennyire nehezítjük meg a dolgát. Tegyük amit lehet, és figyeljünk rendszeresen, hogy mi történik. És ne felejtsük, mindenki célpont. Mi magunk is.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.