Formulář přes SSL

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

Ahoj,

mohl by jste mě někdo nakopnout, jak nastavit formuláři, aby se odesílal přes HTTPS?

Celý web mám jinak bez SSL a jedná se o přihlašovací formulář, který je na každé stránce (vytvářený a zpracovávaný pomocí základního BasePresenteru)

Napadlo mě něco jako:

<?php
function createComponentLoginform()
{
	$form = new AppForm($this, 'loginform');

	...

	$form->action = 'https' . substr($form->action, 4);
	return $form;
}
?>

Ale přijde mi to jako prasárna :)

Díky :)

Ondřej Mirtes
Člen | 1536
+
0
-

Pro https se používá parametr Route::SECURED pro danou routu, takže bych dané stránce asi vytvořil speciální routu s tímto parametrem.

To, cos napsal, je fakt špatný :o))

Panda
Člen | 569
+
0
-

LastHunter napsal(a):

Pro https se používá parametr Route::SECURED pro danou routu, takže bych dané stránce asi vytvořil speciální routu s tímto parametrem.

To, cos napsal, je fakt špatný :o))

To nepůjde, protože by musel předělat celý web na https – formulář má na každé stránce, je definovaný v BasePresenteru. Taky jsem chtěl napsat něco o IRouter::SECURED, ale pak jsem si to přečetl pořádně…

DocX
Člen | 154
+
0
-

On ten router bude dělat vlastně problém i tak, protože zabezpečený požadavek se bude snažit přesměrovat na nezabezpečený. Teda pokud bych nezměnil Router tak, aby mu bylo jedno přes jaký protokol byl obdržen request.

Nebo to možná vyřešit jinak, že by se formulář posílal do nějakého konkrétního presenteru s backlinkem jako parametrem. Router na ten zpracovávající presenter by se nastavil s Router::SECURED, takže by se měla action na formuláři vytvořit sama na https.

Jenže to taky nevím jak na to a tady z toho https://forum.nette.org/…jine-strance taky nejsem moc moudrý :(

kravčo
Člen | 721
+
0
-

Ja som vyššie spomínaný postup s dvoma routami použil úspešne (a bezpečne). Dôležité je vedieť, že formulár sa musí zobraziť na už zabezpečenej stránke – preto musí byť každá stránka, na ktorej ho chceme zobrazovať, zabezpečená. U mňa má prihlasovací formulár na starosti prezenter Security:Auth, teda je to v poriadku.

$router[] = new SecureRouter(array(
	'presenter' => 'Security:Auth',
	'action' => 'default',
));
$router[] = new SimpleRouter(array(
	'presenter' => 'Common:Home',
	'action' => 'default',
));
class SecureRouter extends SimpleRouter
{
    public function __construct($defaults = array(), $flags = 0)
    {
        parent::__construct($defaults, $flags | self::SECURED);
    }

    public function match(IHttpRequest $httpRequest)
    {
	// by default, SimpleRouter is greeeeedy...
        if (!$httpRequest->isSecured()) {
            return NULL;
        }

        return parent::match($httpRequest);
    }

    public function constructUrl(PresenterRequest $appRequest, IHttpRequest $httpRequest)
    {
	// by default, SimpleRouter is greeeeedy...
        if ($appRequest->getPresenterName() !== $this->defaults[self::PRESENTER_KEY]) {
            return NULL;
        }

        return parent::constructUrl($appRequest, $httpRequest);
    }
}

Pripomienky a zdrby vítané :)

DocX
Člen | 154
+
0
-

Kravčo: To je celkem pěkné řešení, když máš přihlašovací formulář na jediné konkrétní stránce/presenteru.

Jenže já potřebuji mít formulář na všech stránkách, vytvářený v BasePresenteru a zobrazovaný v @layout.phtml

Nakonec jsem to vyřešil, ovšem znova až zásahem přímo do Nette\Application\Presenter (když to půjde takhle dál, budu mít za chvíli vážně problém držet se aktuální verze Nette):

<?php

class Presenter
{
	/** @var string */
-	private $signalReceiver;
+	protected $signalReceiver;

	/** @var string */
-	private $signal;
+	protected $signal;
}

?>
<?php

class BasePresenter extends Presenter
{

