Перейти к содержимому

Как экранировать в html

  • автор:

BootstrapTema

Экранирование, преобразование спецсимволов тегов онлайн для изменения угловых скобок < и >HTML кода в демонстрационных примерах кодов, теги станут неактивными при добавлении в HTML страницу и его можно будет показать.

Экранировать Скопировать &#10006 Очистить

Зачем экранировать HTML код?

Всё очень просто, HTML код в чистом не экранированном виде будет активным и его нельзя будет показать окружающим. Обычно экранирование используется для размещения внутри тега или . Наш преобразователь спецсимволов экранирует символы < , >, & , » , ‘ и % . Ваши теги и спецсимволы будут экранированы и код можно безопасно добавить в демонстрационном виде.

Как экранировать вывод в шаблонах

При генерировании HTML из шаблона, всегда существует риск того, что переменная шаблона может вывести ненамеренный HTML или опасный код клиентской стороны. Результатом будет то, что динамеческое содержание может поломать HTML страницы результата, или позволить злому пользователю выполнить межсайтовый скриптинг (XSS-атаку). Рассмотрите этот классический пример:

Hello >
Hello  echo $name ?>

Представьте, что пользователь вводит следующий код в качестве своего имени:

script>alert('hello!') script>

Без какого-либо экранирования вывода, результирующий шаблон приведёт к вызову окна предупредительного сообщения JavaScript:

Hello script>alert('hello!') script>

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

Решением этой проблемы является экранирование вывода. С включенным экранированием вывода, тот же шаблон будет отображаться без вреда, и буквально выводить на экран тег script :

Hello <script>alert('hello!')</script>

Системы шаблонов Twig и PHP подходят к проблеме по-разному. Если вы используете Twig, то экранирование вывода влючено по умолчанию и вы защищены. В PHP, экранирование вывод не автоматическое, что означает, что вам вручную нужно будет экранировать там, где это необходимо.

Экранирование вывода в Twig

Если вы используете шаблоны Twig, тогда экранирование вывода включено по умолчанию. Это означает, что вы защищены сразу после установки от ненамеренных последствий кода, отправленного пользователем. По умолчанию, экранирование вывода предполагает, что содержимое экранируется для вывода HTML.

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

Чтобы отобразить её нормально, добавьте фильтр raw :

Вы также можете отключить экранирование вывода внутри зоны , или во всём шаблоне. Чтобы узнать больше информаии, смотрите Экранирование вывода в документации Twig.

Экранирование вывода в PHP

Экранирование вывода не автоматическое при использовании PHP-шаблонов. Это означает, что разве что вы ясно не выберете экранировать переменную, то вы не защищены. Чтобы использовать экранирование вывода, используйте специальный метод просмотра escape() :

Hello  echo $view->escape($name) ?>

По умолчанию, метод escape() предполагает, что переменная отображается в HTML-контексте (и поэтому переменная экранируется для безопасности HTML). Второй аргумент позволяет вам изменить контекст. Например, чтобы вывести что-то в строке Java-скрипта, используйте контекст js :

var myMsg = 'Hello  echo $view->escape($name, 'js') ?>';

Экранирование (или что нужно знать для работы с текстом в тексте)

SQL инъекции, подделка межсайтовых запросов, поврежденный XML… Страшные, страшные вещи, от которых мы все бы хотели защититься, да вот только знать бы почему это все происходит. Эта статья объясняет фундаментальное понятие, стоящее за всем этим: строки и обработка строк внутри строк.

Основная проблема

Это всего лишь текст. Да, просто текст — вот она основная проблема. Практически все в компьютерной системе представлено текстом (который, в свою очередь, представлен байтами). Разве что одни тексты предназначены для компьютера, а другие — для людей. Но и те, и те, всё же остаются текстом. Чтобы понять, о чем я говорю, приведу небольшой пример:

  
Homo Sapiens Suppose, there is the English text, which I don't wanna translate into Russian

Не поверите: это — текст. Некоторые люди называют его XML, но это — просто текст. Возможно, он не подойдет для показа учителю английского языка, но это — всё еще просто текст. Вы можете распечатать его на плакате и ходить с ним на митинги, вы можете написать его в письме своей маме… это — текст.

Тем не менее, мы хотим, чтобы определенные части этого текста имели какое-то значение для нашего компьютера. Мы хотим, чтобы компьютер был в состоянии извлечь автора текста и сам текст отдельно, чтобы с ним можно было что-то сделать. Например, преобразовать вышеупомянутое в это:

 Suppose, there is the English text, which I don't wanna translate into Russian by Homo Sapiens 

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

Иными словами, мы использовали определенные правила в нашем тексте, чтобы обозначить некое особое значение, которое кто-то, соблюдая те же правила, мог бы использовать.
Ладно, это всё не так уж и трудно понять. А что если мы хотим использовать эти забавные скобки, имеющие какое-то особое значение, в нашем тексте, но без использования этого самого значения. Примерно так:

  
Homo Sapiens Basic math tells us that if x < n and y >n, x cannot be larger than y.

Символы «» не являются ничем особенным. Они могут законно использоваться где угодно, в любом тексте, как в примере выше. Но как же наша идея о специальных словах, типа ? Значит ли это, что » < n and y >» тоже является каким-то ключевым словом? В XML — возможно да. А возможно нет. Это неоднозначно. Поскольку компьютеры не очень справляются с неоднозначностями, то что-то в итоге может дать непредвиденный результат, если мы не расставим сами все точки над i и не устраним неоднозначности.
Решить эту дилемму можно, заменив неоднозначные символы чем-то однозначным.

  
Homo Sapiens Basic math tells us that if x < n and y > n, x cannot be larger than y.

Теперь, текст должен стать полностью однозначным. «<» равносильно «».
Техническое определение этого — экранирование, мы избегаем специальные символы, когда не хотим, чтобы они имели свое особое значение.

escape |iˈskāp| [ no obj. ] вырваться на свободу [ with obj. ] не заметить / не вспомнить [. ] [ with obj. ] IT: причина быть интерпретированным по-разному [. ] 

Если определенные символы или последовательности символов в тексте имеют особое значение, то должны быть правила, определяющие, как разрешить ситуации, когда эти символы должны использоваться без привлечения своего особого значения. Или, другими словами, экранирование отвечает на вопрос: «Если эти символы такие особенные, то как мне их использовать в своем тексте?».
Как можно было заметить в примере выше, амперсанд (&) — это тоже специальный символ. Но что делать, если мы хотим написать «<«, но без интерпретации этого как »

Другие примеры

XML — не единственный случай «страдания» от специальных символов. Любой исходный код, в любом языке программирования может это продемонстрировать:

var name = "Homo Sapiens"; var contents = "Suppose, there is the English text, which I don't wanna translate into Russian"; 

Всё просто — обычный текст четко отделяется от «не текста» двойными кавычками. Таким же образом можно использовать и мой текст из курса математического анализа:

var name = "Homo Sapiens"; var contents ; 

Клево! И даже не нужно прибегать к экранированию! Но, подождите, а что, если я хочу процитировать кого-нибудь?

var name = "Homo Sapiens"; var contents = "Plato is said to once have said "Lorem ipsum dolor sit amet"."; 

Хм… печаль, тоска. Как человек, Вы можете определить где начинается и заканчивается текст и где находится цитата. Однако это снова стало неоднозначным для любого компьютера. Мы должны придумать какие-то правила экранирования, которые помогали бы нам различить буквальный » и «, который означает конец текста. Большинство языков программирование используют косую черту:

var name = "Homo Sapiens"; var contents = "Plato is said to once have said \"Lorem ipsum dolor sit amet\"."; 

«\» делает символ после него не специальным. Но это, опять-таки, значит, что «\» — специальный символ. Для однозначного написания этого символа в тексте, к нему нужно добавить такой же символ, написав: «\\». Забавно, не так ли?

Атака!

