bezpečnost ID v hidden prvku

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
basovnik
Člen | 23
+
0
-

Ahoj, poradili byste mi jak zapezpečit ID v hidden prvku ve formuláři, aby při ruční editaci (např. přes firebug) zůstala uchována původní hodnota po odeslání? Našel jsem témata různá ohledně prvků hidden, ale žádné nějak neřešilo tento problém. Snad jen SafeHiddenField. Také jsem četl něco o atributu hidden prvku forcedValue, ale nějak nevím, jak tu hodnotu naplnit. Je to úplně základní problém, který museli asi řešit všichni. Omlouvám se, zda se to už někde řešilo, ale žadné setDefault ani druhý parametr v addHidden,.. nic nezabralo…

joe
Člen | 313
+
0
-

basovnik napsal(a):

Je to úplně základní problém, který museli asi řešit všichni.

Nic takového jsem nikdy neřešil a ani nevím k čemu by mi to bylo dobré. Můžeš to napsat?

Pokud bych už něco takového někdy potřeboval, jednoduše bych využil sessions.

Filip Procházka
Moderator | 4668
+
0
-

Paranoia.

Když si v systému změníš ID upravovanýho záznamu a přepíšeš tak jiný, je to tvoje blbost. Pokud upravuješ něco co vytváří více lidí (komentáře, články, …) pak máš mít přístup pouze ke svým záznamům a aplikace ti nemá dovolit ostatní upravovat.

Z principu by ti aplikace neměla dovolit upravit něco, na co nemáš oprávnění. Pokud to upravíš regulérním proklikáním se k tomu a nebo si změníš ID hiddenu v html, je to jedno.

Systému by to mělo být jedno, tobě by to mělo být jedno.

Nastuduj si ACL.

Editoval HosipLan (22. 7. 2011 8:07)

JakubJarabica
Gold Partner | 184
+
0
-

Načo potrebuješ ID v hiddene? Zvyčajne stačí pracovať s $this->getParam().

basovnik
Člen | 23
+
0
-

Asi mate pravdu… reseni je kontrolovat pristup k zaznamu i po odeslani editacniho formulare… resil jsem opravneni editace jen pri vstupu do editacni sekce a pak uz ne, takze uzivatel mohl teoreticky v nejake utilite zmenit id a neco neopravnmene prepsat. Nejlepsi reseni to je kontrolovat asi pred i po, jak pisete… Nebo použít to getParam('id') a nedat mu moznost zmenit id v hidden prvku.

Dekuji!

Editoval basovnik (22. 7. 2011 15:33)

Nox
Člen | 378
+
0
-

getParam myslíte z URL? To jde přece taky změnit, kontroluj vždy!

tatyalien
Člen | 239
+
0
-

Není jednodušší si z getparm uložit id do sessionu? Například z comboboxu si vyberu uživatele co chci editovat, uložím jeho id od sessionu a na to už nešáhne…

Filip Procházka
Moderator | 4668
+
0
-

NE. Jednodušší je kontrolovat i po odeslání. Tečka.

JakubJarabica
Gold Partner | 184
+
0
-

Ono ak sa bavíme o nejakej actionEdit($id), tak je dobre hneď v action kontrolovať ID, plniť setDefaults bez nutnosti hiddenu a pri odoslaní sa vykoná to isté, len naviac sa zavolá signál na spracovanie formu, kde je už zvalidované z action $this->param[‚id‘] (dokonca property access už pri overenom parametre)… Tak nie je treba používať hidden. Či to má nejakú muchu…?

Jan Tvrdík
Nette guru | 2595
+
0
-

JAM3SoN wrote:

je dobre hneď v action kontrolovať ID (…) Či to má nejakú muchu…?

Pokud kontroluješ práva pouze v akci edit a existuje libovolná jiná akce, kde se práva nekontrolují (třeba view), tak ti formulář pošlu přes ni, čímž bezpečnostní prověrku zcela obejdu :)

JakubJarabica
Gold Partner | 184
+
0
-

Hm, to by chcelo implementovať nad továrničky nejakú anotáciu allowed(action=edit) aby to v takomto prípade hádzalo výnimky. Inak dobrá pripomienka, vďaka :-)