	function createComponentLoginform()
	{
        	$form = new AppForm($this, 'loginform');

	        ...

        	$form->action = $this->link('Login:dologin');
	        return $form;
	}

}

?>
<?php

class LoginPresenter extends BasePresenter
{

	function actionDologin()
	{
		$this->signal = 'submit';
		$this->signalReceiver = 'loginform';

		$this['loginform']->onSubmit[] = array($this, 'loginSubmitted');
		$this['loginform']->signalReceived('submit');

		$this->redirect('Homepage:');
	}

	function loginSubmitted(Form $form)
	{
		...
	}

}
?>

a v routy mám takto:

<?php
//bootstrap.php
...
$router[] = new Nette\Application\Route('<lang>/login/dologin', array(
	'lang' => null,
	'presenter' => 'Login',
	'action' => 'dologin',
), Nette\Application\Route::SECURED);
...
?>

Výsledek je, že formulář má action="https://localhost/cs/login/dologin" i na původně jen http:// stránce. Po zpracování formuláře se přesměruje obět na ne-SSL adresu.

Akorát to není asi úplně nejhezčí, ale opravdu mě nenapadá jak jinak na to :)

kravčo
Člen | 721
+
0
-

kravčo napsal(a):

Dôležité je vedieť, že formulár sa musí zobraziť na už zabezpečenej stránke – preto musí byť každá stránka, na ktorej ho chceme zobrazovať, zabezpečená

Deja vu.

Zabezpečený action nestačí!

oktam
Člen | 25
+
0
-

kravčo napsal(a):

kravčo napsal(a):

Dôležité je vedieť, že formulár sa musí zobraziť na už zabezpečenej stránke – preto musí byť každá stránka, na ktorej ho chceme zobrazovať, zabezpečená

Deja vu.

Zabezpečený action nestačí!

Preco nie?

DocX
Člen | 154
+
0
-

oktam napsal(a):

Preco nie?

To by mě také zajímalo. Takto to má řešené například i centrum.cz, seznam.cz, apod.

Jinak bych musel mít https:// celý web, protože, jak jsem říkal, je to formulář na každé stránce (něco jako třeba na czc.cz)

Ale hlavně nevím, proč pro takto zdánlivě jednoduchou věc musím zasahovat do implementace Nette Presenteru. Buď za Boha nemůžu přijít jak na to Nette-way a nebo to skutečně Nette netankuje :)

Editoval DocX (24. 8. 2009 23:33)

David Grudl
Nette Core | 8147
+
0
-

kravčo napsal(a):

formulár sa musí zobraziť na už zabezpečenej stránke

Formulář se nemusí zobrazovat na https, stačí ho na https odesílat.

DocX napsal(a):

On ten router bude dělat vlastně problém i tak, protože zabezpečený požadavek se bude snažit přesměrovat na nezabezpečený.

Po odeslání formuláře Nette samo nikam nepřesměrováná.

Ale hlavně nevím, proč pro takto zdánlivě jednoduchou věc musím zasahovat do implementace Nette Presenteru. Buď za Boha nemůžu přijít jak na to Nette-way a nebo to skutečně Nette netankuje :)

Nette to netankuje. Budu tohle vlákno brát jako feature request.

DocX
Člen | 154
+
0
-

David Grudl napsal(a):

Formulář se nemusí zobrazovat na https, stačí ho na https odesílat.

Tak to je fajn :) Řešilo by to dost věcí. Vlastně by stačilo jenom nějak přesvědčit router, aby i když to nemá v definici routy vyrobil URL s https://.

Co jsem na to teď rychle koukal, tak by možná stačilo, aby se Router řídil při rozhodování zda http:// nebo https:// i podle příznaků nastavených v PresenterRequestu. Pak už by stačilo jen přidat nějaký parametr (flags nebo jen konkretně na SSL) metodám Presenter::createRequest() a PresenterComponent::link() (který by to předal createRequestu) a ještě upravit třídu Link, aby také uměla zacházet s těmito příznaky.

Výsledek by mohl být ten, že kdykoliv by se tvořil link, mohlo by se říci, že chci SSL (nebo naopak nechci), a on by se tak vytvořil. Ve Formu by to mohlo být nějak zapouzředné (třeba metodou setSSL).

Akorát to tak trochu narušuje filozofii routů, že by pak aplikace věděla tak trochu o výsledné url.

