2009. május 29., péntek

Webalkalmazások biztonsági hibái - 8. Hibák az alkalmazás logikájában

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.

Az előző részekben bemutatott jelenségek főként a "sebezhetőség" kategóriába sorolhatóak: kinyerhető általuk a webalkalmazás mögött futó adatbázis tartalma, ellopható a belépett felhasználók sessionje stb. Több olyan problémával is találkoztunk azonban, amelyek közvetlenül nem kompromittálnak semmit, ennek ellenére igen súlyos következményekkel jár, ha a támadó (vagy ezekben az esetekben, mint látni fogjuk, belsős alkalmazott, adott esetben rendszeradminisztrátor) kihasználja őket: a problémák az alkalmazás logikájában bújnak meg.

Az ilyen jellegű hibák megtalálása igen nehéz, ugyanis többnyire nem gépesíthetőek, és az alkalmazás meglehetősen mélyreható ismerete szükséges a felfedezésükhöz (illetve ahhoz, hogy a ránézésre amúgy teljesen normálisan viselkedő webalkalmazás képernyőin, kimenetein felismerjék a tesztelők, hogy nem az elvárt működés szerint zajlanak az események). Lássunk néhány tipikus esetet a problémák érzékeltetésére.

Bevásárlókosarak megvalósítása - negatív mennyiségű áruk
A tesztelt alkalmazás egy on-line shop rendszer volt, ahol a felhasználó egy "bevásárlókosárba" tudta gyűjteni a megvásárolni kívánt elemeket. Volt egy mező, ahol megadhatta, hogy hány darabot szeretne rendelni az egyes termékekből, a kosár kezelését végző függvény új elem hozzáadásakor frissítette a kosár összárát szumma(darab*egységár) függvény alapján.

A hiba ott volt, hogy nem végzett ellenőrzést a függvény annak tekintetében, hogy negatív darabszámú termék is rendelhető volt: -1 plazmatévé rendelésekor a kosár összértékéből annak rendje és módja szerint levonódott a plazmatévé ára.

Bevásárlókosarak megvalósítása - párhuzamos bejelentkezések buta kezelése
Ugyanez a webbolt: bejelentkezés nélkül lehetővé tette a felület a kosár bővítését, viszont a megrendelés elküldéséhez be is kellett jelentkezni. A bejelentkezett felhasználókhoz különféle kedvezmények és akciók voltak hozzárendelve, emiatt egy kedvezménnyel rendelkező felhasználó végül is kevesebbet fizetett a kosár tartalmáért, mint amit bejelentkezés előtt látott. A kedvezményeket az alkalmazás logikája a megrendelés elküldése előtti képernyőn vonta le a kosár értékéből, és a megrendelés elküldésekor az alacsonyabb árat számlázták.

A hiba ott volt, hogy a kiszámlázott ár frissítése nem történt meg, csak az utolsó képernyőre lépéskor, viszont a kosár tartalma egy párhuzamos bejelentkezéssel módosítható volt. Tehát a felhasználó a A böngészőben megrendel egy darab csizmakaparót és elviszi a vásárlási folyamatot az utolsó gombig, majd a B ablakban hozzárendel tizenhárom darab plazmatévét (beleteszi a tévéket a kosárba). Az A böngészőben ekkor elküldi a megrendelést, amely a régi árat tartalmazza (a csizmakaparóét), viszont az új kosárral.

Audit trail
Pénzintézeti megrendelő, érzékeny adatokat kezelő webportál. A bejelentkezett felhasználók minden lépéséről log készül, amelyben szerepel a bejelentkezett felhasználó azonosítója, a lépés megnevezése, az érintett adatok köre stb. Az audit trailbe beletartoznak az adminisztrátorok is, és az adminisztrátori felületen lehetőség van az audit trail során keletkezett naplók megtekintésére és a bejegyzések módosítására, törlésére is - azonban magáról a törlésről, módosításról készül bejegyzés, és tisztán látható, hogy melyik adminisztrátor végezte.

Igen ám, de az adminisztrátorok számára lehetséges új felhasználót létrehozni, és különféle jogosultságokat adni neki szerepkörök ("sapkák") formájában - akár egy újabb adminisztrátort is. Az okosság tehát a következő:
  1. Az adminisztrátor belép a saját accountjával.
  2. Létrehoz egy dummy accountot, aminek adminisztrátori jogokat ad.
  3. A dummy accounttal belép, elvégzi, amit el szeretne.
  4. A dummy accounttal törli az összes logot, ami az account létrehozása és felhasználása során keletkezett (ezáltal a dummy nem lesz köthető az eredeti admin accountjához).
A művelet eredményeképp marad egy darab bejegyzés, ami a dummy account logtörlését mutatja - azt azonban, hogy a dummy hogy jött létre, nem lehet kideríteni a trailből.

Nem várt adatok
Biztosító, on-line kötelezőkötő felület. A biztosítás megkötése során többlépcsős folyamaton vezetik végig a felhasználót, minden képernyőn egy témakörben kell adatokat megadni (első képernyőn a személyi adatok, másodikon a kocsi adatai stb.) A képernyők között egyszerűen lehet előre-hátra lépkedni, mert a feldolgozó AJAX-alkalmazás egy objektumban gyűjti a szerződés és az ügyfél adatait, csak a tranzakció lezárásakor küldi az egészet "hátra" a háttérrendszerekbe. Az egyes képernyőkön bevitt információk szigorú szintaktikai és szemantikai ellenőrzésen esnek át elküldéskor.

A hiba ott volt, hogy az ellenőrzés során végigment a validátor az összes olyan inputon, amit az adott képernyőn meg lehet adni, viszont nem ellenőrizte, hogy van-e olyan paraméter, amit nem az adott képenyőn kellene megadni, mégis a kérésben érkezett. Ilyen "extra" paraméter megkapásakor - mivel egy egyszerű foreach-ciklussal iterált végig a feldolgozószkript a validálást követően a GET tömbön - teszőleges mezőjét lehetett írni a tranzakciót leíró objektumnak. Ennek eredményeképp az első képenyőn egy intercepting HTTP proxy (webscarabot használtunk) segítségével ki lehet egészíteni az elküldött GET-kérést tetszőleges paraméterekkel, amik viszont nem esnek át validáláson. A folytatást mindenki kitalálhatja: SQL injection, de finomabb támadások is kidolgozhatóak voltak. Például kimondottan sunyi megoldás az, amikor megváltoztatjuk kézzel a kocsi járműkategóriáját (ami eredetileg egy adatbázisból került a tömbbe a kocsi típusa és egyéb adati alapján).

Nincsenek megjegyzések:

Megjegyzés küldése

Kommentek