kravčo
Člen | 721
+
0
-

Stačí implementovať Authorizator, ktorý rozhodne, či máš ty (používateľ JankoHrasko) povolené na zdroji (článok #23) alebo skupine zdrojov (všetky články) vykonať danú akciu (edit). Napríklad pomocou vstavaného Permission.

pekelnik
Člen | 462
+
0
-

Jan Tvrdík napsal(a):

Pokud kontroluješ práva pouze v akci edit a existuje libovolná jiná akce, kde se práva nekontrolují (třeba view), tak ti formulář pošlu přes ni, čímž bezpečnostní prověrku zcela obejdu :)

Tak tak!

A vyplývá z toho, že je nezbytné autorizovat uživatele přímo v onSuccess handleru formuláře.

K původnímu dotazu o skrytém poli se raději nebudu vyjadřovat :P

Filip Procházka
Moderator | 4668
+
0
-

Legrace je, že taková akce nemusí vůbec existovat, ani jako metoda v presenteru ani jako šablona a stejně to dojde „dost daleko“ aby proběhlo zpracování.

tatyalien
Člen | 239
+
0
-

Tak jak nejlépe postupovat například s tímto:

Pod adminem jsem v sekci editovat uživatele, v comboboxu mám dle práv zobrazené jen ty, na které má dané právo editovat. Po odeslání se zobrazí část na editování (buď redirect na this se zvoleným id, nebo edit view s id), ale jak pak mohu jednoduše ověřit, že uživatel si ručně nezmění hodnotu načteného id a tím pádem i editaci jiného uživatele?
Za chyby sorry, píšu do neděle z mobilu fujky.

Editoval tatyalien (23. 7. 2011 20:58)

voda
Člen | 561
+
0
-

@tatyalien: klidně ať si to změní. Pokud zvolí id uživatele, kterého nemá právo editovat, tak mu to při ukládání neprojde, protože tam probíhá kontrola. Druhý případ, kdy id změní na uživatele, ke kterému má práva, tak (je blbej) se to nijak neliší od případu, kdy si rovnou otevřel editaci toho uživatele.

Tharos
Člen | 1030
+
0
-

@tatyalien: Já bych v tomto případě kontroloval práva na následujících místech:

  • na začátku actionEdit (resp. renderEdit), kde si dokáži představit, že bych admina, který nemá právo editovat jím zamýšleného uživatele, přesměrovával na přehled uživatelů
  • na začátku handleru formuláře (tj. například na začátku metody renderFormSubmitted), kde bych v případě nedostatečných práv pravděpodobně také přesměrovával na přehled uživatelů a asi bych před tím volal i $this->flashMessage('Permission denied')

U toho handleru se samozřejmě nabízí i možnost volat $form->addError('Persmission denied'), ale zde je riziko, že by se formulář s chybou vytvářel právě „v kontextu“ actionEdit a kvůli řešení z prvního bodu by pak stejně došlo k přesměrování na přehled uživatelů. Pracně předaná chybová hláška by se pak k adminovi ve výsledku vůbec nedostala.

Samozřejmě do toho select boxu v přehledu je nanejvýš vhodné vypisovat pouze ty uživatele, které má admin možnost editovat.

kravčo
Člen | 721
+
0
-

Podľa mňa je ideálne kontrolovať práva na jednom mieste – v modeli. Ten ideálne by mal zabezpečuje styčný bod medzi aplikáciou a dátami, ku ktorým pristupuje a je teda miestom, ktorým tečie všetko.

hAssassin
Člen | 293
+
0
-

souhlasim s Tharosem, kontrolovat na dvou (/trech) mistech. kravčo ja si vzdycky myslel ze opravneni ani kdo je aktualne prihlasenej uzivatel by model vubec nemel znat. Jemu by to melo byt jedno, ne? (ikdyz pohledu na vec muze byt asi vic… :-) )

Nox
Člen | 378
+
0
-