Nette to netankuje. Budu tohle vlákno brát jako feature request.

Díky, jsem zvědav co nakonec vymyslíš :)

Editoval DocX (26. 8. 2009 13:01)

kravčo
Člen | 721
+
0
-

kravčo napsal(a):

Dôležité je vedieť, že formulár sa musí zobraziť na už zabezpečenej stránke – preto musí byť každá stránka, na ktorej ho chceme zobrazovať, zabezpečená.

Nepamätal som si, ako som svojho času tento názor prijal, teraz už viem.

Štandardná situácia je plain formulár a plain action. V tomto prípade môže útočník odpočúvajúci komunikáciu z POST požiadavky poľahky zistiť poslané údaje.

Pri plain formulári a zabezpečenej action prípadnú POST požiadavku čítať nemôže, to čo ale môže čítať (a aj podvrhovať) je stránka, na ktorej je formulár zobrazený. V princípe mu teda nič nebráni doručiť používateľovi stránku, ktorú chcel s len poupraveným action – napr. na svoj skriptík, ktorý zbiera heslá.

Pri zabezpečenej stránke s formulárom i akciou tento prístup nie je možný, keďže autenticita dát je overená. Samozrejme dá sa namietať, že podvrhnúť možno už odkaz na stránku s formulárom a áno, je to tak. Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. Na podvrhnutý action sa nedá prísť inak ako prezretím zdrojového kódu.

DocX
Člen | 154
+
0
-

kravčo napsal(a):

… Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. …

Kdyby už byl útočník uprostřed mojí komunikace, mohl by podvrhnout ten odkaz na stránku s formulářem tak, že by jen odstranil „s“ v https://.. Po té by podvrhl stránku s formulářem a dělo by se to, co jsi popsal. Uživatel by neměl šanci nic poznat.

Ale jinak jde o kokrétní situaci. Pokud půjde o e-banking tak budu mít celou aplikaci přes SSL. Pokud mi jde jen o relativně vyšší pocit bezpečí uživatelů, stačí mi zabezpečená akce.

Kdybych to vzal úplně do hloubky, tak mi ani celý web v HTTPS nemusí zaručit bezpečí, protože když uživatel zadá http://ebanking.cz, může mi útočník nabídnout místo přesměrování na https normálně stránku přímo na http. Může pak fungovat jako nějaká proxy, kde z pohledu banky to jede normálně přes SSL, mezi útočníkem a uživatelem to je nešifrovaný (proč řešit podvržený certifikát ;) ). Samozřejmě jde o uživatele jestli si všimne toho, že mu to neběží zabezpečeně.

Ale i kdyby si toho všiml, mohl mi můj dlohouletý „kamrád na drátě“ podvrhnout odkaz na stažení firefoxu a přibalit si do něj vlastní důvěryhodný certifikát. Případně, že mám ff z distribuce, mohl mi podvrhnout instalační CD distribuce. (Hm z toho mi vyplívá, že nejbezpečnější je asi koupenej Windows s IE)

Atd… ;)

Editoval DocX (26. 8. 2009 17:21)

kravčo
Člen | 721
+
0
-

DocX napsal(a):

kravčo napsal(a):

… Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. …

Kdyby už byl útočník uprostřed mojí komunikace, mohl by podvrhnout ten odkaz na stránku s formulářem tak, že by jen odstranil „s“ v https://.. Po té by podvrhl stránku s formulářem a dělo by se to, co jsi popsal. Uživatel by neměl šanci nic poznat.

Práve, že mal. V tvojom scenári nejde ani tak o text adresy ako o to, či je adresa šifrovaná alebo nie. To zväčša prehliadače dávajú výrazne najavo.

A ak používateľ bezpečnosť nijako nerieši, nepomôžeš mu…

DocX
Člen | 154
+
0
-

A ak používateľ bezpečnosť nijako nerieši, nepomôžeš mu…

S tím jsem ve svých úvahách počítal :) Navíc uživatel nemusí vědět že se měl ocitnout na HTTPS ;) Jinak s tebou samozřejmě souhlasím. Původně jsem myslel, že máš na mysli, že se změní na úplně jinou adresu :)

No ale ať uzavřem tento OT :) „Nejslabší článek je vždy uživatel…“

Editoval DocX (26. 8. 2009 18:51)

David Grudl
Nette Core | 8147
+
0
-

