Безопасность PHP (валидация): Как написать надежное регулярное выражение для фильтрации спецсимволов (|’, , [, ], «, !, ?, $, # и др.) в строковых переменных?
Фильтрация спецсимволов в PHP — важная часть защиты приложений от XSS-атак, SQL-инъекций и других уязвимостей. Рассмотрим, как написать надёжное регулярное выражение для этой задачи.
## Базовый подход: удаление спецсимволов через preg_replace
Самый прямолинейный способ — явно перечислить запрещённые символы в символьном классе:
php
function sanitizeString(string $input): string {
// Удаляем спецсимволы: | ‘ [ ] » ! ? $ # / ^ * % @ & ( ) + = { } ; : ` ~
$pattern = ‘/[|»[]»!?$#\/^*%@&()+={};:`~]/u’;
return preg_replace($pattern, », $input);
}
## Альтернатива: разрешить только «белый список» символов
Лучшая практика — не запрещать плохое, а разрешать только хорошее. Например, только буквы, цифры, пробел и дефис:
php
function sanitizeToSafeChars(string $input): string {
// Оставляем только буквы (включая кириллицу), цифры, пробел и дефис
return preg_replace(‘/[^p{L}p{N}s-]/u’, », $input);
}
Флаг `u` обязателен для корректной работы с UTF-8 и кириллицей. `p{L}` — любая буква Unicode, `p{N}` — любая цифра.
## Экранирование вместо удаления
Во многих случаях правильнее не удалять, а экранировать символы:
php
// Для HTML-контекста
$safe = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, ‘UTF-8’);
// Для SQL (лучше использовать PDO с параметрами)
$pdo->prepare(‘SELECT * FROM users WHERE name = ?’)->execute([$input]);
## Комплексная функция валидации
php
function validateAndSanitize(string $input, int $maxLength = 255): string|false {
// Обрезаем по длине
$input = mb_substr($input, 0, $maxLength, ‘UTF-8’);
// Убираем управляющие символы и null-байты
$input = preg_replace(‘/[x00-x1Fx7F]/u’, », $input);
// Проверяем на наличие опасных паттернов
if (preg_match(‘/<script|javascript:|data:/i', $input)) {
return false;
}
// Экранируем HTML
return htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
## Важные рекомендации
1. **Контекст имеет значение**: для HTML используйте `htmlspecialchars`, для SQL — подготовленные запросы PDO, для shell-команд — `escapeshellarg`.
2. **Не полагайтесь только на regex**: регулярные выражения — лишь один из слоёв защиты.
3. **Всегда указывайте флаг `u`** при работе с многобайтовыми строками.
4. **Валидируйте на входе, экранируйте на выходе** — золотое правило безопасности.
5. **Используйте готовые библиотеки**: например, `HTML Purifier` для очистки HTML-контента.
Правильная стратегия защиты всегда многоуровневая: валидация типа данных + фильтрация + экранирование под конкретный контекст вывода.
