Bezpecnost aplikace vs komponenty
- phx
- Člen | 651
Zdravim
Konecne jsem se odhodlal napsat tento prispevek. Nekomu to mozna prijde jako blbost, ale sam na sobe obcas pozoruji, ze diky vlastnostem Nette zapominam na bezpecnost aplikace. Schvalne se kouknete na nasledujici kod a reknete zda si myslite ze je to OK.
Predstavte si situaci kdy mate nejakou stranku s nastavenim aplikace kam muze kazdy uzivatel a v zavislosti na opraveni vidi ruzne moznosti. Uzivatel vidi jen neco, administrator vidi vse. I funkci na vymazani databaze (nereste navrh – je to jen priklad, proste neco k cemu by se nemel bezny uzivatel vubec dostat).
Presenter:
class SettingPresenter extends Presenter {
protected function createComponentForm($name) {
$form = new AppForm($this, $name);
$form->addSubmit('ok', 'Vymazat data z databaze')->onClick[] = array($this, 'form_ok_onClick');
}
public function form_ok_onClick(SubmitButton $btn) {
// neco co vymaze vse v DB
}
}
Sablona:
<html>
<body>
<h1>Nastaveni</h1>
<h2>Neco pro uzivatele</h2>
...
{if Environment::getUser()->isInRole('admin')}
<h2>Opravdu vymazat celou databazi?</h2>
{widget form}
{/if}
</body>
</html>
Myslite si, ze to je OK?
NENI!!!
Pokud uzivatel odesle spravny POST data tak se komponenta vytvori a databaze se
vymaze. FAIL.
Pokud by jste chteli administraci rozdelit na 2 casti (uzivatel vs admin) a v actionForAdmin() zakazat pristup uzivatele tak to je taky FAIL. Komponenta neni vazana na view, ale na presenter. Takze pokud se uzivatel dostane k jakemukoliv view v tomto presenteru tak muze vytvorit i onu komponentu. Pozor taky to plati pro vsechny potomky onoho presenteru.
Dalsi moznost by byla overovat uzivatele v metode form_ok_onClick(), ale to neni KISS, protoze overeni je jiz na 2 mistech (presenter + sablona).
Jako reseni vidim tyto moznosti:
- overeni v metode createComponentForm(). Problem je, ze je nutno vytovorit nejakou fake komponentu nebo se vyporadat s vyjimkou „InvalidArgumentException: Component with name ‚form‘ does not exist.“, pri pokusu o pristup k neexistujici komponente.
- delit presentery dle prav uzivatelu a pristup k presenteru osetrit v metode startup() + potomci museji mit vzdy vyssi opravneni (admin bude jako posledni potomek).
- vytvaret komponenty rucne, kdyz jsou potreba, ale to zase neni hezke vzhledem k vykonu, kdy se napr vytvori nejaka vizualni komponenta a misto vykresleni se presmerovava nekam jinam. Ano jde to napsat inteligentne, ale je to dalsi starost navic.
Tak schvalne, kolik lidi ma diry v aplikaci? Jak to resite? Co je nejlepsi reseni?
Toto tema by chtelo nekde v dokumentaci zduraznit.
Editoval phx (25. 6. 2010 12:52)
- 22
- Člen | 1478
Osobně používám řešení č.2, tedy řeším oprávnění v presenteru a do šablony posílám jen identifikator, jestli se ma to či ono vykreslit danému uživateli nebo ho pošlu na jiný view. Myslím že ověřovat oprávnění až v šabloně není zrovna dobrej nápad…
Editoval 22 (25. 6. 2010 12:27)
- Jan Tvrdík
- Nette guru | 2595
Ahoj, díky za pěkný příspěvek do fóra. O tomto vím už hodně dlouho a ideální řešení je asi následující:
- Pokud lze, tak oprávnění řešit ve startupu (typicky, když má aplikace
dva moduly – Front a Admin, tak stačí ochrana v presenteru
Admin:Base
). - Pokud nelze řešit ve startupu, tak je potřeba hlídat práva v továrničce + v šabloně (to sjednotit nelze, protože v šabloně často skrýváš i další kusy kódu kromě výpisu formuláře – zde např. nadpis).
Poznámka: Ještě bych doplnil, že na první pohled užitečný kód jako
tento umístěný v BasePresenteru
může vést k velké
bezpečností díře.
// BĚDA VÁM, KDO TOHLE POUŽIJETE!
protected function createComponent($name)
{
$component = parent::createComponent($name);
if ($component === NULL && class_exists($name)) {
$component = new $name;
}
return $component;
}
Editoval Jan Tvrdík (25. 6. 2010 13:39)
- Lopo
- Člen | 277
osobne v nasom intranete pouzivam overovanie pomocou mierne upraveneho systemu popisaneho niekde tuna na fore – anotacia @secured pred triedou/akciou/etc. presentera ktore maju byt zabezpecene …
pri najdeni anotacie je to overovane voci DB, v ktorej mam zoznam ludi, zabezpecenych veci a povoleni
overenie moze byt aj normalne volanim isAllowed za pouzitia skratky opravnenia
toto mi umoznuje zabezpecit jednotlive funkcie (cele prezentery, pohlady, akcie, …) ale aj casti kodu v sablonach a pod.
pri neprihlasenom cloveku mi to presmeruje na login form a po uspesnom prihlaseni s5 na to co uzivatel pozadoval
pri odopreti pristupu napise ktory clovek je zodpovedny za danu vec a da link na poslanie mailu s poziadavkou o spristupnenie
samotne overovanie pri prihlaseni mam primarne cez localny domain controler, v pripade zlyhania sa skusa este interna DB (ludia zo sesterskej firmy)
Editoval Lopo (25. 6. 2010 13:53)
- Jan Tvrdík
- Nette guru | 2595
Lopo: Pokud nezabezpečujete ani továrničky, ani submit handlery, ani zpracování dat v modelech, tak je aplikace náchylná na výše zmíněné bezpečností riziko („Komponenta neni vazana na view, ale na presenter. Takze pokud se uzivatel dostane k jakemukoliv view v tomto presenteru tak muze vytvorit i onu komponentu. “).
- Lopo
- Člen | 277
Jan Tvrdík napsal(a):
Lopo: Pokud nezabezpečujete ani továrničky, ani submit handlery, ani zpracování dat v modelech, tak je aplikace náchylná na výše zmíněné bezpečností riziko („Komponenta neni vazana na view, ale na presenter. Takze pokud se uzivatel dostane k jakemukoliv view v tomto presenteru tak muze vytvorit i onu komponentu. “).
nepovedal by som – @secured mam nahadzane aj pred handlery …
formy spracuvam v render{} a nie cez callbacky, tym padom su osetrene
pravami pohladu …
a vacsinu su stejne zabezpecene cele presentery, takze ak clovek nema pravo
k presenteru tak nema pravo k ziadnej jeho casti … pripadne aj ak by mal
k niektorej casti povolenie ale nie k celemy presenteru, tak zabezpecenie
presenteru ma vacsiu prioritu ako niektorej jeho casti
Viem ze to nemam uplne idealne doriesene, ale tuna nema nikto take znalosti aby sa dokazal naburat kam nema a z internetu to neni dostupne vobec
- uestla
- Backer | 799
Používám ACL – vizte třebas návod zde. Čili ve
startup()
u BasePresenteru kontroluji povolení přístupu na
základě role. Do šablony samozřejmě také posílám booleany, ale to je
čistě jen pro vizuální stránku věci – aby se prostě neadminovi
nezobrazovaly odkazy na akce, které stejně nemůže provést (byl by odchycen
právě na straně severu). A jelikož startup()
proběhne dříve
než zpracování signálu, je to (doufám ;) ) v suchu…
Editoval uestla (25. 6. 2010 15:22)
- Ani
- Člen | 226
V nejbližší době se to chystám řešit nějakou univerzální metodou,
která bude pro jednotlivé action, zpracování formuláře, továrničky atd.
kontrolovat práva někde ve startupu. Myslím, že nějaké takové
univerzální řešení je v Nelle, ale zatím sem to moc nezkoumal.
Z hlediska návrhu by mi tohle přišlo nejlepší řešit někde v modelu,
ale tam si zas moc neumím představit vracení vyjímek do presenteru (bylo by
to až moc robustní).
Editoval Ani (25. 6. 2010 15:25)
- Lopo
- Člen | 277
dalsie bezpecnostne riziko je napr v nekontrolovani hodnot formu … resp nedokonalom … typicky napr. overenie hodnoty zo select boxu – vacsina sa spolieha ze dostane hodnotu len z pola ktore je v selectboxe
napr vyber mesiaca – overenie ci obdrzana hodnota je v rozsahu 1–12 … taketo veci kontroluje asi malokto (priznavam sa ze ja tiez nie, ale vacsinu mam za tym prepocet obdobi v ramci ktorych sa toto samovolne osetri)
- Jan Tvrdík
- Nette guru | 2595
Hodnoty selectu kontroluje Nette samo. Pokud dojde v POST požadavku hodnota, která nebyla na výběr, tak se to zachová stejně, jako kdyby uživatel nevyplnil nic.
- Jan Tvrdík
- Nette guru | 2595
@secured mam nahadzane aj pred handlery
Klasické handlery (navěšené přes onSubmit nebo onClick) takto nelze (AFAIK) kontrolovat (bez upravené definice formuláře). Vzhledem k tomu, že to ale zpracováváš v render fázi (proč vlastně?), tak je ti ale fuk.
pripadne aj ak by mal k niektorej casti povolenie ale nie k celemy presenteru, tak zabezpecenie presenteru ma vacsiu prioritu ako niektorej jeho casti
Tohle mi připadá jako nesmysl. Nedovedu si představit, jak by to vypadalo.
- Lopo
- Člen | 277
Jan Tvrdík napsal(a):
Hodnoty selectu kontroluje Nette samo. Pokud dojde v POST požadavku hodnota, která nebyla na výběr, tak se to zachová stejně, jako kdyby uživatel nevyplnil nic.
Tak to som si nejako nevsimol … v takom pripade pre mna tym lepsie :)
Jan Tvrdík napsal(a):
@secured mam nahadzane aj pred handlery
Klasické handlery (navěšené přes onSubmit nebo onClick) takto nelze (AFAIK) kontrolovat (bez upravené definice formuláře). Vzhledem k tomu, že to ale zpracováváš v render fázi (proč vlastně?), tak je ti ale fuk.
Mno co som zatial testoval tak som mal pristupy zabezpecene kde bolo treba
>
pripadne aj ak by mal k niektorej casti povolenie ale nie k celemy presenteru, tak zabezpecenie presenteru ma vacsiu prioritu ako niektorej jeho casti
Tohle mi připadá jako nesmysl. Nedovedu si představit, jak by to vypadalo.
Napr. mam prezenter financii … cely je samozrejme oznaceny secured, takze hocico z neho uvidi len clovek ktory ho ma povoleny …
v ramci neho ale mam este dovernejsie informacie … ktorych funkcie su znovu nastavene secured … takze ak nema navyse k nim povoleny pristup, tak sa k nim nedostane … tj na pristup k nim treba uz 2 povolenia …
ak by som mal nejaky prezenter free a len niektoru vec v nom secured … tak po pridani secured na cely prezenter sa k predtym povolenym veciam ludia nedostanu ak im nebude dane povolenie aj na cely prezenter
proste aby clovek mal pristup, tak musi mat pristup ku vsetkemu v retazci spracovania
Editoval Lopo (25. 6. 2010 16:43)