Методы защиты PHP-приложений от XSS SQL-инъекций и других распространённых уязвимостей

Откажитесь от конкатенации запросов. Используйте подготовленные выражения через PDO с параметризацией. Это исключает возможность внедрения управляющих конструкций в запрос к базе данных. Пример: $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");.

Фильтрация на входе и проверка на выходе – подход, который должен стать привычкой. Проверяйте данные по типу: число должно быть числом, email – email. Для проверки используйте filter_var() и строгие регулярные выражения.

Ограничьте права учетной записи, через которую приложение работает с БД. У этой роли не должно быть доступа к операциям DROP, ALTER, GRANT и другим административным командам. Это минимизирует ущерб при успешной попытке внедрения.

Устанавливайте заголовки Content-Security-Policy для ограничения источников скриптов. Это один из способов блокировать внедренный код даже при его наличии в HTML. Дополнительно применяйте X-Content-Type-Options: nosniff и X-Frame-Options: DENY.

Не забывайте обновлять сторонние библиотеки. Уязвимости часто появляются не в вашем коде, а в зависимостях. Используйте composer audit и мониторинг GitHub Security Advisories.

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

Запрещай вставку HTML в текстовые поля, если это не нужно. Даже комментарии, описания и формы обратной связи не должны принимать «чистый» HTML. Валидация на клиенте не спасёт – обрабатывай всё на сервере.

Не вставляй данные внутрь атрибутов, классов, inline-стилей и JavaScript без строгой фильтрации. Особенно опасны конструкции типа onclick, href="javascript:" и вставки через innerHTML.

Периодически проверяй отчёты Content Security Policy. Включи CSP заголовок хотя бы в режиме Content-Security-Policy-Report-Only – он поможет найти потенциальные точки внедрения.

Методы защиты от SQL-инъекций при работе с базами данных в PHP

Используйте подготовленные выражения (prepared statements). Вместо подстановки переменных напрямую в запрос, передавайте значения отдельно. Это исключает влияние пользовательского ввода на структуру запроса. В PDO – метод prepare() и execute(). В MySQLi – prepare() и bind_param().

Пример с использованием PDO:

$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $_POST['email']]);
$data = $stmt->fetch();

Никогда не вставляйте данные напрямую в SQL-строку. Даже если вы уверены в источнике данных. Проверка типа переменной – не защита. Подготовленные выражения работают как фильтр на уровне протокола.

Что еще стоит учесть:

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

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Ограничьте права пользователя базы данных. У аккаунта, с которого работает приложение, не должно быть доступа к командам DROP, DELETE без условий, и другим потенциально разрушительным действиям. Назначьте минимально необходимые привилегии.

Если используете ORM, убедитесь, что он поддерживает привязку параметров и не вставляет значения напрямую. Не доверяйте автоформированию запросов без явного контроля над входными данными.

И, наконец, не забывайте логировать подозрительные запросы, особенно те, где количество переданных параметров не совпадает с ожидаемым.