Не всё было бы так плохо, если бы просто должны были прибегать к экранированию. Напрягает конечно, но это не так ужасно. Проблемы начинаются, когда одни программы пишут текст для других программ, чтобы те могли его «читать». И нет, это не научная фантастика, это происходит постоянно. Например, на этом сайте, вы, публикуя сообщение, не набираете его в ручную в формате HTML, а пишите лишь только текст, который, в последствие, преобразуется этим сайтом в HTML, после чего, уже браузер, преобразует «сгенерированный» HTML снова в читабельный текст.

Другой распространенный пример и источник многих проблем безопасности — SQL запросы. SQL — язык, предназначенный для упрощения общения с базами данных:

SELECT phone_number FROM users WHERE name = 'Alex' 

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

$query = "SELECT phone_number FROM users WHERE name = 'Alex'"; $result = mysql_query($query); 

Эти две простые строки абстрагируют от нас ужасно сложную задачу запроса программой у БД данных, удовлетворяющих нашим требованиям. БД «просеивает», возможно, терабайты битов и байтов, чтобы вернуть красиво отформатированный результат программе, сделавшей запрос. Серьезно, вся эта хрень инкапсулирована в простом англо-подобном предложении.

Для того, чтобы сделать это полезным, подобные запросы не хард-кодятся, а строятся на основе пользовательского ввода. Это же предложение, направленное на использование разными пользователями:

$name = $_POST['name']; $query = "SELECT phone_number FROM users WHERE name = '$name'"; $result = mysql_query($query); 

В случае, если Вы просто просматриваете эту статью: Это — анти-пример! Это худшее, что Вы когда-либо могли сделать! Это кошмар безопасности! Каждый раз, когда Вы будете писать что-то подобное, будет погибать один невинный котенок! Ктулху сожрет Вашу душу за это!

А теперь давайте посмотрим, что здесь происходит. $_POST[‘name’] — значение, которое некий случайный пользователь ввел в некую случайную форму на вашем случайно веб-сайте. Ваша программа построит SQL-запрос, использующий это значение в качестве имени пользователя, которого Вы хотели бы найти в БД. Затем это SQL «предложение» отправляется прямиком в БД.

Вроде бы звучит все не так ужасно, да? Давайте попробуем ввести несколько случайных значений, которые можно ввести на вашем случайном веб-сайте и какие запросы из этого получатся:

SELECT phone_number FROM users WHERE name = 'Alex' 

Mc’Donalds

SELECT phone_number FROM users WHERE name = 'Mc'Donalds' 

Joe’; DROP TABLE users; —

SELECT phone_number FROM users WHERE name = 'Joe'; DROP TABLE users; --' 

Первый запрос выглядит не страшно, а вполне себе мило, правда? Номер 2, кажется, «несколько» повреждает наш синтаксис из-за неоднозначного ‘. Чертов немец! Номер 4 какой-то дурацкий. Кто бы такое написал? Это ведь не имеет смысла…
Но не для БД, обрабатывающей запрос… БД понятия не имеет от куда этот запрос поступил, и что он должен значить. Единственное, что она видит — это два запроса: найти номер пользователя по имени Joe, а затем удалить таблицу users (что сопровождается комментарием ‘), и это будет успешно сделано.

Для вас это не должно быть новостью. Если это так, то, пожалуйста, прочитайте эту статью еще раз, ибо Вы либо новичок в программировании, либо последние 10 лет жили в пещере. Этот пример иллюстрирует основы SQL-инъекций, применяемых во всем мире. для того, чтобы удалить данные, или получить данные, которые не должны быть просто так получены, или войти в систему, не имея на то прав и т.д. А все потому, что БД воспринимает англо-подобный «приговор» слишком буквально.

Впереееееед!

Следующий шаг: XSS атаки. Действуют они аналогично, только применяются к HTML.
Допустим, Вы решили проблемы с БД, получаете данные от пользователя, записываете в базу и выводите их назад на веб-сайт, для доступа пользователям. Это то, что делает типичный форум, система комментариев и т.д. Где-то на вашем сайте есть что-то подобное:

  Posted by on 

