Bezpecnost n:href odkazu pri zpracovani signalu

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

Dobry den, chtel bych se zeptat, jestli existuje v nette elegantni reseni nasledujiciho problemu.
Rekneme, ze mam komponentu, ktera zpracovava signal delete. Nejspise pouziju neco v tomto smyslu pro jeji zavolani
<a n:href=„delete! $id“>Vymaz</a>
A v tomto ja vidim velky kamen urazu, co kdyz si nekdo bude chtit stranku stahnout robotem, ktery prochazi vsechny linky na strance a stahuje je. Dle vseho se mi vymaze cela databaze, coz ja urcite nechci. Existuje tedy nejake jednoduche reseni jak volat signaly pres tlacitko formulare? Prijde mi to jako obrovska chyba, ale je mozne, ze je to jenom mou neznalosti nette a vyvojari na takovouto situaci jiste mysleli.

Ani
Člen | 226
+
0
-

Ahoj,

přece nemůžeš mít v aplikace volně linky na mazaní databáze, a button to nezachrání… :)

Takže se musí použít nějaké přihlašování uživatelů https://doc.nette.org/…thentication

A pak si musíš ten link zabezpečit tak aby se robotovy vůbec nezobrazil. A zároveň by jsi měl kontrolovat oprávnění i v handle metodě, když by ti někdo podvrhnul url.

Tady je nějaký screencast, kde se na to můžeš podívat https://doc.nette.org/cs/quickstart

babcca
Člen | 23
+
0
-

Toto muze chtit i radne prihlaseny uzivatel (vezme session a da ji curl) a to ze to schovam pod nejaka prava taky nic neresi (co takovy prohlizec, ktery si projde linky do jedne urovne a ulozi je do cache [Diky bohu ze to nedelaj, ale stat se to muze]). Tlacitko me zachrani od vetsiny robotu, jelikoz to neni odkaz, ale formularovy prvek a o tom se vi, ze se „nema“ navstevovat. Jedine reseni je vytvaret vsude form rucne, ale to se mi nezda elegantni.

Shrnu to:
To ze to dam do „zabezpecene“ sekce neresi problem.
Neni mozne to skryt pred roboty.

Nox
Člen | 378
+
0
-

Neshrnuj;)

Přece ti to Ani napsal – musíš kontrolovat oprávnění i v akci, robot práva mít nebude, takže nic nesmaže

Jan Endel
Člen | 1016
+
0
-

jednak rel=nofollow a jednak v signálu jak už zaznělo hlídat zda-li k tomu má dotyčný oprávnění. (jak už zaznělo)-

babcca
Člen | 23
+
0
-

Jakto, ze nebude mit prava, kdyz se bude tvarit jako legitimne prihlaseny uzivatel?
Vezme se cely pozadavek (ne URI) na server (od aktualne prihlaseneho uzivatele), zkopiruje se, da se do curl a zacne se stahovat (zjednodusene). Tedy se tvari jako prihlaseny uzivatel (jako by se na to koukal prohlizec), ale prochazi vsechny linky na strance a stahuje je. Tedy problem stale existuje. Nebo nevim jak co znamena „kontrolovat opravneni v akci“.

babcca
Člen | 23
+
0
-

To mazani byl jenom priklad. Muze to byt jakykoliv signal (ajaxova hlasovani, hodnoceni, atp.) To nikoho netrapi takovato vec? Vzdyt samotne rfc 1866 o linku tvrdi toto:
>In an anchor address, the URI refers to a resource; it may be used in
>a variety of information retrieval protocols to obtain an entity that
>represents the resource, such as an HTML document. The fragment
>identifier, if present, refers to some view on, or portion of the
>resource.

Tedy jenom o ziskavani dat a ne o provadeni „akci“. Jinak ja nehanim nette ani jeho koncept, jenom mi toto prijde jako velice nebezpecna vec.

Elijen
Člen | 171
+
0
-

Ono to nikoho netrapi, protoze to neni az tak velky problem jak si myslis. Ve verejne casti typicky nemas odkaz na smazani clanku a tu neverejnou nikdo nestahuje a kdyz jo, tak si ma dat bacha sam (kdyz tam das rel=„nofollow“, tak budes z obliga :))

