У навчальному каталозі назва товару містить кутові дужки й лапки. Після вставлення в PHP-шаблон частина назви стає жирною, хоча редактор вводив звичайний текст. Це ознака того, що браузер отримав дані як розмітку. Безпечний вивід у PHP починається з правильного розділення тексту та HTML: нижче перевіримо його на маленькому файлі без бази даних, реальних користувачів і небезпечних сценаріїв.
Завдання вправи конкретне: однаковий рядок має залишитися текстом і в абзаці, і в значенні поля. Ми не створюватимемо універсальний очищувач для всіх форматів. Натомість отримаємо відтворювану перевірку двох визначених місць виводу, а також межі, за якими потрібен інший підхід. Навчальні дані не є прикладом інциденту клієнта AriZone.
Спочатку визначте місце, куди потрапляє значення
Відкрийте шаблон і знайдіть конкретну операцію виводу назви: echo, короткий тег виводу або виклик шаблонізатора. Поруч запишіть, де браузер прочитає результат. Текст між звичайними тегами та значення звичайного текстового атрибута в лапках — це не те саме, що JavaScript, CSS або URL. Назва змінної сама по собі нічого не говорить про безпечність її вставлення.
Не починайте з масової заміни всіх рядків у базі. Один запис може використовуватися у листі, JSON-відповіді та HTML-сторінці, де правила різні. Збережіть вихідний текст і застосовуйте потрібне перетворення біля відповідного виводу. Перевірка довжини та дозволеного формату на вході теж потрібна, але не замінює цей крок. Наприклад, цілком допустима назва може містити амперсанд.
Для вправи потрібен налаштований підтримуваний PHP CLI, редактор і новий тестовий каталог поза публічною директорією сайту. Додаткові пакети, адміністративні права та з’єднання з сервером не потрібні. Не редагуйте робочу тему заради експерименту. Якщо команда php відсутня, скористайтеся вже налаштованим інтерпретатором середовища розробки; встановлення іншого середовища не є частиною цього прикладу.
Збережіть текст у двох контрольованих місцях
Створіть у тестовому каталозі новий файл escape-demo.php з наведеним вмістом. Назва файла умовна: якщо зміните її, змініть також команди нижче. Рядок label — вигадані дані, замінювати його справжніми заявками не потрібно. Функція призначена лише для тексту в HTML і звичайних текстових атрибутів у лапках. Не застосовуйте її до довільного атрибута лише тому, що він оточений лапками.
<?php
function escapeHtml(string $text): string
{
return htmlspecialchars(
$text,
ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5,
'UTF-8'
);
}
$label = '<strong>Demo & "draft"</strong>';
?>
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Escaping demo</title>
<p><?= escapeHtml($label) ?></p>
<input value="<?= escapeHtml($label) ?>">
</html>
Виклик htmlspecialchars має явно вказані параметри, щоб поведінка не залежала від випадкового налаштування кодування. ENT_QUOTES охоплює обидва види лапок, ENT_SUBSTITUTE задає заміну некоректних послідовностей, а ENT_HTML5 відповідає типу документа прикладу. Докладний опис є в офіційному довіднику PHP. Заміна пошкоджених символів не виправляє джерело даних: причину неправильного кодування потрібно досліджувати окремо.
Зверніть увагу на подвійні лапки навколо value: дані не повинні самостійно визначати межі атрибута. Ми фіксуємо назву атрибута й структуру документа в шаблоні, а змінною залишаємо тільки його текстове значення. Приклад не формує динамічних назв тегів, атрибутів чи обробників подій. Це свідомо вузька задача, для якої можна сформулювати зрозумілий результат.
Перевірте HTML, а не лише відсутність помилок PHP
У терміналі перейдіть саме до каталогу з новим файлом і виконайте обидві команди. Перша перевіряє синтаксис без виконання, друга запускає локальний приклад і друкує документ у термінал. Вони не встановлюють залежності й не змінюють дані сайту. Не запускайте цей файл на продуктивному сервері, де перевірка може випадково зачепити чужий робочий каталог.
php -l escape-demo.php
php escape-demo.php
Очікуйте, що PHP-код завершиться без синтаксичної помилки, а в надрукованому документі кутові дужки даних будуть представлені сутностями. У самому шаблоні теги p та input повинні залишитися звичайною розміткою. Це важлива різниця: перетворюється значення, а не весь готовий документ. Не плутайте текст у терміналі з тим, що користувач має побачити у браузері.
Для візуальної перевірки використайте ізольований локальний сайт вашого середовища розробки, не відкриваючи його назовні. Після відображення прикладу абзац має показувати буквальний текст із strong, а не робити слово жирним; поле повинно містити весь рядок разом із лапками. В інструментах розробника переконайтеся, що дані не створили дочірній елемент strong або додаткові атрибути input. На вузькому екрані перевірте також доступність повного значення поля.
Потім окремо підставте порожній рядок, українську назву, амперсанд і обидва види лапок. Запишіть очікування для кожного випадку. Якщо видно буквальне & замість амперсанда, дослідіть повторне екранування в ланцюжку виводу. Не вимикайте перетворення глобально задля одного красивішого прикладу. У шаблонізаторі з автоматичним екрануванням перевірте його правила, перш ніж додавати власну функцію поверх.
Не переносіть HTML-правило в інші контексти
Ця функція не перевіряє допустимість адреси посилання і не робить довільний HTML безпечним. Для тексту з дозволеним форматуванням потрібна окрема політика очищення HTML; для JavaScript, CSS і URL — відповідні правила та обмеження. Не вставляйте неперевірені дані в onClick, style або script. Розмежування контекстів пояснює пам’ятка OWASP щодо запобігання XSS.
Перед перенесенням рішення зробіть окрему зміну в системі контролю версій і перевірте її на тестовій копії. Корисно переглянути Git-коміт перед відправленням, щоб не змінити сусідні контексти випадково. Для відкату повертайте конкретну зміну шаблону, а не вимикайте захист усього застосунку. Висновок: правильний результат — передбачуваний текст у визначеному місці. Якщо шаблони змішують різні формати, AriZone допоможе розібрати місця виводу та підготувати цільові перевірки.
Залиште коментар