Přesně, tohle model nemá řešit, ten má řešit svou doménu působnosti. Presenter spojuje uživatele, model a výstup a je tedy na rozhraní, kde lze řešit, jestli toto uživatel smí.

Filip Procházka
Moderator | 4668
+
0
-

Podle mě, je ideální ověřovat, zda má uživatel oprávnění zobrazit aktuální presenter, logicky v presenteru. Ale zároveň by měla být kontrola na práci s daty v modelu. Zda může číst, nebo editovat.

Čili souhlasím s kravčo.

kravčo
Člen | 721
+
0
-

Upresním. Nehovorím, že model má implementovať kontrolu práv. Len to, že má byť miestom, kde sa kontroluje, či má JankoHraško má právo upraviť článok #23, pretože model je tým, čo tie dáta fyzicky upraví.

Myslím to nejako takto:

class Model
{
    /** @var IAuthorizator */
    private $acl;

    public function editArticle($id, $data)
    {
	if (!$this->acl->isAllowed('edit', 'article')) {
	    throw new AccessDeniedException;
	}
	//TODO: check return value and catch exceptions
	return dibi::query('UPDATE ...', $id, $data);
    }
}

Teda model vykonáva kontrolu práv na prostredníctvom poskytnutého autorizátora, nie sám o sebe.

tatyalien
Člen | 239
+
0
-

Tak jak koukám, tak nevím jak nastavit uživatelům jaký mají právo na editaci.. pokud nastavím v acl že mají uživatelé právo na view edit tak jim povolím zobrazovat a upravovat, tím pádem mají právo na vše… ale u vyhledávacího combobxu mám nastaveno, pokud je přihlášen „superadmin“ nasypu například všechny jména, pokud má roly „admin“ tak všechny mimo superadmina a admina, atd… ale jak nastavím přímo při updatu jestli dané id mohu editovat? To mám cpát ještě kontrolu, že si vytáhnu danou roly editovacího id a porovnám jestli může nebo ne? Nějak v tom plavu…

Editoval tatyalien (24. 7. 2011 19:52)

tatyalien
Člen | 239
+
0
-

kravčo: Používám ACL co tu je…

Takže práva na zobrazení stránek mám nastavené, ale jak jednoduše udělat, když mají admin i superadmin právo na zdroj „edit“, a zde můžou oba dva upravovat data, jak nastavit které id může a nemůže upravit o to mě šlo. Jestli před vykonáním si musím šáhnout do DB zjistit jestli editující data mají menší práva než ten co je edituje a dle toho mu to povolit, nebo zakázat…

Práva mám v nástřelu takto.

<?php
$acl->addResource('edit');

$acl->allow('admin', 'edit', Array('user'));
// superadmin bude mít přímo editaci bokem zvlášť, jen jsem chtěl mít to při jednom na stejném místě s adminem...
$acl->allow('superadmin', 'edit', Array('user', 'userAdminem'));
?>

Tak jsem si doděla ještě kontrolu těsně před editaci a asi to tak nechám

<?php
    /**
     * Vrátí zda zadané id mohu editovat
     * @param int $id_editovaneho
     * @param int $id_editujiciho
     * @param string $role_editujiciho
     * @return boolean
     */
    public static function kontrolaOpravneniEditaceUser($id_editovaneho, $role_editujiciho, $id_editujiciho) {
        try {
            if ($id_editovaneho == $id_editujiciho) {
                throw new IOException('Zde nemůžete editovat sama sebe.');
            }

            $query = 'SELECT role FROM ' . self::TABLE_USERS . ' WHERE id = ? LIMIT 1';
            $result = self::$connection->query($query, $id_editovaneho);
            $row = $result->fetch();

            // při nenalezení daného id vracím false
            if(!$row) {
                throw new IOException('Zadané id uživatele neexistuje.');
            }

            if($role_editujiciho == 'superadmin') {
                return true;
            }

            if ($row['role'] == 'superadmin' || $row['role'] == 'admin') {
                return false;
            } else {
                return true;
            }
        } catch (IOException $e) {
            throw $e;
            // při neúspěchu vracím false
            return false;
        }
    }
?>

Editoval tatyalien (25. 7. 2011 11:03)