Pokud by te to opravdu trapilo, tak muzes pozadavky posilat ajaxove, pouzit formular nebo nejakou formu captchy.

Jeste k otazce jak volat signal pres formular: signal se vola GET parametrem do=„<nazev-signalu>“, takze staci pouzit <input type="hidden" name="do" value="<nazev-signalu>" />

Editoval Elijen (3. 2. 2012 2:39)

Ot@s
Backer | 476
+
0
-

Malinko absurdní/paranoidní téma. Když už budu ten robot ničitel s ukradenou session, tak není problém ze stránky rozparsovat i ty formuláře a podvrhovat submitty (třeba) na mazání. Pokud bychom takto uvažovali, tak celý admin webu by musel být readonly (i konfirmace mazání via. email by ti někdo mohl za zády provádět, kdyby měl příst. údaje do pošt. schránky).

Možnosti, které by opravňovaly k ne-readonly opearacím:

  • omezení kritických operací na IP
  • tajný příznak v zasílané idenfifikaci prohlížeče
  • potvrzení operace přes odkaz v mailu

PS: hlasování do anket a jiných „nedůležitých“ odkazů via JS nebo formuláře

Editoval Ot@s (3. 2. 2012 8:51)

Nox
Člen | 378
+
0
-

Tak u rel="follow" je samozřejmě jen na konkrétní implementaci bota – dokonce se myslim spekulovalo, jestli to google sám vůbec dodržuje.

Plete se tu problematika botů a celková bezpečnost. Pokud nechceš, aby ti boti chodili na určité adresy (signál je prostě adresa!), tak tam dáš podmínku, že to ignoruje boty, podle nějakých hlaviček – a víc ověřovat není třeba, pokud je to nějaký co neposílá hlavičky že je bot, pak jde o nějaké promile a to se třeba v hlasování neprojeví – a pokud je to něco jiného, zde stále mluvím o bot VS člověk. Neodchycení jednoho bota prostě znamená, že danou url nezkusil člověk ale stroj, což by mě zajímal případ, kdy to kriticky vadí i v zanedbatelném množství.

Dále je zde obecná otázka bezpečnosti.

Použij https://github.com/…tte/pull/469 + ověření práv + se koukni na obecné zabezpečení session

Každopádně argument, že si někdo stáhne stránku botem co kliká na odkazy a použije na to vlastní session, tak je to jeho blbost, že si to tak nakódoval. Je to stejné, jako by na ty tlačítka klikl sám a pomazal si to. Jako by se nepoužilo Nette, ale normální aplikace s odkazy. Atd.

Caine
Člen | 216
+
0
-

@nox: Google rel=„nofollow“ ignoruje – vím z vlastní zkušenosti. Mám na stránce linky pro řazení právě s tímto atributem a stějně na ně googlebot leze.

David Grudl
Nette Core | 8228
+
0
-

Proti robotům se dá použít JavaScriptová ochrana. JavaScript přidá do URL &confirmed=1 a na straně presenteru se přidá proměnná $confirmed a kontroluje se, zda je nastavená.

babcca
Člen | 23
+
0
-

ROBOT := program, ktery prochazi odkazy na strance (omlouvam se, nedefinoval jsem toto slovo)