Если ваши пользователи будут хорошими и добрыми, то они будут размещать цитаты старых философов, а сообщения будут иметь примерно следующий вид:

 

Posted by Plato on January 2, 15:31

I am said to have said "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."

Если пользователи будут умниками, то они, наверное, будут говорить о математике, и сообщения будут такие:

 

Posted by Pascal on November 23, 04:12

Basic math tells us that if x < n and y >n, x cannot be larger than y.

Хм… Опять эти осквернители наших скобок. Ну, с технической точки зрения они могут быть неоднозначными, но браузер простит нам это, правда?

 

Posted by JackTR on July 18, 12:56

Хорошо, СТОП, что за черт? Какой-то шутник ввел javascript теги на ваш форум? Любой, кто смотрит на это сообщение на вашем сайте, сейчас загружает и выполняет скрипты в контексте вашего сайта, которые могут сделать не весть что. А это не есть хорошо.

Не следует понимать буквально

В вышеупомянутых случаях, мы хотим каким-то образом сообщить нашей БД или браузеру, что это просто текст, ты с ним ничего не делай! Другими словами, мы хотим «удалить» особые значения всех специальных символов и ключевых слов из любой информации, предоставленной пользователем, ибо мы ему не доверяем. Что же делать?

Что? Что говоришь, мальчишка? Ах, ты говоришь, «экранирование»? И ты абсолютно прав, возьми печеньку!
Если мы применим экранирование к пользовательским данным до объединения их с запросом, то проблема решена. Для наших запросов к БД это будет что-то вроде:

$name = $_POST['name']; $name = mysql_real_escape_string($name); $query = "SELECT phone_number FROM users WHERE name = '$name'"; $result = mysql_query($query); 

Просто одна строка кода, но теперь больше никто не может «взломать» нашу базу данных. Давайте снова посмотрим как будут выглядеть SQL-запросы, в зависимости от ввода пользователя:
Alex

SELECT phone_number FROM users WHERE name = 'Alex' 

Mc’Donalds

SELECT phone_number FROM users WHERE name = 'Mc\'Donalds' 

Joe’; DROP TABLE users; —

SELECT phone_number FROM users WHERE name = 'Joe\'; DROP TABLE users; --' 

mysql_real_escape_string без разбора помещает косую черту перед всем, у чего может быть какое-то особое значение.

Далее, заменим наш скрипт на форуме:

   Posted by on 

Мы применяем функцию htmlspecialchars ко всем пользовательским данным, прежде, чем вывести их. Теперь сообщение вредителя выглядит так:

  

Posted by JackTR on July 18, 12:56

<script src="http://evil.com/dangerous.js" type="text/javascript" charset="utf-8"></script>

Обратите внимание, что значения, полученные от пользователи, на самом деле не «повреждены». Любой браузер парсит этот как HTML и выведет на экран все в правильной форме.

Что возвращает нас к.

Все вышеупомянутое демонстрирует проблему, характерную для многих систем: текст в тексте должно быть подвергнут экранированию, если предполагается, что он не должен иметь специальных символов. Помещая текстовые значения в SQL, они должны быть экранированы по правилам SQL. Помещая текстовые значения в HTML, они должны быть экранированы по правилам HTML. Помещая текстовые значения в (название технологии), они должны быть экранированы по правилам (название технологии). Вот и все.

Для полноты картины
  • Validation
    Вы можете проверить, соответствует ли пользовательский ввод некоторой заданной спецификации. Если Вы требуете ввода числа, а пользователь вводит нечто другое, программа должна сообщить ему об этом и отменить ввод. Если все это правильно организовать, то нет никакого риска схватить «DROP TABLE users» там, где, предполагалось, пользователь введет «42». Это не очень практично, для избегания HTML/SQL-инъекций, т.к. часто требуется принять текст свободного формата, который может содержать «подковырки». Обычно валидацию используют в дополнение к другим мерам.
  • Sanitization
    Вы можете так же «втихую» удалить любые символы, которые считаете опасными. Например, просто удалить что-либо похожее на HTML-тег, что избежать добавления на ваш форум. Проблема в том, что вы можете удалить вполне законные части текста.
    Prepared SQL statements
    Есть специальные функции, делающие то, чего мы и добивались: заставляют БД понять различия между самим SQL-запросом и информацией, предоставленной пользователями. В РНР они выглядят примерно так:
