Bezpecnost n:href odkazu pri zpracovani signalu
- babcca
- Člen | 23
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
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
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.
- babcca
- Člen | 23
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
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
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
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
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.
- David Grudl
- Nette Core | 8228
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
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
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
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
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
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
@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
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
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');
});
- llook
- Člen | 407
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
@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
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
@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
@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
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
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.
- Elijen
- Člen | 171
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)
- Panda
- Člen | 569
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.