Porad tu resite presne opacny problem, nez ktery resim ja :(. Ja proste predpokladam ze neco takoveho existuje!! Muze to byt i plug-in do firefoxu, chromu, ktery prochazi linky (v odkazech) a zobrazuje nahledy stranek kam vedou.

Tak jedine, aspon kapku rozumne reseni tu zaznelo toto (@Elijen):
<form action=„…“ method=„get“><input type=„hidden“ name=„do“ value=„<nazev-signalu>“ /></form>
coz se temer blizi k idealnimu, reseni, ale je to strasne pracne na vypisovani.
Tedy vznikla otazka: je nejaky syntax sugar pro to?
Dale nejsem si 100% jist, ale pri pouziti formulare prijdu o nativni podporu ajax, coz ja taky nechci. A musim to dohanet knihovnami z venku a psanim jich primo do kodu.

Jinak prvni reseni co me napadlo bylo ve stylu (predpokladejme, ze existuje n:action podobne n:href):
<form n:action=„delete! $id“><input type=„submit“/></form>
Ale toto je je temer stejny problem jak u odkazu, je tam cela url, tedy „hloupi“ robot ktery hleda vyskyty http://… by tento odkaz nasel.

Dalsi moznosti je vyse uvedeny postup:
<form action=„…“ method=„get“><input type=„hidden“ name=„do“ value=„<nazev-signalu>“ /><input type=„submit“/></form>
Toto se blizi temer k dokonalosti, jedine co me kapinku trapi, je method=„get“, ale to si myslim, ze se da ozelet. Bohuzel u tohoto reseni to znamena psat porad toto

<?php
...
$form = new Form;
$form->setMethod("GET");
$form->addHidden("do", <nazev signalu>);
$form->addSubmit("send");
$form->onSuccess[] = callback($this, '<zpracovani signalu>');
...
?>

Coz je abytecne pracne a porad se opakujici.

Obecny nette ajax funguje tak, ze vezme odkaz, da mu class=„ajax“ a pak v js vola (zjednoduseno) $(„.ajax“).each($.get($(this).href)), tedy zapnout nette ajax nedava smysl. Druha varianta je, nechat vygenerovat odkazy, nekam si ulozit vystup z n:href (treba <a href=„#“ tag=„n:href“></a>) a napsat si vlastni zpracovani onClick.

A posledni poznamka, davat do odkazu akce je sematicky spatne! Akce maji byt ve formularich! Tolik rfc.
Vznika otazka, je najaky specialni duvod proc jsou signaly odkazy?
Jinak je velice zvlastmi, ze to nikoho netrapi :D.

babcca
Člen | 23
+
0
-

A podporuje to primo nette, nebo se o to musim starat sam? Jinak velmi dobre reseni :) Sice prijdu o lidi s vypnutym js, ale ty cert vem.

David Grudl napsal(a):

Proti robotům se dá použít JavaScriptová ochrana. JavaScript přidá do URL &confirmed=1 a na straně presenteru se přidá proměnná $confirmed a kontroluje se, zda je nastavená.

Filip Procházka
Moderator | 4668
+
0
-

Můžeš si napsat formulářovou komponentu (znovupoužitelnost!), která se bude chovat jako odkaz, potom s tím tolik psaní mít nebudeš.

$this['delete35'] = $verify = new VerifyLinkForm('Opravdu smazat?', function () {
	echo "smazáno!";
});
Panda
Člen | 569
+
0
-

babcca napsal(a):

Vznika otazka, je najaky specialni duvod proc jsou signaly odkazy?

A hned na ní vzniká protiotázka: a co jiného by to mělo být?

To, co pořád řešíš, je spíše filosofická otázka než technická. Automaticky bereš signál jako něco, co vykonává nějakou akci. Ale tak to vůbec není! Signál je univerzální signál komponentě od uživatele. A tím signálem může být „teď mi zobraz detaily“, nebo „změň filtrování v tabulce“. Pokud potřebuješ, aby byla akce signálu ve formuláři, udělej jí formulářem. A to už není problém signálu jako takového, ale jeho realizace, která je na Tobě.

A pokud Ti formulář přijde pracný na psaní, napiš si na to makro. :-)

//EDIT: nebo tu komponentu, podle toho, co přesně potřebuješ.

Editoval Panda (3. 2. 2012 12:39)

David Grudl
Nette Core | 8228
+
0
-

babcca napsal(a):

A podporuje to primo nette, nebo se o to musim starat sam? Jinak velmi dobre reseni :) Sice prijdu o lidi s vypnutym js, ale ty cert vem.

Na straně prohlížeče je to věc JS frameworku, třeba jQuery, na straně Nette zkontroluješ hodnotu parametru.

babcca
Člen | 23
+
0
-

@Panda Koncept signalu chapu. Jen mi dela problem, jak jsou prezentovany. Vsechny tipy signalu se hazi do jednoho pytle a ma se na ne odkazovat pres n:href (viz. tutorial [kde delete je odkaz]), tedy jak na ty
>„teď mi zobraz detaily“, nebo „změň filtrování v tabulce“
coz jsou pohledove akce, tak i na
„ted mi vymaz zaznam“ nebo „ted mi proved hlasovani“
coz jsou jenom akce.
Ale oni totozne nejsou. Chapu, ze signaly jsou prostredek. Nechapu styl jejich volani, tak jak se prezentuje (lidi mylne z navodu ziskaji pocit, ze mazat data z db pred odkazy je v poradku). Jinak dekuji za reakci k tematu :).