Tak fajn, ukončeme OT a zkusme navrhnout, jak by (globálně) měla podpora SSL v Nette fungovat.

  1. canonicalizace – otázkou je, jestli je fuk, jestli se na jednu stránku dívám přes https a nebo http; nejspíš ano, ale vidí to tak i Google? Chce to najít nějaké podklady.
  2. rozšíření Routeru, aby při generování přihlížel k flagu PresenterRequest::SECURED
  3. rozšíření Presenter::createRequest(), aby takový flag uměl nastavit (tohle je dokonce napůl předpřipravené, odkaz lze psát jako scheme://Presenter:action, jen zatím se scheme ignoruje, bo není vymyšlená syntax. Použít https nebo ssl nebo secured?)
Gringo
Člen | 32
+
0
-

Já si zavedl do vlastní odvozeniny Route pole $secured, které určuje, co se má posílat přes SSL. V bootstrapu pak mám toto:

<?php
DbRoute::$secured = array(
	'PlaceOrder',  // cely presenter
	'JobDirectory:postJob', // jenom action postJob
);
?>

Editoval Gringo (26. 8. 2009 23:39)

DocX
Člen | 154
+
0
-

David Grudl napsal(a):

  1. canonicalizace – otázkou je, jestli je fuk, jestli se na jednu stránku dívám přes https a nebo http; nejspíš ano, ale vidí to tak i Google? Chce to najít nějaké podklady.

Co jsem spěšně našel, tak to asi vidí skutečně jako duplicitu. Viz http://webtrh.cz/…ps-duplicita?…;

Tohle bych ale nechal jak je. Teď mě napadá, že by to možná chtělo vymezit jen na generování linků pro signály (jako je i form submit), co myslíš? Pokud se vlastně nejedná o signál, je to tedy klasická kombinace Presenter:action:params, tak se o adresu postará router (například tím způsobem, který napsal Gringo) a případně ji kanonizuje.

  1. rozšíření Routeru, aby při generování přihlížel k flagu PresenterRequest::SECURED
  2. rozšíření Presenter::createRequest(), aby takový flag uměl nastavit (tohle je dokonce napůl předpřipravené, odkaz lze psát jako scheme://Presenter:action, jen zatím se scheme ignoruje, bo není vymyšlená syntax. Použít https nebo ssl nebo secured?)

To s tím scheme://... se mi docela líbí a přikláněl bych se k syntaxy ‚secured‘ (presenter by měl být oddělen od toho, že HTTP vůbec existuje).

Editoval DocX (27. 8. 2009 0:58)

DocX
Člen | 154
+
0
-

Gringo napsal(a):

<?php
DbRoute::$secured = array(
	'PlaceOrder',  // cely presenter
	'JobDirectory:postJob', // jenom action postJob
);
?>

Tyjo, tohle mi přijde vážně geniální :) Navíc by to mohlo řešit to, že si každý presenter může sám určit jestli chce být zabezpečený jednoduše přidáním se do routeru ve startupu :)


Takže co myslíte?

Měl by Presenter rozhodovat o tom zda a jaké akce budou zabezpečené (potom by na tu šel určitě udělat nějaký obecný mechanismus), tak, že by to oznámil routeru, který by poté případně požadavek kanonizoval

nebo

by mělo toto rozhodovací právo zůstat na Routeru a jeho nastavení v bootstrapu?

Editoval DocX (27. 8. 2009 0:21)

Gringo
Člen | 32
+
0
-

Tak ten startup mě původně ani nenapadl :)

David Grudl
Nette Core | 8147
+
0
-

Podle Marka Prokopa je https vs. http také duplicitní obsah, nepřímo to zmiňuje i Petr Fidler. Viz také SEO konference.

DocX
Člen | 154
+
0
-

David Grudl napsal(a):

Podle Marka Prokopa je https vs. http také duplicitní obsah, nepřímo to zmiňuje i Petr Fidler. Viz také SEO konference.

Já jsem se v původním příspěvku překlepl (myslel jsem rozdílné stránky jakože to nevidí jako jednu a tutéž, ale jako 2 duplicitní).

Co to ale pro nás znamená? Myslím, že automatická kanonizace je jedna z klíčovích výhod Nette routeru. Na tom bych tedy nic neměnil. Měl jsem na mysli původně jen možnost SSL formuláře a ty vyhledávače neindexují.

