§

Введення

Режим
Стиль сутності
Область кодування
§

Виведення

Веб-команди звертаються до кодування HTML-сутностей щоразу, коли введений користувачем текст потрапляє всередину серверно рендереної сторінки або шаблону email. Чит-лист OWASP з запобігання XSS визначає кодування сутностей як Правило №1 для контексту тіла HTML, а кодування виведення є базовою вимогою для веб-застосунків. Цей браузерний кодек використовує близько 200 поширених іменованих сутностей та числовий запасний варіант для решти, тому відповідь збігається з тим, що `htmlspecialchars` або автоекранування React видають у продакшні.

Як працює кодування HTML-сутностей

HTML-сутність — це символьне посилання, яке браузер розбирає назад в єдиний символ. П'ять зарезервованих символів HTML (<, >, &, ", ') завжди потребують кодування, коли текст рендериться як HTML; все інше є необов'язковим і залежить від кодування документа.

  1. Виберіть режим та область. Режим кодування проходить введення символ за символом. Режим декодування шукає шаблони сутностей у введенні. Перемикач області вирішує, чи кодуються лише п'ять HTML-безпечних символів, чи також кожна не-ASCII кодова точка.
  2. Виберіть стиль сутності. Іменовані сутності (&copy;) добре читаються у джерельному коді. Десяткові посилання (&#169;) та hex-посилання (&#xA9;) охоплюють кожну кодову точку Unicode без необхідності назви. Старіші поштові клієнти та XML-парсери надають перевагу числовим формам.
  3. Прохід по введенню. При кодуванні ми зчитуємо кожну кодову точку та шукаємо її у вбудованій таблиці близько 200 поширених іменованих сутностей. Для відсутніх використовується числовий запасний варіант. При декодуванні ми сканируємо за допомогою одного регулярного виразу, що відповідає &name;, &#NNN; та &#xHH; за один прохід.
  4. Відображення на символи. Іменовані збіги розв'язуються через зворотну таблицю. Числові збіги проходять через String.fromCodePoint з основою 10 або 16. Невідомі іменовані сутності залишаються незмінними, тому часткове введення зберігається без втрат.
  5. Живий режим. Увімкніть живий режим, і кожне натискання клавіші повторно запускає конвертацію з затримкою 150 мс. Корисно, коли ви налаштовуєте фрагмент і хочете негайний зворотний зв'язок перед вставлянням у шаблон.

Навіщо кодувати HTML-сутності

  • Захистіть введення користувача від зламу макету. Коли користувач вводить випадковий < у поле коментаря, вставлення цього тексту безпосередньо в HTML переписує решту сторінки. Кодування зарезервованих символів спочатку означає, що браузер рендерить символ замість того, щоб розібрати його як початок тегу.
  • Зберігайте значення атрибутів дійсними. Вбудовування рядка в лапках всередину HTML-атрибута потребує заміни вбудованих лапок на &quot; (для атрибутів у подвійних лапках) або &#39; (для одинарних). Інакше парсер закриє атрибут раніше, і решта рядка стане зайвою розміткою.
  • Знешкодьте випадковий HTML у збережених даних. Журнали, звіти про помилки та експорти чатів часто містять справжні кутові дужки та амперсанди. Кодування сутностями дампу перед вставлянням у сторінку документації зберігає цей вміст видимим як текст замість того, щоб запускати рендерер або автовизначник посилань.
  • Безпечно діліться фрагментами коду. Розміщення прикладного тегу, як-от <script>alert(1)</script>, у публікації блогу, email або Slack-повідомленні потребує кодування дужок, щоб фрагмент відображався, а не виконувався. Та сама техніка охоплює тіла RSS-каналів та поля `description` JSON-LD.

Поширені застосування

Кодування сутностей зустрічається скрізь, де звичайний текст компонується в HTML під час виконання — навіть коли фреймворк зазвичай обробляє це за вас, ручний інструмент корисний у моменти, коли він цього не робить.

  • Серверно рендерені шаблони: Jinja2, ERB, Twig та Handlebars автоматично екранують за замовчуванням, але raw-блоки та маркери `safe` вимикають це — кодек дозволяє підтвердити, що мало б видати екранування.
  • Авторинг email та розсилок: багато механізмів шаблонів ESP не автоматично екранують поля злиття, тому розумні лапки та символи авторських прав у іменах, введених користувачем, потребують попереднього кодування.
  • Документація та зразки коду: вставлення прикладного HTML-тегу у публікацію Markdown або фрагмент статичного сайту потребує кодування дужок, щоб рендерер розглядав це як видимий текст.

Практичний приклад

Вставте <script>alert('hi')</script> у введення з режимом Кодувати, стилем Іменований, областю Мінімальна. Виведення читається як &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;. Перемкніть стиль на Числовий hex, і те саме введення дає &#x3C;script&#x3E;alert(&#x27;hi&#x27;)&#x3C;/script&#x3E;. Перейдіть у режим Декодувати, вставте закодований рядок назад, і оригінальний тег повертається.

FAQ

Що таке HTML-сутності?

HTML-сутності — це символьні посилання, які браузер замінює назад на окремі символи при розборі сторінки. Вони мають три форми: іменовані (як &amp; для &), числові десяткові (&#38;) та числові hex (&#x26;). П'ять зарезервованих символів HTML (<, >, &, ", ') потребують кодування щоразу, коли текст вставляється в HTML. Інші близько 2 225 іменованих сутностей охоплюють символи, наголоси та грецькі літери, але є необов'язковими, якщо кодування документа — UTF-8.

Коли використовувати іменовані сутності замість числових?

Використовуйте іменовані сутності, коли хочете, щоб джерело читалося зрозуміло (людина, яка переглядає &copy; у шаблоні, одразу це розуміє). Використовуйте числові (десяткові або hex), коли споживач є старішим або суворішим — XML-парсери, старі поштові клієнти та деякі читачі каналів розпізнають лише невелику підмножину іменованих сутностей HTML5, але всі вони розпізнають числові форми. Hex перемагає в контекстах, орієнтованих на безпеку, оскільки відповідає один до одного нотації кодової точки Unicode у специфікаціях.

Чи декодує він hex-сутності, як-от &?

Так. Декодер використовує один регулярний вираз, що відповідає всім трьом формам сутностей за один прохід: &name;, &#NNN; та &#xHH;. Числові збіги розв'язуються через String.fromCodePoint з основою 10 або 16. Змішане введення (іменовані та числові в одному рядку) декодується правильно, а невідомі назви залишаються як буквальний текст, тому часткове введення зберігається без втрат.

Чи безпечно використовувати з ненадійним введенням?

Сам кодек є браузерним і не надсилає ваше введення нікуди. Чи безпечно вбудовувати виведення, залежить від контексту. Кодування сутностей обробляє контексти тіла HTML та значень атрибутів, що охоплює випадок Правила OWASP №1. Контексти JavaScript (вбудовані обробники подій, блоки `<script>`), контексти CSS та URL кожен потребує власних правил кодування — лише кодування сутностей там є недостатнім. Для захисту на стороні сервера в глибину поєднайте це з контекстно-усвідомленим механізмом шаблонів, як-от DOMPurify або автоекранування вашого фреймворку.

Кодування сутностей на стороні браузера знаходиться на межі між введенням користувача та рендереним HTML. Виконання конвертації локально означає, що ви можете перевірити те, що міг би видати ваш фреймворк, не надсилаючи оригінальний текст до стороннього інструменту.