@HosipLan: Dekuji.
@David Grudl: Dekuji.

Patrik Votoček
Člen | 2221
+
0
-

Pokud jsem dobře pochopil celé tohle vlákno, tak problém je že ty automaticky bereš smazání záznamu jako Nette signál. Přitom máš vyšší požadavky na bezpečnost než je běžné a sám znáš řešení tohoto problému.

Tak proč si prostě neuděláš komponentu (formulář), který tohle bude obstarávat (napíšeš to jednou a pak už to jenom používáš)?

Btw: akce pro smazání má v 99% „confirm“ fázi („Skutečně si přejete smazat záznam ‚foo‘?“).

hrach
Člen | 1838
+
0
-

Upřímě řečeno, má to několik aspektů.

  • už jsem „slyšel“ jednu story, jak se to opravdu s tím robotem stalo. muze byt kec, ale…
  • neni nic otravnejsiho, nez mit mezistranku s otazkou, jestli to opravdu chci udelat (dokonce to tak je v nette examples)
  • destruktivni akce by mely byt reseny pomoci POST pozadavku
  • Nette zatim stale nema CSRF ochranu na signaly, takze v tuto chvili, pokud nekdo ma mazani bez csrf ochrany na signalech, je normalni hazarder
  • zaver: pokud si nemergnech https://github.com/…tte/pull/469, tak ani neuvazuji o danem chovani, dale odkazy tvor
    <a href="{delete! $id}" data-confirm="Opravdu chceš?">smazat</a>

    a pak v javascriptu neco, jak rikal David.

$('a[data-confirm]).live('click', function() {
	var q = $(this).attr('data-confirm');
	if (!confirm(q)) {
		event.preventDefault();
		return false;
	}

	// tady pridat danej &confirm=1, coz moc nevim, jak efektivne zjistit,
	// jestli link uz ma nejaky nejaky query argumenty (jinak by bylo ?confirm=1)
	$(this).attr('href', $(this).attr('href') + '&confirm=1');
});
Ani
Člen | 226
+
0
-

@hrach: Ten signál má určitě ?do= tak když to člověk nemá v routě…

Problém bude spíš u komponent, kde se musí přidat nějaké &{!$control->uniqueId}-confirm=1 aby ho přijmul signál komponenty.

Editoval Ani (3. 2. 2012 18:24)

llook
Člen | 407
+
0
-

Elijen napsal(a):

Ono to nikoho netrapi, protoze to neni az tak velky problem jak si myslis. Ve verejne casti typicky nemas odkaz na smazani clanku a tu neverejnou nikdo nestahuje a kdyz jo, tak si ma dat bacha sam (kdyz tam das rel=„nofollow“, tak budes z obliga :))

To je sice bohužel pravda, že to skoro nikoho netrápí, ale pokud nějaká aplikace umožňuje měnit data pomocí GET požadavků, třebaže po přihlášení, tak je velmi zranitelná. Jestli je někde v dokumentaci mazací tlačítko dělané přes <a n:href="...">delete</a>, tak je to chyba. Tohle bychom nováčky učit neměli.

Mazací tlačítko jedině přes formulář s CSRF ochranou: https://doc.nette.org/cs/forms#…

babcca
Člen | 23
+
0
-

@hrach Dekuji za podporu.
S tim javascriptem je to strasne tezky. Me napadlo toto
$("a[data-confirm]").each(function() { $(this).attr('href', $(this).attr('href') + '&confirm=1'); })
Otazka je, jestli to dokaze zpracovat tento signal i bez ajaxu, tedy dopravdy jako odkaz na ktery se kliklo.

Jinak mohu te poprosit o nejaky zdroj jak zabezpecit signaly proti CSRF v nette?

@ani Myslim, ze David G. myslel, ze si mas primo rict o $_GET promennou a tu kontrolovat. Nejsem Nette guru, nevim jak se generuji odkazy, ale pokud tam je reflexe a zjisti se, ze signal bere dva argumenty tak ty se tam taky vygeneruji pres n:href ⇒ jsme tam kde jsme byli.

Ani
Člen | 226
+
0
-

Já vím co myslel, chtěl jsem tim říct toto:

Tento signál:

<?php
handleAction ($id, $confirm = null){}
?>

Presneter:
{link action! 1}
vygeneruje:
?do=action&id=1
přes JS přidáme confirm=1:
?do=action&id=1&confirm=1

handle obdrží $id=1 a $confirm=1

Ale když to celé bude v komponentě, třeba foo:
{link action! 1}
vygeneruje:
?do=foo-action&foo-id=1
přes JS přidáme confirm=1:
?do=foo-action&foo-id=1&confirm=1

handle obdrží $id=1 a $confirm=null, protože není v getu foo-confirm

Editoval Ani (3. 2. 2012 19:22)

hrach
Člen | 1838
+
0
-

@Ani: dobrej point! Na druhou stranu selector vybira odkazy s data-confirm, ne odkazy se signalem. U komponent nevidim moc problem

if ($this->presenter->getParameter('confirm')) { do it! }

@llook: vseho s mirou, sic s tebou souhlasim, ale nemyslim si, ze je mit vsude post formulare; dokumentace (examples) ale to ma spravne – form s postem. to, co mi vadi, ze to ma s proklikavaci strankou :)

Editoval hrach (3. 2. 2012 19:21)

babcca
Člen | 23
+
0
-

@Ani Vyborne, dekuji :)
Jinak takovy odstrasujici priklad je zde https://doc.nette.org/cs/quickstart u signalu markDone, pokud by tim robot probehl, tak nemame sanci obnovit db do konzistetniho stavu zpet.

Panda
Člen | 569
+
0
-

babcca napsal(a):

@Ani Vyborne, dekuji :)
Jinak takovy odstrasujici priklad je zde https://doc.nette.org/cs/quickstart u signalu markDone, pokud by tim robot probehl, tak nemame sanci obnovit db do konzistetniho stavu zpet.

U QS to bude spolu s ochranou proti CSRF vyřešeno poznámkou v textu s případným odkazem na bližší vysvětlení problému.

Elijen
Člen | 171
+
0
-

llook napsal(a):

Mazací tlačítko jedině přes formulář s CSRF ochranou: https://doc.nette.org/cs/forms#…

No CSRF ochrana se da udelat i pro odkaz … nekde jsem na to dokonce mel komponentu.

mkoubik
Člen | 728
+
0
-
  • destruktivni akce by mely byt reseny pomoci POST pozadavku

Destruktivní akce by měly být řešeny pomocí DELETE požadavku, když už jsme u toho.

Elijen
Člen | 171
+
0
-

Destruktivní akce by měly být řešeny pomocí DELETE požadavku, když už jsme u toho.

Ma to nejaky hlubsi smysl z hlediska bezpecnosti nebo pouzitelnosti? Jelikoz HTML formulare podporuji pouze GET/POST, tak by se DELETE pozadavek musel delat pres AJAX.

Editoval Elijen (4. 2. 2012 12:31)

mkoubik
Člen | 728
+
0
-

To jsem jenom musel upřesnit, když se tady začalo mluvit o rfc. Význam je ten, že až se boti naučí používat javascript, tak ten delete požadavek možná zahodí spíš, než nějaký post.

Panda
Člen | 569
+
0
-

Nedelejme z toho zase vzpouru stroju… Pokud vim, rec je o automatickych preloaderech stranek. Kdyz bude chtit nekdo udelat bota, co bude pouzivat JS, tak to pro nej nebude problem (staci pouzit napriklad htmlunit), pripadne script do browseru a primamanipulace s DOM. Coz mimochodem obejde i to pridavani &confirm do adresy. Takze bud formular, nebo nemit odkaz primo, ale menit adresu az onclick po potvrzeni uzivatelem,pripadne rovnou AJAX. Ale to zase snizuje pouzitelnost na zarizenich bez JS, pripadne s emulovanym JS (opera mini), kde se takove udalosti obcas chovaji dost divoce.