Nebo jak jsi to myslel ty?

_Martin_
Generous Backer | 679
+
0
-

Ad. duplictiní obsah: a není možné předpokládat, že chci-li mít nějakou stránkou dostupnou pod šifrovaným spojením, chci také, aby byla dostupná pouze pod šifrovaným spojením?

Marek Malevič
Člen | 2
+
0
-

Pekny den, chci se zeptat na stav teto problematiky. Prave resim stejny problem u jedne webove aplikace a tak me zajima, jestli nakonec (pripadne v jakem casovem horizontu) nejake reseni bude nebo mam radeji slevit ze svych predstav a prihlasovani resit na zvlastni strance.

Diky moc za odpoved.

Honza Kuchař
Člen | 1662
+
0
-

Taky si myslím, že by měla být stránka pouze zabezpečená nebo pouze nezabazpečená. Případně by byl redirect.

Marek Malevič
Člen | 2
+
0
-

Ja bych rad, aby mel guest neustale v me aplikaci moznost se prihlastit (formular bych chtel mit vzdy zobrazen) a chci, aby to odesilani jmena a hesla slo pres https. Zaroven mam ale vyrazne vykonnostni problemy pri pouzivani https (vzdycky se u DataGridu dlouho ceka z me neznameho duvodu) a to si u aplikace, kde se predpoklada aktivni prace uzivatele, nemuzu dovolit.

Protoze jedina informace, kterou chci sifrovat, je poslani hesla, pak bych opravdu uvital moznost odeslat heslo pres https, ale zbytek aplikace by dal pokracovala zase klasicky pres http.

Neni mi znam jediny duvod, proc by melo byt na zavadu takove reseni. V podstate neni zabezpecena nebo nezabezpecena stranka. Je pouze zabezpecena a nezabezpecena komunikace. A tu zabezpecenou vyzaduji pouze u hesla.

DocX
Člen | 154
+
+1
-

Marek Malevič napsal(a):

Protoze jedina informace, kterou chci sifrovat, je poslani hesla, pak bych opravdu uvital moznost odeslat heslo pres https, ale zbytek aplikace by dal pokracovala zase klasicky pres http.

Jde to, já to vyřešil následovně:

<?php

// BasePresenter:

function createComponentLoginForm()
{
	$form = new AppForm();
	...

	// odkaz na action "dologin" v "LoginPresenter"
	$form->action = $presenter->link('Login:dologin');
}


// v bootstrapu pridat zabezpecenou routu, aby se link vyse vytovril s https://

$router[] = new Nette\Application\Route('login/dologin', array(
	'presenter' => 'Login',
	'action' => 'dologin',
), Nette\Application\Route::SECURED);

?>

Neni mi znam jediny duvod, proc by melo byt na zavadu takove reseni. V podstate neni zabezpecena nebo nezabezpecena stranka. Je pouze zabezpecena a nezabezpecena komunikace. A tu zabezpecenou vyzaduji pouze u hesla.

Duvod tam je.

Pokud by se nekdo dostal k moznosti jen slyset komunikaci (napr. bydli v baraku na jehoz srese je AP s nesifrovanym „signalem“ na nejz se pripojuje okolnich 10 baraku), tak to staci.

Predstav si ale ze se dostane nejakym zpusobem mezi (man in the middle), tzn ze komunikaci nejen ze slysi, ale muze ji i menit. Pak to nestaci, protoze v okamziku, kdy tvuj server posila nesifrovanou (a nepodepsanou) stranku s formularem, on v ni zmeni prislusnou hodnotu v action na http:// (bez „s“), klidne i stejne adresy. Jakmile pak uzivatel formular odesle (pres ne-ssl), data pujdou znovu skrz nej. K tvemu serveru se prihlasi jakoby on pres SSL a odezvu prelozi zpet uzivateli, aby nic nepoznal. Kdyby jsi ale mel cely web zabezpeceny s certifikatem podepsanym znamou autiritou, tohle by neslo. Teda slo, kdyby utocnik zamezil pristupu uzivatele na SSL, treba by zmenil odkaz ve vysledku google. Je ale fakt, ze dostat se nekomu doprostred komunikace je celkem obtizne.

Doufam ze u nas jeste neni trestne zverejnovani takovychto informaci :o))