# 09. Безопасность

[← Оглавление](./index.md)

---

## ORM вместо raw SQL — никаких переменных в строке запроса

**ПЛОХО — SQL-ИНЪЕКЦИЯ ДАЖЕ С FORSQL**
```php
global $DB;
$email = $_GET['email'];
$sql = "SELECT * FROM b_user WHERE EMAIL = '" . $DB->ForSql($email) . "'";
$res = $DB->Query($sql);
```

**ХОРОШО — ORM С ПАРАМЕТРИЗОВАННЫМ ЗАПРОСОМ**
```php
use Bitrix\Main\UserTable;

$email = $_GET['email'] ?? '';
$user = UserTable::query()
    ->setSelect(['ID', 'NAME', 'LAST_NAME'])
    ->where('EMAIL', $email) // параметр передаётся безопасно
    ->setLimit(1)
    ->exec()
    ->fetch();
```

---

## Экранирование вывода в HTML

**ПЛОХО — XSS УЯЗВИМОСТЬ**
```php
echo "Привет, " . $arUser['NAME'];
```

**ХОРОШО — HTMLFILTER::ENCODE()**
```php
use Bitrix\Main\Text\HtmlFilter;

echo "Привет, " . HtmlFilter::encode($arUser['NAME']);
```

---

## Валидация входящих данных

`FILTER_SANITIZE_SPECIAL_CHARS` и `FILTER_SANITIZE_STRING` удалены в PHP 8.1–8.2. Используйте явную санитизацию.

**ПЛОХО — УДАЛЁННЫЕ КОНСТАНТЫ PHP**
```php
// FILTER_SANITIZE_SPECIAL_CHARS удалён в PHP 8.2!
$phone = filter_input(INPUT_POST, 'PHONE', FILTER_SANITIZE_SPECIAL_CHARS);
```

**ХОРОШО — ЯВНАЯ САНИТИЗАЦИЯ ДЛЯ PHP 8.2+**
```php
$phone = trim((string)($_POST['PHONE'] ?? ''));
$phone = strip_tags($phone);
if (!preg_match('/^\+?\d{10,15}$/', $phone)) {
    throw new \InvalidArgumentException('Некорректный номер телефона');
}

// Для email — нативный PHP-фильтр (не удалён):
$email = filter_input(INPUT_POST, 'EMAIL', FILTER_VALIDATE_EMAIL);
if ($email === false || $email === null) {
    throw new \InvalidArgumentException('Некорректный email');
}
```