Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Предотвратяване на XSS в PHP: надеждна защита от Cross-Site Scripting

Как разработчиците предотвратяват Cross-Site Scripting в PHP приложения: кодиране според контекста, auto-escaping в шаблоните, почистване на HTML и Content Security Policy.

Актуалност 5 мин. четенеНаръчници

Накратко: XSS в PHP предотвратявате, като кодирате всеки изход според неговия контекст: htmlspecialchars() за HTML, json_encode() със защитни опции за JavaScript, проверени URL за връзки. Шаблоните с автоматичен escaping Ви освобождават от голяма част от това. Content Security Policy и бисквитки HttpOnly ограничават щетите, ако все пак остане уязвимост.

Защо Cross-Site Scripting трябва да се провери едновременно

Вниманието през октомври 2026 г. е насочено към PHP2Shell, две критични уязвимости в интерпретатора на PHP, за които от 21.10.2026 има пачове. Много фирми в тази връзка проверяват уеб приложенията си. Това е добър повод да се разгледат и слабостите в собствения код, които никоя актуализация на PHP не отстранява.

Cross-Site Scripting, накратко XSS, е една от тях. OWASP Top 10 водят XSS в рамките на категорията Injection. За разлика от уязвимост в сървъра, атаката тук е насочена срещу посетителите и потребителите на Вашия уебсайт, например срещу клиентите в магазина или служителите в административната част.

Последствията могат да бъдат значителни: превзети сесии на администратори, манипулирани формуляри, които изпращат данни на трети лица, или фалшиво съдържание на Вашия уебсайт. Ако бъде превзет администраторски акаунт, това може да доведе до пълен контрол над приложението.

Как възниква XSS в PHP приложения?

XSS възниква, когато приложение извежда в страница непроверени данни от недоверен източник. Браузърът тогава вече не може да различи Вашето съдържание от внедрения код и изпълнява и двете.

Различават се три форми. При отразения XSS съдържанието идва директно от текущата заявка, например от термин за търсене в URL. При съхранения XSS то е в базата данни, например в коментар или поле на профил, и засяга всеки, който отвори страницата. DOM-базираният XSS възниква в JavaScript на браузъра, когато скриптове записват стойности от URL в страницата.

Недоверени са всички данни, които не са зададени твърдо в кода: полета на формуляри, URL параметри, бисквитки, имена на файлове, отговори на външни интерфейси и съдържание от собствената база данни, което някога е дошло отвън.

Правилно кодиране на изхода според контекста

Най-важното правило гласи: кодирайте при извеждане, и то според мястото, където попада стойността. За HTML съдържание и атрибути в кавички htmlspecialchars() е средството по избор. Малка помощна функция пречи опциите да бъдат забравени:

<?php
function e(?string $wert): string
{
    return htmlspecialchars($wert ?? '', ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
}
?>
<h2><?= e($produkt['name']) ?></h2>
<input type="text" name="suche" value="<?= e($_GET['q'] ?? '') ?>">

Други контексти изискват други средства:

Контекст Сигурен метод
HTML съдържание, атрибут в кавички htmlspecialchars() с ENT_QUOTES и UTF-8
Данни за JavaScript json_encode() с JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_HEX_QUOT
Параметър в URL rawurlencode() за отделната стойност
Пълен URL от въведено от потребителя Проверка на схемата, разрешаване само на https и http, след това htmlspecialchars()
Атрибути без кавички, event handler-и, CSS да се избягват, стойности там не се вмъкват

За данни, от които скриптът се нуждае, атрибут за данни или JSON блок обикновено е най-чистият път:

<?php
$daten = json_encode($konfiguration, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
?>
<div id="app" data-konfig="<?= e($daten) ?>"></div>

В JavaScript след това четете стойността през атрибута за данни и задавате съдържание с textContent, а не с innerHTML.

Шаблони, почистване на HTML и фреймуърци

Шаблонните енджини като Twig и Blade кодират изходите автоматично по подразбиране. Това изключва голяма част от типичните грешки. Опасно става там, където това поведение е изключено нарочно, например с филтъра raw в Twig или синтаксиса {!! !!} в Blade. Такива места в кода трябва да са редки и да се проверяват целенасочено при всеки преглед.

Ако Вашето приложение нарочно трябва да допуска HTML от потребители, например форматиране в коментари или в редакционна система, кодирането не е достатъчно, защото HTML-ът трябва да се показва. Тогава Ви е нужна проверена библиотека за почистване като HTML Purifier, която пропуска само фиксиран списък от разрешени елементи и атрибути. Собствените филтри с регулярни изрази по опит са с пропуски.

Важно

Проверявайте особено областите на административната част. XSS в изгледи, които виждат само администратори, често се подценява, но засяга именно акаунтите с най-много права.

Откриване на XSS в съществуващ PHP код

В нараснали приложения първият въпрос обикновено не е как се кодира правилно, а къде досега е забравено. Прагматично начало е търсенето на места, където променливи се извеждат директно:

# Директно извеждане на данни от заявката
grep -rnE "(echo|print|<\?=)\s*\\\$_(GET|POST|REQUEST|COOKIE|SERVER)" src/ templates/ --include="*.php"
# Изключен auto-escaping в Twig и Blade
grep -rnE "\|raw|\{!!" templates/ resources/views/

Съвпаденията са задачи за проверка, а не готови констатации. Съхранен XSS такова търсене открива само отчасти, защото стойностите там идват от базата данни. Затова проверете допълнително всички изгледи, които показват съдържание от потребители: коментари, профили, бележки към поръчки, тикети в поддръжката. При CMS и магазини добавките и темите на трети доставчици изрично спадат към тях, защото там е голяма част от логиката за извеждане.

Втора линия на защита: CSP и сигурни бисквитки

Дори при внимателен код едно място може да бъде пропуснато. Две мерки тогава ограничават щетите. Content Security Policy позволява на браузъра само скриптове от определени източници и забранява вградените скриптове, освен ако не са изрично разрешени:

Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"

Въвеждайте такава политика постепенно, първо само в режим на отчитане чрез Content-Security-Policy-Report-Only, защото съществуващите вграждания на услуги за анализ или плащане обикновено трябва да се допълнят. Допълнителни хедъри описва наръчникът Хедъри за сигурност за уебсайтове.

Освен това бисквитките на сесиите трябва да носят атрибута HttpOnly, за да не могат скриптове да ги четат. Как да защитите сесиите изобщо, е описано в наръчника Защита на сесиите в PHP. Сродна уязвимост от страна на базата данни разглежда Предотвратяване на SQL инжекция в PHP.

Как конкретно помага PHP SOS?

  • Проверяваме шаблоните и изходите на Вашето приложение за липсващо или грешно кодиране.
  • Оценяваме находките според достъпността и засегнатите акаунти и показваме конкретни корекции.
  • Въвеждаме Content Security Policy постепенно, без да нарушаваме функциите на магазина или плащанията.
  • След корекцията тестваме отново и документираме резултата.

Независима проверка описва услугата Одит на сигурността и тест за проникване.

Често задавани въпроси

Достатъчно ли е htmlspecialchars срещу XSS?

За обикновен текст в HTML съдържанието и в атрибути в кавички да, ако посочите ENT_QUOTES и набора от знаци UTF-8. В JavaScript, в URL или в CSS важат други правила, там е нужно отделно, подходящо кодиране.

Да филтрирам ли въвеждането при записване или при извеждане?

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

Какво дава Content Security Policy?

Content Security Policy определя от кои източници браузърът може да зарежда и изпълнява скриптове. Тя може значително да ограничи последствията от пропусната XSS уязвимост, но не заменя правилното кодиране.

Как да разреша форматиране като удебелен текст или връзки в коментари?

Използвайте проверена библиотека за почистване на HTML с whitelist на разрешените елементи и атрибути. Собствените регулярни изрази за премахване на скриптове са податливи на грешки и не бива да се използват.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