$stmt = $pdo->prepare('SELECT phone_number FROM users WHERE name = ?'); $stmt->execute($_POST['name']); 

При этом отправка происходит в два этапа, четко разграничивая запрос и переменные. БД имеет возможность сначала понять структуру запроса, а потом заполнить его значениями.

C4: Кодирование и экранирование данных¶

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

Контекстное кодирование выходных данных¶

Контекстное кодирование выходных данных является ключевым для безопасного программирования и предотвращения межсайтового выполнения сценариев. Подобная мера защиты применяется при создании интерфейсов пользователя, непосредственно перед динамическим добавлением непроверенных данных к HTML-коду. Тип кодирования будет зависеть от места (или контекста) отображения или хранения данных в документе. Типы кодирования, рекомендуемые к использованию при создании безопасного интерфейса: кодирование сущностей или атрибутов HTML, а также кодирование JavaScript и URL.

Примеры кодирования на Java¶

Примеры использования кодировщика Java, обеспечивающего контекстное кодирование выходных данных, можно посмотреть на сайте проекта кодировщика Java от OWASP.

Примеры кодирования в .NET¶

Начиная с .NET 4.5, библиотека антимежсайтового выполнения сценариев является частью фреймворка, но не используется по умолчанию. Вы можете назначить AntiXssEncoder из этой библиотеки в качестве стандартного кодировщика вашего приложения, изменив настройки web.conf. При кодировании выходных данных необходимо учитывать контекст, т. е. использовать соответствующую функцию из библиотеки AntiXSSEncoder в зависимости от расположения данных в документе.

Примеры кодирования на PHP¶

Zend Framework 2¶

В Zend Framework 2 (ZF2) для кодирования выходных данных может быть использован ZendEscaper. Примеры контекстного кодирования можно посмотреть на странице, посвященной контекстному экранированию с помощью zend-escaper.

Другие способы кодирования и защиты от внедрений¶

Кодирование или экранирование может быть использовано для предотвращения других форм внедрений в контент. Например, можно нейтрализовывать некоторые специальные метасимволы при вводе данных для системных команд. Это называют «экранированием команд ОС», «экранированием shell» и т. п. Подобная защита может быть использована для предотвращения «Внедрения команд».

Существуют и другие формы экранирования, которые могут быть использованы для предотвращения внедрений, например, экранирование атрибутов XML, защищающее от различных форм внедрений XML и XML-путей, а также экранирование уникальных имен LDAP, позволяющее предотвратить различные LDAP-внедрения.

Нормализация и кодировка символов¶

Кодировка Юникод — это способ хранения символов с использованием нескольких байтов. При вводе данных злоумышленник может использовать Юникод, чтобы скрыть вредоносный код и получить возможность проведения различных атак. RFC 2279 описывает несколько способов кодировки текста.

Нормализация — это способ преобразования данных в простую или стандартную форму. В веб-приложениях нормализацию обычно используют для обеспечения единообразия символов всего контента при его хранении или отображении.

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

Предотвращаемые уязвимости¶

  • Топ-10 OWASP 2017 — A1: Внедрение
  • Топ-10 OWASP 2017 — А7: Межсайтовое выполнение сценариев (XSS)
  • Топ-10 OWASP 2014 (мобильные устройства) — M7: Внедрение на стороне клиента

Ссылки¶

  • Межсайтовое выполнение сценариев — общие сведения
  • Памятка OWASP: Предотвращение межсайтового выполнения сценариев (XSS) — предотвращение XSS в веб-приложениях
  • Памятка OWASP: Предотвращение межсайтового выполнения сценариев на основе объектной модели документа
  • Памятка OWASP: Предотвращение внедрений

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *