Подтвердить что ты не робот

Html/XSS escape на входе и выходе

Из всего, что я видел, похоже, что соглашение об экранировании html на введенном пользователем контенте (с целью предотвращения XSS) заключается в том, чтобы делать это при рендеринге контента. Большинство языков шаблонов, похоже, делают это по умолчанию, и я сталкивался с такими вещами, как qaru.site/info/247276/..., утверждая, что эта логика является заданием уровня представления.

Итак, мой вопрос: почему это так? Для меня кажется, что на входе (например, в форме или модели) вы можете избежать выхода, так что вы можете работать в предположении, что что-либо в базе данных безопасно отображать на странице по следующим причинам:

  • Разнообразие форматов вывода - для современного веб-приложения вы можете использовать комбинацию html-рендеринга на стороне сервера, веб-приложение javascript с использованием ajax/JSON и мобильного приложения, которое получает JSON (и которое может или может не иметь некоторых веб-просмотров, которые могут быть приложениями javascript или обработанными сервером html). Таким образом, вам нужно иметь дело с html, убегающим повсюду. Но вход всегда будет создан как модель (и проверен) до сохранения в db, и ваши модели могут наследовать один и тот же базовый класс.

  • Вам уже нужно быть осторожным в отношении ввода, чтобы предотвратить атаки с использованием кода (при условии, что это обычно абстрагируется с ORM или курсором db, но все же), поэтому почему бы и не беспокоиться о том, что html не работает здесь, t нужно беспокоиться о чем-либо связанном с безопасностью на выходе?

Мне бы хотелось услышать аргументы о том, почему предпочтительнее использовать html-экранирование на странице.

4b9b3361

Ответ 1

Исходное заблуждение

Не путайте санитарию вывода с проверкой.

В то время как <script>alert(1);</script> - это абсолютно правильное имя пользователя, оно обязательно должно быть экранировано перед показом на веб-сайте.

И да, есть такая вещь, как "логика представления", которая не связана с "бизнес-логикой домена". И указанная логика представления - это то, с чем связан уровень представления. И экземпляры View в частности. В хорошо написанном MVC представления представляют собой полномасштабные объекты (в отличие от того, что RoR попытается рассказать вам), которые при применении в веб-контексте жонглируют несколькими шаблонами.

О ваших причинах

Различные форматы вывода должны обрабатываться разными видами. В каждом случае правила и ограничения, которые управляют HTML, XML, JSON и другими форматами, различны.

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

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

Ответ 2

В дополнение к уже написанному:

  • Именно потому, что у вас есть множество выходных форматов, и вы не можете гарантировать, что все они будут нуждаться в HTML-экранировании. Если вы обслуживаете данные через JSON API, вы не знаете, нужен ли ему клиент для HTML-страницы или текстового вывода (например, электронной почты). Почему вы должны заставить своего клиента unescape "Jack &amp; Jill" получить "Джек и Джилл"?

  • По умолчанию вы портите свои данные.

    • Когда кто-то выполняет поиск по ключевым словам для "amp", они получают "Jack and Jill". Зачем? Потому что вы испортили свои данные.

    • Предположим, что один из входов - это URL: http://example.com/?x=1&y=2. Вы хотите проанализировать этот URL-адрес и извлечь параметр y, если он существует. Это тихо терпит неудачу, потому что ваш URL-адрес поврежден в http://example.com/?x=1&amp;y=2.

  • Это просто неправильный слой, чтобы сделать это - материал, связанный с HTML, не должен смешиваться с необработанной обработкой HTTP. База данных не должна хранить вещи, связанные с одним возможным выходным форматом.

  • XSS и SQL Injection не являются единственными проблемами безопасности, есть проблемы для каждого вывода, с которым вы имеете дело - например, файловая система (например, такие расширения, как ".php", которые вызывают веб-серверы выполнить код) и SMTP (думаю, символы новой строки) и любое количество других. Думая, что вы можете "справиться с безопасностью на входе, а затем забыть об этом", снижает уровень безопасности. Скорее вы должны делегировать экранирование на конкретные серверы, которые не доверяют их входным данным.

  • Вы не должны делать HTML-экранирование "повсюду". Вы должны делать это ровно один раз для каждого выходного файла, который ему нужен - точно так же, как с любым экранированием для любого бэкэнд. Для SQL вы должны выполнять SQL-экранирование один раз, то же самое для SMTP и т.д. Обычно вы не будете выполнять any, вы будете использовать библиотеку, которая обрабатывает его для вас.

    Если вы используете разумные рамки/библиотеки, это не сложно. Я никогда не применяю SQL/SMTP/HTML в моих веб-приложениях вручную, и у меня никогда не бывает уязвимостей XSS/SQL. Если ваш метод создания веб-страниц требует, чтобы вы не учитывали возможность экранирования или в результате получили уязвимость, вы делаете это неправильно.

  • Выполнение экранирования на уровне входа/формы ввода не гарантирует безопасность, потому что ничто не гарантирует, что данные не попадут в вашу базу данных или систему с другого маршрута. Вы должны вручную обеспечить, чтобы все входы в вашу систему применяли экранирование HTML.

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

  • Даже веб-входы в систему небезопасны, потому что часто применяется другой уровень кодирования, например. вам может понадобиться входной код с кодировкой base64 в некоторой точке входа. Автоматическое выключение HTML пропустит любой HTML-код, закодированный в этих данных. Поэтому вам нужно будет снова выполнить HTML-экранирование и не забудьте сделать и отслеживать, где вы это сделали.

Я расширил их здесь: http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea/