Latte a chystaný sandbox režim
- David Grudl
- Nette Core | 8227
přesunuto z jiného vlákna
Doslechl jsem se, že někteří uživatelé potřebují sandbox režim, kde lze omezit, co všechno může autor šablony dělat: můžete omezit přístup jen k vybraným filtrům, proměnným, metodám, značkám a funkcím.
Hodí se k vykreslování „nedůvěryhodných“ šablon, které editují samotní uživatelé.
Sám jsem tomu nepřikládal nikdy důležitost, protože vycházím z toho,
že při používání dependency injection může autor šablony dělat jen to,
co mu dovolí objekty, které do ní programátor pošle. Pokud tedy hrozí
nebezpeční, že by se koder přes
$presenter->getContext()->getService('database')->query(...)
dostával tam, kam nemá, jednoduše smažu proměnnou $presenter
ze šablony. Ona je tam předaná jen pro případné užití autorem šablony,
kvůli funkčnosti tam být nemusí. Respektive žádná z automaticky
předávaných proměnných tam být nemusí.
Faktem ale je, že lze těžko zamezit volání delete()
nad
výsledkem z Nette Database Explorer. Nebo přístupu k monostate třídám,
jako je dibi::query(...)
. A nebo všem systémovým PHP funkcím.
Tak jsem oprášil neuvěřitelné 4 roky starý commit a sandbox režim
mergnul.
API
Přístup řídí objekt implementující Latte\Policy
:
interface Policy
{
function isMacroAllowed(string $macro): bool;
function isFilterAllowed(string $filter): bool;
function isFunctionAllowed(string $function): bool;
function isMethodAllowed(string $class, string $method): bool;
function isPropertyAllowed(string $class, string $property): bool;
}
Z API by mohlo být patrné, co vše lze ovlivnit.
Výchozí implementace je třída Latte\Sandbox\SecurityPolicy
má v základu všechno zakázané a jednotlivé věci je potřeba povolit:
$policy = new Latte\Sandbox\SecurityPolicy;
$latte->setPolicy($policy);
$policy->allowMacros(['=', 'foreach', 'block']); // povolí {=$var} a tedy i {$var}, {foreach}, {block}
$policy->allowFilters($policy::ALL); // povolí všechny |filtry
$policy->allowFunctions(['trim', 'explode']); // povolí tyto globální funkce (a potažmo custom funkce)
$policy->allowMethods(DateTime::class, ['format']); // povolí volat tyto metody nad objekty DateTime
$policy->allowProperties(Nette\Database\Table\ActiveRow::class, $policy::ALL); // povolí přístup ke všem properties
Aktivace
Bezpečnostní pravidla se uplatní pro šablony, které se načtou novým
makrem {sandbox untrustworthy.latte}
(na rozdíl od
{include ...}
).
Pokud se mají pravidla použít už na první renderovanou šablonu, je
potřeba to sdělit skrze: $latte->setSandboxMode();
.
Potřeboval bych spolupráci od těch, kteří sandbox chtějí
používat. Jak navrhnout co nejlépe třídu
Latte\Sandbox\SecurityPolicy
, co změnit, aby byla dobře
použitelná, najít co nefunguje atd.