Шаблонизатор Smarty - нужно ли автоэкранирование?

Фанат

oncle terrible
Команда форума
Одна и та же переменная может использоваться в двух разных контекстах:
Вооот! Именно поэтому второй пункт противоречит первому:
область действия автоэкранирования очень конкретна:
Ну вот из твоих же примеров и видно, что область неконкретная. Это как с SQL - "область действия автоэкранирования очень конкретна - SQL". Но SQL неоднороден, и каждый литерал требует своего форматирования.

А по первому пункту - да, согласен. Он годится в аргументы того, что

предварительное форматирование на роль автоформатирования не годится в принципе.

Но я хочу вернуться вот к этому пункту
Наверное, mysql_real_escape_string() ты тоже ставишь ручками и только там, где «нужно».
Здесь надо понимать два момента.
1. Негодность mysql_real_escape_string() для форматирования. Поэтому сразу откажемся от нее в пользу PDO::quote()
2. Наличие того самого дефолтного форматирования.
И с этими поправками - ты будешь смеяться - да, ставлю!
Когда я пишу код
PHP:
$stm = $pdo->prepare("SELECT name FROM table WHERE id=?");
$stm->execute(array($id));
То таки да - я именно что говорю PDO: "отформатируй мне id, как строку, поскольку мне лень указывать конкретный фильтер".
При этом dbSimple будет сильно нагляднее в этом смысле, поскльку ее строковый плейсхолдер - это как раз просто ? , без модификаторов. Это и есть дефолтный искейпинг.
Сам символ ?, без модификаторов - это и есть "автоформатирование переменной, как строки"

То есть, знак вопроса - это то самое, что ты имел в виду под " mysql_real_escape_string()". А ставлю ручками потому, что других вариантов нету.
Так что, на самом деле всё так и есть :)

Вопрос - ПОЧЕМУ я так делаю.

И здесь я снова хочу сесть на свою кобылу про безопасность.
В PDO и dbSimple оно работает потому, что даже отформатировав идентификатор(массив, кейворд, что угодно), как строку, ты получишь ошибку, но не получишь инъекцию.
Поэтому дефолтный (АКА авто-) искейпинг работает в них идеально.
А вот с хтмл это уже не прокатывает.
Поэтому я и говорю о том, что дефолтный должен быть каким-то другим.

Потому что я считаю именно безопасность основной причиной автоискейпинга, а не облегчение жизни кодеру, которому лень написать e().
 

fixxxer

К.О.
Партнер клуба
Автоэкранирование в template engines чем-то похоже на плейсхолдеры: в том смысле, что данные передаются как есть, а преобразования происходят уже "внутри черного ящика". ;)

В случае со smarty/twig, это вообще влияет не на данные, а на подстановку компилятором выражения вида htmlspecialchars() в компилированный шаблон.

С js-контекстом и подобными - вопрос ровно такой же, как в sql с кавычками: в случае с var a = "{{ x }}" ничего страшного (кавычки у нас &quot), а если var a = {{ x }}, ну там что угодно будет, но надо быть совершенно упоротым, чтобы такое написать, это что-то сродни eval($_GET['x']). И вообще подставлять что-то в js это способ совершенно идиотский, если что-то нужно в js - подставлять надо в атрибуты тэгов, а из js-а вычитывать.
 

fixxxer

К.О.
Партнер клуба
Дело не в "лень", а в "легко забыть".

Смотрим, например, http://corp.*****.com/security-board/, считаем сколько там xss-ов. Уверен, что если бы в blitz templates был автоэскейпинг, xss-ов бы было ровно 0 (ну может один очень хитрый =). (Кстати, он в blitz таки недавно появился.)

Утверждение, что "разработчик сам знает", сродни утверждению "разработчик сам знает, где при составлении sql-запроса присунуть mysql_real_escape_string", что очевидная фигня.
 

Фанат

oncle terrible
Команда форума
Дело не в "лень", а в "легко забыть".
Ну да - я ж именно это и пишу :)
Что безопасность, а не лень.

И вот с точки зрения безопасности хочется составить такой же чит-шит, как с SQL-ем:
- все подставляем только через плейсхолдеры
- должны быть готовые плейсхолдеры для всего, что может попасть в запрос.
- для чего нету плейсхолдера - попадает через белый список.
- идентификаторы, по-хорошему, тоже через белый список.

А для шаблонов что писать?
"если что-то нужно в js - подставлять надо в атрибуты тэгов, а из js-а вычитывать."?
Имхо, какое-то скользкое решение
 

Вурдалак

Продвинутый новичок

Фанат

oncle terrible
Команда форума
Ну вот я опять буду повторяться.
Перепутав контекст в SQL, ты не получишь инъекцию. (ну, кроме ?p плейсхолдера, хе-хе %)
А перепутав в шаблоне - запросто. Причем ты даже и не отловишь ошибку, как с эскуэлем - вот в чем беда!
 

fixxxer

К.О.
Партнер клуба
Ну потому что смешиваются два разных языка.
Если я начну плейсхолдерами подставлять значения в, например, код хранимой процедуры, я тоже получу схожие проблемы.
Сменил язык - надо указать, что сменил, куда деваться-то.

В том же твиге есть средства для сведения этого на нет, если придерживаться определеных правил.
Например, можно javascript-шаблоны разместить в отдельной директории (или с другим расширением) и указать для них js-автоэксейпинг.
PHP:
class TwigEscapingGuesser
{
    function guess($filename)
    {
        // get the format
        $format = substr($filename, strrpos($filename, '.') + 1);

        switch ($format) {
            case 'js':
                return 'js';
            case 'css':
                return 'css';
            case 'html':
            default:
                return 'html';
        }
    }
}

$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
    'autoescape' => array(new TwigEscapingGuesser(), 'guess'),
));
 

Вурдалак

Продвинутый новичок
Я считаю, что этот пример противоречит твоей фразе про однородность.
Я такого слова-то не употреблял. У меня вызывает недоумение, от того, что ты не видишь разницы в области видимости magic_quotes и {% autoescape %} ... {% endautoescape %}.
 

Фанат

oncle terrible
Команда форума
Я такого слова-то не употреблял.
Да, сорри. Но конкретность я понимаю примерно так же.
Про magic_quotes я и забыл уже. Но успел с тобой согласиться, что предварительное форматирование (по типу волшебных кавычек) не годится совершенно. Форматировать надо только по месту.

Я сейчас уже про другое.
И в этом другом мне уже контексты не нравятся (вот такой я привередливый %)
Как-то это всё представляется шатко, ненадёжно.

Мне куда больше нравится идея с неким буллет&фул-пруф дефолтным вариантом автоискейпинга (не уверен, правда, что такой существует), а остальное выставляется руками. Совсем ведь несложно проставить тип значения. Зато однозначности будет больше, а магии - меньше.

В общем, если подытожить, то я бы ввел правила по типу своих плейсхолдеров - чтобы к переменной в принципе нельзя было обратиться, не указав ее тип.
И с этой точки зрения, хоть и не хочется, но придется согласиться с заезжим профессором - что от автоискейпинга больше вреда, чем пользы.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Мне куда больше нравится идея с неким буллет&фул-пруф дефолтным вариантом автоискейпинга (не уверен, правда, что такой существует), а остальное выставляется руками. Совсем ведь несложно проставить тип значения. Зато однозначности будет больше, а магии - меньше.

В общем, если подытожить, то я бы ввел правила по типу своих плейсхолдеров - чтобы к переменной в принципе нельзя было обратиться, не указав ее тип.
не-не-не, ты все правильно говоришь! на примере твига, дефолтный автоэскейпинг, включенный в режим хтмл (что и так по дефолту) эскейпит все до уровня плейн-текста, что собственно и требуется. Но там, где это нужно, ты можешь ИЗМЕНИТЬ политику эскейпинга, сказав, что у тебя там например JS, или вообще, нормальный чистый и безопасный хтмл.
 

Фанат

oncle terrible
Команда форума
  • область действия автоэкранирования очень конкретна: HTML-шаблон, либо его часть (между двумя тегами). Поэтому удивляться, что в HTML-шаблоне данные встраиваются по умолчанию с примением HTML-экранирования, по меньшей мере странно.
До меня только сейчас дошло, что речь идет о тегах autoescape.
В принципе, я бы не хотел сводить дискуссию об автоформатировании к столь частному случаю, как autoescape в твигги.
В смарти, как я понимаю, такого переключения контекстов автоискейпинга нету ведь?
 

fixxxer

К.О.
Партнер клуба
В смарти можно явно указать для конкретной переменной, что-то типа типа | e('js') насколько я помню.

Но вообще в любом случае стратегия "по дефолту все оборачиваем в htmlspecialchars" - это лучше, чем "по дефолту ничего не делаем". Это покрывает 99% случаев.
 

Фанат

oncle terrible
Команда форума
дефолтный автоэскейпинг, включенный в режим хтмл (что и так по дефолту) эскейпит все до уровня плейн-текста, что собственно и требуется. Но там, где это нужно, ты можешь ИЗМЕНИТЬ политику эскейпинга, сказав, что у тебя там например JS, или вообще, нормальный чистый и безопасный хтмл.
Эх.
У меня всё эти идея-фикс про безопасность. И такой вариант мне не подходит, как мне кажется.

Я повторю свой тезис вкратце:
Если в dbSimple или в PDO написать что-то вроде
PHP:
$stm = $pdo->prepare("SELECT name FROM table WHERE ?=?");
$stm->execute(array('id',1));
То мы получим, с одной стороны бесполезный, но с другой - всё равно абсолютно безопасный запрос.
То есть, дефолтное форматирование АКА автоэскейпинг обеспечивает нам кроме всего прочего ещё и защиту от дурака.
А в автоэскейпинге смарти и твига такая защита не обеспечивается.

Но как ее обеспечить - я, увы, и сам не знаю.
 

Фанат

oncle terrible
Команда форума
Это покрывает 99% случаев.
Ну вот разве что.
Хотя опять же - в голову все равно неудержимо лезут эти чертовы волшебные кавычки, которые - если забыть про порчу данных - тоже, в общем-то, покрывали те самые 99%, если кавычек для чисел не жалеть...
 

флоппик

promotor fidei
Команда форума
Партнер клуба
PHP:
$stm = $pdo->prepare("SELECT name FROM table WHERE ?=? AND id = ".$_GET['q']);
$stm->execute(array('id',1));
И толку? Такой же уровень, от совершенно полного идиота не защитит. Требует наличия элементарного здравого смысла.

Автоэскейпинг хорош тем, что защищает нормального разработчика от забывчивости, а не спасает от идиотизма.
 

Фанат

oncle terrible
Команда форума
Требует наличия элементарного здравого смысла.
Я сейчас выступаю в роли адвоката дьявола, но этот пример я считаю некорректным.
Речь идет про защиту от дурака при соблюдении правил игры.
Понятно, что сдуру можно и ствол сломать, но если человеку дать простую вводную "в запрос - только через плейсхолдер", то при соблюдении этого правила он хотя бы не пропустит инъекцию.
А с автоэскейпингом получается хорошо, но малость дыряво. Ну вот как с magic quotes, будь они неладны.

Но, может быть, я слишком усложняю.
Надо будет бадушнегов подергать, к чему они в итоге пришли.
А вот кстати!
Уверен, что если бы в blitz templates был автоэскейпинг, xss-ов бы было ровно 0 (ну может один очень хитрый =). (Кстати, он в blitz таки недавно появился.)
Автоискейпинг, кстати, они вводили аккурат год назад, во время прошлогодней конфы. И фигли, что называется, толку?
 

fixxxer

К.О.
Партнер клуба
Думаю, что ввели автоэскейпинг !== включили его везде глобально прям сразу.
Это ж везде надо лишние htmlspecialchars убрать в php-вьюхах.

Правила игры, мне кажется, достаточно простые:

1) если пишешь html-шаблон, то все переменные по умолчанию эскейпятся, и можно безопасно писать просто {{ var }}
2) если делаешь подстановки в javascript или css, не забудь указать соответствующий режим экранирования

Вроде достаточно внятно, не?
 

hell0w0rd

Продвинутый новичок
А, вспомнил... Сейчас все дружно смеяться будем.

PHP:
{capture name="myblock"}{$url}{/capture}
{$smarty.capture.myblock}
Сколько раз будет применён автоэскейпинг?... Один? Два? Кто больше?
Не знаю как в смарти, твиг экранирует только 1 раз, даже если у тебя по дефолту стоит автоэкскейпинг, блок с автоэксейпингом и дополнительно фильтр на эскейпинг.
Ровно как и отменит в обратном порядке. То есть есть система приоритетов у фильтров, что очень круто. Думаю в смарти все также сделано)
 
Сверху