Безопасность приложений
Безопасность фронтенда
Фронтенд — это клиентская часть веб-приложения, с которой взаимодействует пользователь через браузер. Безопасность фронтенда направлена на защиту пользователя от атак, которые могут быть выполнены через вредоносный код, манипуляции с DOM, подмену интерфейса или несанкционированный доступ к данным. Хотя большая часть логики и хранения данных находится на сервере, именно фронтенд является первой линией обороны против множества угроз.
Виды угроз фронтенду
| Угроза | Решение |
|---|---|
| XSS (Cross-site Scripting) | Санитизация входных данных, применение Content Security Policy (CSP), использование современных фреймворков (React, Angular), экранирование всех динамически выводимых значений |
| CSRF (Cross-site Request Forgery) | Использование CSRF-токенов, установка атрибута SameSite для cookies, корректная настройка CORS |
| Clickjacking | Заголовки X-Frame-Options (например, DENY или SAMEORIGIN) и директивы CSP (frame-ancestors) |
| Небезопасные скрипты | Исключение подключения внешних JavaScript-библиотек из непроверенных или недоверенных источников |
| Утечка токенов авторизации | Хранение токенов в защищённых cookie с атрибутами HttpOnly, Secure, SameSite=Strict или Lax; избегать использования localStorage |
| CORS политики | Ограничение доменов, которым разрешено делать запросы к API, через заголовки Access-Control-Allow-Origin и другие CORS-заголовки |
| Произвольные скрипты и загрузка ресурсов из посторонних источников | Настройка Content Security Policy (CSP) для блокировки выполнения неавторизованных скриптов и загрузки ресурсов с недоверенных доменов |
XSS (Cross-site Scripting)
XSS (межсайтовый скриптинг) — это уязвимость, при которой злоумышленник внедряет вредоносный JavaScript-код на веб-страницу, где он выполняется в контексте браузера жертвы. Такой код может украсть токены авторизации, перехватить действия пользователя, изменить поведение интерфейса или отправить данные на сторонний сервер.
Защитные меры:
- Экранирование всех динамически выводимых значений: специальные символы (
<,>,&,",') заменяются на HTML-сущности, например<становится<. Это предотвращает интерпретацию пользовательского ввода как исполняемого кода. - Санитизация входных данных: очистка содержимого от потенциально опасных элементов, таких как теги
<script>, атрибутыonerror,onclick, ссылки с протоколомjavascript:. - Использование современных фреймворков: React, Angular и Vue по умолчанию экранируют текстовое содержимое, что снижает риск XSS. Однако при использовании низкоуровневых API (например,
dangerouslySetInnerHTMLв React илиinnerHTMLв чистом JavaScript) разработчик берёт на себя ответственность за безопасность. - Content Security Policy (CSP): механизм, ограничивающий источники, из которых можно загружать и выполнять скрипты, стили, изображения и другие ресурсы. CSP позволяет блокировать выполнение встроенных скриптов и внешних ресурсов, не указанных в белом списке.
CSRF (Cross-site Request Forgery)
CSRF (межсайтовая подделка запроса) — это атака, при которой злоумышленник заставляет браузер пользователя выполнить нежелательный запрос к доверенному сайту, используя уже установленную сессию. Например, если пользователь авторизован в интернет-банке, вредоносный сайт может инициировать перевод средств без его ведома.
Защитные меры:
- CSRF-токены: сервер генерирует уникальный случайный токен для каждой сессии или формы. При отправке запроса (особенно POST, PUT, DELETE) клиент должен передать этот токен. Сервер проверяет его наличие и корректность.
- Атрибут
SameSiteдля cookies: установкаSameSite=StrictилиSameSite=Laxпредотвращает автоматическую отправку cookie в междоменных запросах.SameSite=Strict: cookie отправляются только при переходе внутри того же сайта.SameSite=Lax: cookie отправляются при безопасных междоменных GET-запросах (например, по клику на ссылку), но не при POST-запросах.
- Корректная настройка CORS: хотя CORS сам по себе не защищает от CSRF (он регулирует чтение ответов, а не отправку запросов), правильная конфигурация помогает ограничить источники, которым разрешено взаимодействовать с API.
Clickjacking
Clickjacking (перехват кликов) — это атака, при которой вредоносный сайт встраивает целевой сайт в невидимый <iframe> и маскирует его под другую кнопку или элемент. Пользователь, кликая на видимый элемент, на самом деле взаимодействует с интерфейсом целевого сайта.
Защитные меры:
- Заголовок
X-Frame-Options: HTTP-заголовок, указывающий браузеру, можно ли отображать страницу внутри фрейма. Возможные значения:DENY: запрещает любое встраивание.SAMEORIGIN: разрешает встраивание только с того же домена.
- Директива CSP
frame-ancestors: более гибкая и современная заменаX-Frame-Options. Позволяет явно указать, какие источники могут встраивать страницу, например:Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com;
Небезопасные скрипты и внешние зависимости
Подключение JavaScript-библиотек из непроверенных или недоверенных источников создаёт риск выполнения вредоносного кода. Даже популярные CDN могут быть скомпрометированы, а сторонние пакеты — содержать уязвимости.
Защитные меры:
- Использование только проверенных источников: предпочтительно использовать официальные CDN (например, cdnjs, jsDelivr) или локально размещённые копии библиотек.
- Верификация зависимостей: применение инструментов вроде Snyk, Dependabot или npm audit для выявления известных уязвимостей в зависимостях.
- Subresource Integrity (SRI): механизм, позволяющий браузеру проверить целостность загружаемого ресурса. Для этого в теге
<script>указывается хеш содержимого:Если содержимое изменится, браузер откажется его выполнять.<script src="https://cdn.example.com/library.js"
integrity="sha384-abc123..."></script>
Утечка токенов авторизации
Токены авторизации (например, JWT) часто используются для поддержания сессии пользователя. Их утечка даёт злоумышленнику полный доступ к аккаунту.
Токен можно украсть через XSS или историю браузера.
Защитные меры:
- Хранение токенов в защищённых cookie: использование cookie с атрибутами:
HttpOnly: запрещает доступ к cookie из JavaScript, что блокирует кражу через XSS.Secure: гарантирует передачу cookie только по HTTPS.SameSite=StrictилиLax: ограничивает отправку cookie в междоменных запросах. Strict - самый трогий режим SameSite, cookie отправляются только при переходе внутри сайта. Lax - более мягкий режим SameSite, разрешает GET-запросы с других сайтов (например, ссылки).
- Избегание
localStorageдля токенов:localStorageдоступен из любого JavaScript-кода на странице, включая вредоносный. Он подходит только для нечувствительных данных. - Краткосрочные токены и механизмы обновления: использование короткоживущих access-токенов и долгоживущих refresh-токенов, хранящихся в
HttpOnlycookie.
CORS и управление междоменными запросами
CORS (Cross-Origin Resource Sharing) — это механизм безопасности браузера, регулирующий, какие веб-сайты могут делать запросы к API на другом домене.
Ключевые понятия:
- Origin (источник): комбинация схемы, домена и порта, с которой инициирован запрос. Например, запрос с
https://app.example.comимеет originhttps://app.example.com. - Credentials (учётные данные): куки, заголовки авторизации и TLS-сертификаты, которые могут быть включены в запрос.
Основные CORS-заголовки:
Access-Control-Allow-Origin: указывает, какие источники могут получать ответ. Значение*разрешает все источники, но не совместимо с передачей учётных данных.Access-Control-Allow-Credentials: true: разрешает браузеру включать учётные данные в запрос. Требует указания конкретного домена вAccess-Control-Allow-Origin.- В JavaScript (например, в
fetch) для отправки учётных данных используется опцияcredentials: 'include'.
Пример безопасного запроса с учётными данными:
fetch('https://api.bank.com/transfer', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: 'attacker', amount: 1000 })
});
Такой запрос будет выполнен только если сервер ответит заголовками:
Access-Control-Allow-Origin: https://trusted.app.com
Access-Control-Allow-Credentials: true
Content Security Policy (CSP)
Content Security Policy — это мощный механизм защиты от XSS, clickjacking и других атак, основанный на белых списках источников ресурсов.
Пример политики:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://cdn.trusted.com;
style-src 'self' 'unsafe-inline';
img-src 'self' https://images.example.com;
frame-ancestors 'none';
object-src 'none';
Эффекты:
- Скрипты выполняются только с текущего домена и
https://cdn.trusted.com. - Встроенные стили (
<style>, атрибутstyle="") разрешены ('unsafe-inline'), но это снижает безопасность. - Изображения могут загружаться с текущего домена, из Data URL и с доверенного хоста.
- Встраивание страницы в iframe запрещено (
frame-ancestors 'none'). - Плагины (например, Flash через
<object>) полностью отключены.
CSP требует тщательной настройки, но значительно повышает уровень защиты даже при наличии уязвимостей в коде.
Безопасность бэкенда
Бэкенд — это серверная часть приложения, отвечающая за реализацию бизнес-логики, хранение и обработку данных, взаимодействие с базами данных, внешними сервисами и клиентскими приложениями. Именно на бэкенде сосредоточены наиболее критичные компоненты системы: учётные данные пользователей, конфиденциальная информация, механизмы авторизации и транзакционные процессы. Поэтому безопасность бэкенда определяет общую устойчивость всего программного продукта к внешним и внутренним угрозам.
Безопасность бэкенда строится как многоуровневая система защиты, охватывающая сетевой уровень, уровень приложения, уровень данных и уровень процессов. Каждый слой должен быть независимо защищён, чтобы компрометация одного элемента не приводила к полному захвату системы.
Основные категории угроз бэкенду
Угрозы безопасности бэкенда можно разделить на несколько ключевых категорий:
- Уязвимости уровня данных — атаки, направленные на получение, модификацию или уничтожение информации.
- Уязвимости уровня приложения — ошибки в логике работы, позволяющие обойти проверки доступа или выполнить произвольный код.
- Проблемы управления сессиями и аутентификацией — недостаточная защита учётных записей и сессионных токенов.
- Неконтролируемый пользовательский ввод — отсутствие валидации и санитизации входных данных.
- Устаревшие или уязвимые зависимости — использование сторонних библиотек с известными уязвимостями.
- Недостаточный мониторинг и логирование — невозможность обнаружить или проанализировать инцидент.
Каждая из этих категорий требует системного подхода к защите.
Уязвимости уровня данных
SQL Injection
SQL Injection — это классическая уязвимость, возникающая при некорректной обработке пользовательского ввода в SQL-запросах. Злоумышленник может внедрить произвольный SQL-код через параметры запроса, что позволяет ему читать, изменять или удалять данные, а в некоторых случаях — выполнять команды операционной системы.
Основная причина SQL Injection — смешивание кода и данных. Когда строка запроса формируется путём конкатенации, пользовательские данные интерпретируются как часть SQL-команды.
Параметризованные запросы — это механизм, при котором пользовательские данные передаются отдельно от текста SQL-запроса. СУБД обрабатывает такие данные исключительно как значения, а не как исполняемый код.
# ❌ Небезопасно: конкатенация строк
query = f"SELECT * FROM users WHERE email = '{email}'"
# ✅ Безопасно: параметризованный запрос
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))
// ❌ Небезопасно
string query = $"SELECT * FROM Users WHERE Id = {userId}";
// ✅ Безопасно
using var cmd = new SqlCommand("SELECT * FROM Users WHERE Id = @UserId", connection);
cmd.Parameters.AddWithValue("@UserId", userId);
// ❌ Небезопасно
String query = "SELECT * FROM users WHERE id = " + userId;
// ✅ Безопасно
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setInt(1, userId);
Современные ORM-системы, такие как Entity Framework (C#), Hibernate (Java) или Django ORM (Python), по умолчанию используют параметризованные запросы при корректном использовании. Это значительно снижает риск человеческой ошибки, но не отменяет необходимости понимать принципы защиты.
Insecure Direct Object References (IDOR)
Insecure Direct Object References (IDOR) — это уязвимость, возникающая, когда приложение предоставляет прямой доступ к внутренним объектам (например, файлам, записям в БД) по их идентификатору без проверки прав доступа текущего пользователя.
Пример:
GET /api/documents/456
Если сервер просто извлекает документ с ID 456 и возвращает его, не проверяя, принадлежит ли он текущему пользователю, злоумышленник может перебирать идентификаторы и получить доступ к чужим данным.
Меры защиты от IDOR:
- Всегда проверять принадлежность объекта текущему пользователю.
- Использовать непредсказуемые идентификаторы, например UUID вместо последовательных чисел.
- Логировать попытки доступа к ресурсам, к которым пользователь не имеет прав.
@app.route('/api/documents/<doc_id>')
@require_auth
def get_document(user_id, doc_id):
document = db.query(Document).filter_by(id=doc_id).first()
if not document or document.owner_id != user_id:
log_suspicious_access(user_id, doc_id)
return jsonify({'error': 'Access denied'}), 403
return jsonify(document.to_dict())
Обработка ошибок и раскрытие информации
Раскрытие деталей реализации
Раскрытие деталей реализации — это ситуация, когда сервер возвращает клиенту информацию о внутренней структуре приложения: стек вызовов, пути к файлам, версии библиотек, конфигурационные параметры. Такая информация даёт злоумышленнику карту системы и упрощает поиск уязвимостей.
Трассировка стека (stack trace) особенно опасна, так как она показывает точное место ошибки, используемые классы и методы.
Меры защиты:
- В production-среде использовать обобщённые сообщения об ошибках.
- Полностью логировать ошибки на сервере для внутреннего анализа.
- Удалять заголовки, раскрывающие технологии (
Server,X-Powered-By). - Использовать reverse proxy (например, Nginx или Traefik) для маскировки бэкенда.
// ❌ Раскрытие информации
{
"error": "NullPointerException at com.app.service.UserService.getUser(UserService.java:42)"
}
// ✅ Безопасный ответ
{
"error": "Internal server error",
"code": "INTERNAL_ERROR"
}
Защита файловых операций
Веб-корень и безопасное хранение файлов
Веб-корень (webroot) — это директория файловой системы, из которой веб-сервер отдаёт статические файлы клиентам. Файлы вне этой директории не должны быть доступны напрямую через HTTP.
Чувствительные файлы, такие как .env, конфигурации, логи или исходный код, никогда не должны находиться внутри webroot. Их размещение в этой зоне создаёт риск их случайной публикации.
Рекомендации по защите файловых операций:
- Хранить чувствительные файлы вне webroot.
- Отключать листинг директорий в веб-сервере.
- Проверять расширения и MIME-типы загружаемых файлов.
- Ограничивать максимальный размер загрузки.
- Сохранять загруженные файлы в изолированной файловой системе.
- Генерировать случайные имена файлов для предотвращения перезаписи.
- Сканировать файлы антивирусом перед обработкой.
import os
import magic
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
UPLOAD_FOLDER = '/var/app/uploads' # Вне webroot
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/upload', methods=['POST'])
def upload_file():
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
# Проверка размера
file.seek(0, os.SEEK_END)
size = file.tell()
file.seek(0)
if size > MAX_FILE_SIZE:
return jsonify({'error': 'File too large'}), 400
# Проверка расширения
if not allowed_file(file.filename):
return jsonify({'error': 'Invalid file type'}), 400
# Проверка MIME-типа
mime = magic.from_buffer(file.read(2048), mime=True)
file.seek(0)
if mime not in ['image/png', 'image/jpeg', 'image/gif']:
return jsonify({'error': 'Invalid MIME type'}), 400
# Безопасное имя файла
filename = secure_filename(file.filename)
unique_filename = f"{uuid.uuid4().hex}_{filename}"
file.save(os.path.join(UPLOAD_FOLDER, unique_filename))
return jsonify({'success': True, 'filename': unique_filename}), 200
Управление сессиями и токенами
Механизмы сессий и безопасные cookie
Сессия — это механизм поддержания состояния между запросами пользователя к веб-приложению. Поскольку HTTP — протокол без состояния, сессии позволяют идентифицировать пользователя на протяжении нескольких взаимодействий.
Сессии обычно реализуются через cookie — небольшие фрагменты данных, хранящиеся в браузере и отправляемые на сервер при каждом запросе.
Cookie-флаги безопасности повышают устойчивость сессий к атакам:
- HttpOnly — запрещает доступ к cookie через JavaScript, защищая от XSS.
- Secure — разрешает передачу cookie только по HTTPS.
- SameSite — ограничивает отправку cookie в межсайтовых запросах:
Strict— cookie отправляются только в запросах первого уровня.Lax— cookie отправляются в безопасных межсайтовых GET-запросах.
- Max-Age / Expires — задаёт срок жизни сессии.
- Path / Domain — ограничивает область действия cookie.
Пример безопасной настройки сессии в Express.js:
const session = require('express-session');
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 30 * 60 * 1000 // 30 минут
}
}));
Пример настройки аутентификационных cookie в ASP.NET Core:
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Lax;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.SlidingExpiration = true;
});
Мониторинг и реагирование на инциденты
Подозрительная активность
Подозрительная активность — это поведение, отклоняющееся от установленной нормы использования системы. Такое поведение может указывать на попытку несанкционированного доступа, автоматизированную атаку или внутреннюю угрозу. Примеры подозрительной активности:
- Высокая частота запросов с одного IP-адреса;
- Последовательные обращения к несуществующим ресурсам (например,
/api/user/999999); - Необычная географическая локализация запросов (например, вход из страны, где пользователь никогда не был);
- Использование устаревших или нетипичных User-Agent строк;
- Попытки выполнить операции, недоступные по текущей роли пользователя.
Для обнаружения таких событий требуется централизованное логирование всех значимых действий: авторизации, изменения данных, доступа к защищённым эндпоинтам.
Логирование безопасности
Логирование безопасности — это систематическая запись событий, связанных с защитой приложения. Логи должны содержать:
- Временную метку события;
- Идентификатор пользователя или сессии;
- IP-адрес источника запроса;
- Тип события (успешный вход, ошибка аутентификации, изменение пароля и т.д.);
- Результат операции (успех/ошибка);
- Контекст (URL, метод HTTP, параметры запроса).
Критически важно хранить логи в защищённом хранилище с ограниченным доступом и обеспечивать их целостность — например, через хеширование или использование immutable-логов.
SIEM-системы
SIEM (Security Information and Event Management) — это платформа для сбора, агрегации, анализа и корреляции данных безопасности из множества источников. Современные SIEM-системы позволяют:
- Автоматически выявлять аномалии на основе машинного обучения;
- Строить временные цепочки событий (например, «неудачная попытка входа → успешная → изменение email»);
- Генерировать оповещения и триггеры для автоматического реагирования;
- Интегрироваться с другими системами (WAF, IAM, облачные сервисы).
Популярные решения:
- Elastic Security (часть ELK-стека);
- Splunk Enterprise Security;
- IBM QRadar;
- Microsoft Sentinel;
- Grafana Loki + Promtail + Alertmanager (для лёгковесных сред).
Пример правила для обнаружения брутфорса:
# Alertmanager rule
- alert: BruteForceDetected
expr: sum by (ip) (rate(auth_failed_total{service="auth"}[5m])) > 10
for: 1m
labels:
severity: high
annotations:
summary: "Brute-force attack detected from {{ $labels.ip }}"
description: "More than 10 failed auth attempts in 5 minutes"
План реагирования на инциденты
План реагирования на инциденты — это заранее подготовленный документ, описывающий действия команды в случае компрометации системы. Он включает:
- Обнаружение и классификация — определение типа инцидента (утечка данных, DDoS, взлом аккаунта).
- Сдерживание — изоляция затронутых компонентов (блокировка IP, отзыв токенов, отключение сервиса).
- Устранение — устранение первопричины (закрытие уязвимости, удаление вредоносного кода).
- Восстановление — возврат системы в рабочее состояние (развертывание из резервной копии, повторная аутентификация пользователей).
- Постинцидентный анализ — документирование причин, последствий и мер по предотвращению повторения.
Такой план должен регулярно тестироваться через tabletop-упражнения и автоматизированные сценарии.
Регуляторные требования и работа с персональными данными
Минимизация данных
Минимизация данных — принцип, согласно которому собираются и обрабатываются только те персональные данные, которые необходимы для достижения конкретной цели. Например, если приложение не требует знания даты рождения пользователя, её не следует запрашивать.
Этот подход снижает поверхность атаки и упрощает соблюдение законодательства.
GDPR
GDPR (General Data Protection Regulation) — европейский регламент, вступивший в силу в 2018 году. Он применяется ко всем организациям, обрабатывающим данные граждан ЕС, независимо от их местоположения.
Ключевые требования:
- Явное согласие на обработку данных;
- Право на доступ, исправление и удаление своих данных;
- Обязательное уведомление регулятора в течение 72 часов после обнаружения утечки;
- Назначение ответственного за защиту данных (DPO) при массовой обработке;
- Передача данных за пределы ЕС разрешена только при наличии адекватной защиты.
CCPA
CCPA (California Consumer Privacy Act) — закон штата Калифорния, предоставляющий жителям права на прозрачность и контроль над своими данными. Основные положения:
- Право знать, какие данные собираются;
- Право на удаление информации;
- Право отказаться от продажи данных третьим лицам;
- Запрет на дискриминацию за использование прав.
ФЗ-152 «О персональных данных»
Федеральный закон №152-ФЗ регулирует обработку персональных данных в Российской Федерации. Основные особенности:
- Обязательное получение согласия субъекта (за исключением случаев, предусмотренных законом);
- Хранение данных граждан РФ на серверах, расположенных на территории России;
- Отсутствие обязательного требования уведомлять Роскомнадзор об утечке (в отличие от GDPR);
- Право субъекта на отзыв согласия и требование удаления данных.
Меры защиты персональных данных
Для соответствия требованиям законодательства необходимо внедрить технические и организационные меры:
- Шифрование данных при передаче (TLS 1.2+) и хранении (AES-256);
- Псевдонимизация — замена идентификаторов на искусственные ключи, не позволяющие напрямую связать данные с человеком;
- Анонимизация — необратимое преобразование данных, исключающее возможность идентификации;
- Разграничение доступа — только авторизованные сотрудники могут работать с персональными данными;
- Аудит операций — фиксация всех действий с данными для последующего анализа.
Языковые особенности безопасности
JavaScript / Node.js
Node.js-приложения особенно уязвимы к атакам через зависимости и динамическое выполнение кода. Рекомендуемые практики:
- Использование библиотеки
helmetдля установки безопасных HTTP-заголовков (X-Content-Type-Options,X-Frame-Options,Content-Security-Policy); - Применение
sanitize-htmlили DOMPurify для очистки HTML-контента; - Полный отказ от
eval(),new Function(),setTimeout(string)и других функций, выполняющих строку как код; - Валидация зависимостей через
npm audit,snyk testилиsocket.dev; - Настройка строгих CORS-политик.
Пример конфигурации:
const helmet = require('helmet');
const express = require('express');
const app = express();
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.trusted.com"],
styleSrc: ["'self'", "'unsafe-inline'"]
}
},
hsts: { maxAge: 31536000, includeSubDomains: true }
}));
Python (Django, Flask)
- Django предоставляет встроенную защиту от CSRF, автоматическое экранирование в шаблонах и безопасную работу с ORM.
- Flask требует ручной настройки защиты. Рекомендуется использовать:
- Flask-Talisman для CSP и HSTS;
- Flask-WTF для CSRF-токенов;
- Bandit для статического анализа кода;
- Safety или pip-audit для проверки зависимостей.
from flask import Flask
from flask_talisman import Talisman
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
Talisman(app, force_https=True)
CSRFProtect(app)
Java (Spring Boot)
- Spring Security — стандарт де-факто для аутентификации и авторизации.
- Использование OWASP Java Encoder для экранирования вывода.
- Генерация токенов через
SecureRandom, а неMath.random(). - Анализ зависимостей через OWASP Dependency-Check или Snyk.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // или настроить правильно
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'"))
.httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).maxAgeInSeconds(31536000))
)
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
C# (.NET Core)
- ASP.NET Core Identity — встроенная система управления пользователями.
- Data Protection API — для шифрования cookies, токенов и других чувствительных данных.
- Entity Framework использует параметризованные запросы по умолчанию.
- Защита от CSRF через
[ValidateAntiForgeryToken].
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo("/keys"))
.SetApplicationName("MyApp");
app.UseHsts();
app.Use(async (ctx, next) => {
ctx.Response.Headers.Add("X-Frame-Options", "DENY");
await next();
});
Что важно добавить в проект для безопасности
Безопасность программного проекта не возникает автоматически — она закладывается на всех этапах жизненного цикла: от проектирования до эксплуатации. Даже при использовании современных фреймворков и инструментов разработчик обязан явно предусмотреть защитные механизмы. Ниже описаны ключевые компоненты, которые следует внедрять в любой проект, работающий с данными, пользователями или внешними системами.
Сетевая и транспортная безопасность
HTTPS и TLS
HTTPS — это протокол передачи гипертекста поверх зашифрованного соединения TLS (Transport Layer Security). Он обеспечивает конфиденциальность, целостность и аутентичность данных между клиентом и сервером.
Использование HTTPS обязательно для:
- защиты учётных данных и сессий;
- предотвращения модификации трафика (MITM-атак);
- корректной работы современных браузерных API (геолокация, Service Workers и др.);
- соответствия требованиям регуляторов и платформ (Google, Apple, GDPR).
Минимально допустимая версия — TLS 1.2, рекомендуется использовать TLS 1.3. Устаревшие протоколы (SSLv3, TLS 1.0, TLS 1.1) должны быть отключены.
Настройка HTTPS:
- Получение сертификата через Let’s Encrypt (бесплатно) или коммерческий CA;
- Настройка HSTS (HTTP Strict Transport Security) для принудительного перехода на HTTPS;
- Отключение небезопасных шифров (например, RC4, DES, NULL ciphers).
Пример заголовка HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Этот заголовок указывает браузеру использовать только HTTPS для домена и всех его поддоменов в течение одного года.
Web Application Firewall (WAF)
Web Application Firewall (WAF) — это специализированный фильтр HTTP-трафика, предназначенный для блокировки известных атак на уровне приложения: SQL Injection, XSS, CSRF, path traversal и другие.
WAF может быть:
- Облачным: Cloudflare, AWS WAF, Azure Front Door;
- Локальным: ModSecurity (в связке с Nginx/Apache);
- Встроенным: часть API Gateway или reverse proxy.
WAF работает по сигнатурам и поведенческим правилам. Например, правило OWASP Core Rule Set (CRS) автоматически блокирует запросы, содержащие <script> в параметрах или одинарные кавычки в числовых полях.
Преимущество WAF — он действует до попадания запроса в код приложения, снижая нагрузку на бэкенд и уменьшая поверхность атаки.
Управление доступом и авторизация
Принцип наименьших привилегий
Принцип наименьших привилегий — это стратегия, согласно которой каждый пользователь, сервис или процесс получает только те права, которые необходимы для выполнения его задачи.
Практические меры:
- Сервисный аккаунт базы данных не имеет прав на удаление таблиц;
- Администратор не может читать пароли пользователей;
- Мобильное приложение не запрашивает доступ к контактам, если это не требуется функционалом.
Этот принцип ограничивает последствия компрометации: даже при утечке токена злоумышленник не получит полный контроль над системой.
RBAC и ABAC
RBAC (Role-Based Access Control) — модель управления доступом, основанная на ролях. Пользователь назначается одной или несколькими ролями («пользователь», «модератор», «админ»), а роли имеют набор разрешений.
ABAC (Attribute-Based Access Control) — более гибкая модель, где решение о доступе принимается на основе атрибутов:
- пользователя (роль, отдел, страна);
- ресурса (владелец, уровень конфиденциальности);
- контекста (время суток, IP-адрес, устройство).
Пример ABAC-правила:
Разрешить доступ к документу, если пользователь является владельцем ИЛИ имеет роль «юрист» И запрос идёт с корпоративного IP.
ABAC сложнее в реализации, но обеспечивает точечный контроль в крупных системах.
Выход из системы и отзыв токенов
Механизм выхода из системы должен не только очищать cookie на клиенте, но и инвалидировать сессию или токен на сервере. В противном случае украденный JWT остаётся действительным до истечения срока.
Решения:
- Хранение чёрного списка отозванных токенов в Redis с TTL, равным времени жизни токена;
- Использование короткоживущих access-токенов и долгоживущих refresh-токенов;
- При выходе — удаление refresh-токена из базы.
Работа с файлами и загрузками
Изоляция среды хранения
Загружаемые пользователем файлы никогда не должны сохраняться в директории, доступной напрямую через веб-сервер. Это предотвращает выполнение вредоносных скриптов (например, .php или .jsp).
Рекомендуемые практики:
- Сохранение файлов вне webroot (например,
/var/uploads); - Обслуживание файлов через контроллер, который проверяет права доступа;
- Использование объектного хранилища (AWS S3, MinIO) с подписанными URL для временного доступа.
Санитизация и проверка содержимого
Проверка расширения файла недостаточна — злоумышленник может переименовать malware.php в photo.jpg. Необходима проверка MIME-типа на основе фактического содержимого.
Дополнительно:
- Ограничение размера файла (например, не более 10 МБ);
- Генерация случайного имени файла (
a1b2c3d4.jpg); - Сканирование антивирусом (ClamAV, VirusTotal API);
- Конвертация изображений в безопасный формат (например, PNG → JPEG без метаданных).
Валидация и санитизация данных
Строгая валидация входных данных
Строгая валидация — это проверка каждого входящего параметра на соответствие ожидаемому типу, формату, диапазону и длине.
Примеры:
- Email должен соответствовать регулярному выражению RFC 5322;
- Возраст — целое число от 0 до 150;
- Телефон — строка в формате E.164 (
+79001234567); - Имя — только буквы, пробелы и дефисы, длина от 2 до 50 символов.
Инструменты:
- Joi (Node.js), Pydantic (Python), FluentValidation (.NET), Bean Validation (Java).
Экранирование вывода
Экранирование — преобразование специальных символов (<, >, ", ', &) в HTML-сущности (<, > и т.д.), чтобы они не интерпретировались как код.
Это основная защита от XSS (Cross-Site Scripting).
Пример в Python:
from html import escape
safe_output = escape(user_input)
В современных фреймворках (React, Angular, Vue, Django) экранирование применяется автоматически при выводе переменных в шаблонах. Однако при использовании innerHTML, dangerouslySetInnerHTML или аналогов — разработчик берёт ответственность на себя.
Управление зависимостями и обновлениями
Анализ состава ПО (SCA)
Software Composition Analysis (SCA) — это процесс сканирования зависимостей проекта на наличие известных уязвимостей (CVE).
Инструменты:
- Snyk — интеграция с GitHub, CLI, CI/CD;
- Dependabot — автоматические PR с обновлениями;
- OWASP Dependency-Check — open-source сканер для Java, .NET, Python и др.
Рекомендуется:
- Запускать SCA при каждом коммите;
- Блокировать сборку при обнаружении критических уязвимостей;
- Использовать lock-файлы (
package-lock.json,Pipfile.lock) для воспроизводимости.
Защита от поддельных пакетов
Угрозы:
- Typosquatting — пакет с опечаткой в имени (
reqeustsвместоrequests); - Dependency confusion — публикация пакета с именем внутренней библиотеки в публичном реестре.
Защита:
- Использование приватных реестров (Nexus, Artifactory);
- Верификация цифровых подписей пакетов;
- Аудит новых зависимостей перед добавлением.
Логирование, мониторинг и реагирование
Централизованное логирование
Все значимые события должны записываться в централизованную систему логирования:
- Авторизации (успешные и неудачные);
- Изменения данных;
- Доступ к защищённым ресурсам;
- Ошибки безопасности.
Логи должны содержать:
- Временную метку;
- Идентификатор пользователя или сессии;
- IP-адрес;
- User-Agent;
- Контекст операции.
Чувствительные данные (пароли, токены, персональная информация) не должны попадать в логи.
Системы мониторинга
Интеграция с системами вроде Prometheus + Grafana, ELK Stack или Datadog позволяет:
- Визуализировать метрики (запросы в секунду, ошибки 5xx, время ответа);
- Настраивать алерты на аномалии;
- Выполнять корреляционный анализ (например, рост 403-ошибок + рост трафика = возможная атака).
План реагирования на инциденты
Каждый проект должен иметь документированный план реагирования, включающий:
- Контакты ответственных лиц;
- Процедуры изоляции (блокировка IP, отзыв токенов);
- Шаблоны уведомлений пользователям и регуляторам;
- Постинцидентный разбор (post-mortem).
Обновление зависимостей и управление составом ПО
Анализ состава программного обеспечения (SCA)
Анализ состава программного обеспечения (Software Composition Analysis, SCA) — это процесс сканирования всех сторонних библиотек и компонентов, используемых в проекте, на наличие известных уязвимостей, лицензионных рисков и устаревших версий.
Современные приложения зависят от сотен и даже тысяч open-source пакетов. Уязвимость в одном из них может скомпрометировать всё приложение, даже если собственный код написан идеально.
Основные задачи SCA:
- Выявление всех транзитивных зависимостей;
- Сопоставление их с базами CVE (Common Vulnerabilities and Exposures);
- Оценка критичности уязвимостей по шкале CVSS;
- Предложение безопасных альтернатив или патчей.
Инструменты SCA
Популярные инструменты для анализа зависимостей:
- Snyk — поддерживает все основные языки, интегрируется с GitHub, GitLab, CI/CD, предлагает автоматические PR с исправлениями.
- Dependabot — встроенный в GitHub инструмент, который отслеживает обновления и создаёт pull request при обнаружении уязвимостей.
- OWASP Dependency-Check — open-source решение для Java, .NET, Python, Ruby и других экосистем.
- Trivy — лёгкий сканер, поддерживающий не только зависимости, но и контейнеры, конфигурации IaC.
Пример запуска Trivy для анализа Python-проекта:
trivy fs --security-checks vuln .
Рекомендуется:
- Запускать SCA на каждом коммите в CI;
- Блокировать мёрж, если обнаружены критические уязвимости;
- Использовать lock-файлы (
package-lock.json,Pipfile.lock,Gemfile.lock) для воспроизводимости сборок.
Защита от поддельных пакетов
Угрозы целостности зависимостей включают:
- Typosquatting — публикация пакета с опечаткой в имени популярной библиотеки (например,
reqeustsвместоrequests); - Dependency confusion — публикация пакета с именем внутренней приватной библиотеки в публичном реестре, но с более высокой версией.
Меры защиты:
- Использование приватных реестров (Nexus, Artifactory, GitHub Packages) для внутренних пакетов;
- Верификация цифровых подписей пакетов (где поддерживается);
- Аудит новых зависимостей перед добавлением в проект;
- Отключение автоматической установки пакетов из ненадёжных источников.
Управление доступом и авторизация
Многофакторная аутентификация (MFA)
Многофакторная аутентификация (MFA) — это метод подтверждения личности пользователя с использованием двух или более независимых факторов:
- Знание (пароль, PIN);
- Владение (токен, смартфон, аппаратный ключ);
- Биометрия (отпечаток пальца, распознавание лица).
MFA значительно снижает риск компрометации учётных записей даже при утечке пароля.
Реализации:
- TOTP (Time-based One-Time Password) через Google Authenticator, Authy;
- WebAuthn/FIDO2 для аппаратных ключей (YubiKey, Touch ID);
- SMS-коды (менее безопасны из-за SIM-swap атак).
Выход из системы и отзыв токенов
Механизм выхода из системы должен не только очистить cookie или localStorage на клиенте, но и инвалидировать сессию на сервере.
Для JWT-токенов, которые по своей природе stateless, рекомендуется:
- Использовать короткий срок жизни access-токена (5–15 минут);
- Хранить refresh-токены в защищённой базе данных;
- При выходе — удалять refresh-токен из базы;
- Поддерживать чёрный список отозванных токенов в Redis с TTL, равным времени жизни токена.
Пример отзыва токена в Redis:
# При выходе
redis.delete(f"refresh_token:{user_id}")
# При проверке access-токена
if redis.exists(f"revoked_token:{jti}"):
return jsonify({'error': 'Token revoked'}), 401
Работа с файлами и загрузками
Изоляция исполняемого контекста
Загруженные пользователем файлы никогда не должны исполняться в контексте веб-приложения. Это означает:
- Запрет выполнения
.php,.jsp,.asp,.exeи других исполняемых расширений; - Отключение интерпретаторов в директории загрузок;
- Обслуживание файлов через контроллер, а не напрямую через веб-сервер.
Пример Nginx-конфигурации:
location /uploads/ {
# Запрет выполнения PHP
location ~ \.php$ {
deny all;
}
# Разрешить только статические файлы
try_files $uri =404;
}
Антивирусная проверка
Перед сохранением файла его следует проверить на наличие вредоносного кода. Для этого можно использовать:
- ClamAV — open-source антивирус с API и CLI;
- VirusTotal API — облачное решение для анализа файлов (ограничения по количеству запросов);
- Встроенные средства облачных провайдеров (AWS GuardDuty, Azure Defender).
Логирование и мониторинг
Централизованное логирование
Все значимые события должны отправляться в централизованную систему логирования:
- Успешные и неудачные попытки входа;
- Изменение пароля или email;
- Доступ к защищённым эндпоинтам;
- Ошибки безопасности (403, 429, SQL-ошибки).
Формат лога должен быть структурированным (например, JSON):
{
"timestamp": "2026-03-10T12:34:56Z",
"level": "warn",
"event": "failed_login",
"user_id": null,
"ip": "203.0.113.42",
"user_agent": "Mozilla/5.0 ...",
"path": "/api/auth/login"
}
Системы мониторинга
Интеграция с системами вроде Prometheus + Grafana или ELK Stack позволяет:
- Визуализировать метрики (запросы в секунду, ошибки 5xx, время ответа);
- Настраивать алерты на аномалии (например, рост 403-ошибок);
- Выполнять корреляционный анализ между событиями.
Пример правила в Alertmanager:
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate detected"
План реагирования на инциденты
Этапы реагирования
- Обнаружение — фиксация подозрительного события (лог, алерт, жалоба пользователя).
- Сдерживание — изоляция затронутых компонентов (блокировка IP, отзыв токенов, отключение сервиса).
- Устранение — устранение первопричины (патч уязвимости, удаление вредоносного кода).
- Восстановление — возврат системы в рабочее состояние (развертывание из резервной копии, повторная аутентификация).
- Постинцидентный анализ — документирование причин, последствий и мер по предотвращению повторения.
Документирование
План должен содержать:
- Контакты ответственных лиц (SOC, DevOps, юристы);
- Шаблоны уведомлений пользователям и регуляторам;
- Процедуры сбора доказательств (forensics);
- Список критически важных активов и точек восстановления.
Безопасность в разных языках
Разные языки программирования предоставляют разные инструменты, парадигмы и встроенные механизмы защиты. Понимание особенностей безопасности каждого языка позволяет избежать типичных ошибок и использовать платформу максимально надёжно. Ниже описаны ключевые практики для наиболее распространённых языков бэкенд-разработки.
JavaScript / Node.js
Защита HTTP-трафика и заголовков
Node.js не предоставляет встроенных механизмов защиты от уязвимостей уровня приложения. Поэтому разработчики обязаны явно внедрять меры безопасности через middleware и сторонние библиотеки.
Helmet — стандартная библиотека для установки безопасных HTTP-заголовков:
X-Content-Type-Options: nosniffX-Frame-Options: DENYContent-Security-PolicyStrict-Transport-Security
const helmet = require('helmet');
const express = require('express');
const app = express();
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.trusted.com"],
styleSrc: ["'self'", "'unsafe-inline'"]
}
},
hsts: { maxAge: 31536000, includeSubDomains: true }
}));
Защита от XSS и HTML-инъекций
При работе с пользовательским HTML-контентом необходимо применять санитизацию. Библиотека sanitize-html удаляет потенциально опасные теги и атрибуты:
const sanitizeHtml = require('sanitize-html');
const clean = sanitizeHtml(userInput, {
allowedTags: ['b', 'i', 'em', 'strong'],
allowedAttributes: {}
});
Никогда не используйте innerHTML или аналоги без предварительной очистки.
Запрет динамического выполнения кода
Функции eval(), new Function(), setTimeout(string) и setInterval(string) позволяют выполнять произвольный JavaScript-код. Их использование открывает прямой путь к RCE (Remote Code Execution).
Вместо eval(jsonString) всегда применяйте JSON.parse().
Управление зависимостями
Экосистема npm содержит миллионы пакетов, многие из которых содержат уязвимости или являются поддельными (typosquatting, dependency confusion).
Рекомендуемые практики:
- Регулярный запуск
npm audit - Интеграция Snyk или Socket.dev в CI/CD
- Использование
.npmrcс ограничением источников пакетов - Проверка авторов и количества загрузок перед установкой
Python (Django, Flask)
Django: безопасность «из коробки»
Django предоставляет встроенную защиту от большинства распространённых уязвимостей:
- Автоматическое экранирование переменных в шаблонах
- Защита от CSRF через middleware и токены
- ORM с параметризованными запросами
- Валидация форм и моделей
Пример защиты от CSRF в шаблоне:
<form method="post">
{% csrf_token %}
<!-- поля формы -->
</form>
Flask: ручная настройка защиты
Flask — микрофреймворк, не включающий защиту по умолчанию. Разработчик должен явно подключать компоненты:
- Flask-Talisman — для CSP, HSTS, X-Frame-Options
- Flask-WTF — для CSRF-токенов
- WTForms — для валидации входных данных
from flask import Flask
from flask_talisman import Talisman
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY')
Talisman(app, force_https=True)
CSRFProtect(app)
Анализ кода и зависимостей
- Bandit — статический анализатор Python-кода на наличие уязвимостей (например, использование
pickle,exec, небезопасные вызовы ОС) - Safety или pip-audit — проверка зависимостей на наличие CVE
Запуск анализа:
bandit -r .
safety check
Управление конфигурацией
Чувствительные данные (ключи, пароли) должны храниться в переменных окружения, а не в коде. Для удобства используется python-dotenv:
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.getenv('SECRET_KEY')
Файл .env добавляется в .gitignore.
Java (Spring Boot)
Spring Security: комплексная защита
Spring Security — мощная платформа для аутентификации, авторизации и защиты веб-приложений. Она поддерживает:
- OAuth2, OpenID Connect, JWT
- RBAC и метод-level security (
@PreAuthorize) - Защиту от CSRF, XSS, clickjacking
- Настройку CORS и CSP
Пример конфигурации:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // или настроить правильно
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'"))
.httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).maxAgeInSeconds(31536000))
.frameOptions().deny()
)
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
Криптографическая безопасность
Для генерации токенов, солей и случайных значений следует использовать SecureRandom, а не Math.random():
SecureRandom random = new SecureRandom();
byte[] bytes = new byte[32];
random.nextBytes(bytes);
String token = Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
Анализ зависимостей
OWASP Dependency-Check сканирует зависимости проекта (Maven, Gradle) на наличие известных уязвимостей:
dependency-check.sh --scan ./target
Интеграция возможна через плагины Maven/Gradle или CI/CD.
Экранирование вывода
Для предотвращения XSS при ручном формировании HTML используйте OWASP Java Encoder:
String safeOutput = Encode.forHtml(userInput);
PHP
Защита от SQL Injection
Используйте PDO с подготовленными выражениями вместо устаревших функций mysql_*:
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
Это гарантирует разделение кода и данных.
Хеширование паролей
PHP предоставляет встроенные функции для безопасного хеширования:
$hash = password_hash($password, PASSWORD_ARGON2ID);
if (password_verify($input, $hash)) {
// пароль верен
}
Алгоритм Argon2id считается современным стандартом.
Экранирование вывода
Для предотвращения XSS экранируйте вывод в HTML:
echo htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
Конфигурация сервера
- Отключите
display_errorsв production - Включите
log_errors - Используйте
.htaccessили Nginx для запрета доступа к.env,composer.json,vendor/
C# (.NET Core)
ASP.NET Core Identity
Встроенная система управления пользователями, поддерживающая:
- Регистрацию и вход
- Подтверждение email и телефона
- Восстановление пароля
- Двухфакторную аутентификацию (MFA)
Data Protection API
Шифрование cookies, токенов и других чувствительных данных:
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo("/keys"))
.SetApplicationName("MyApp");
Ключи можно хранить в Azure Key Vault или защищённой директории.
Защита от CSRF
Используйте атрибут [ValidateAntiForgeryToken] в контроллерах и токены в формах:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult UpdateProfile(ProfileModel model)
{
// обработка
}
Entity Framework и SQL Injection
Entity Framework автоматически использует параметризованные запросы при работе с LINQ:
var user = context.Users.FirstOrDefault(u => u.Email == email);
Этот код безопасен от SQL Injection.
Безопасные HTTP-заголовки
Настройка через middleware:
app.Use(async (ctx, next) => {
ctx.Response.Headers.Add("X-Frame-Options", "DENY");
ctx.Response.Headers.Add("Content-Security-Policy", "default-src 'self'");
await next();
});
PHP
Защита от SQL-инъекций через PDO
PDO (PHP Data Objects) — это расширение PHP, предоставляющее унифицированный интерфейс для работы с различными СУБД. Оно поддерживает параметризованные запросы, которые полностью отделяют пользовательские данные от исполняемого SQL-кода.
Использование mysql_query() или конкатенации строк при построении запросов считается устаревшим и опасным.
// ❌ Небезопасно
$query = "SELECT * FROM users WHERE email = '" . $_POST['email'] . "'";
$result = mysql_query($query);
// ✅ Безопасно через PDO
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$_POST['email']]);
$user = $stmt->fetch();
Параметр PDO::ATTR_EMULATE_PREPARES => false гарантирует, что подготовленные выражения обрабатываются на стороне СУБД, а не эмулируются в PHP.
Хеширование паролей
PHP предоставляет встроенные функции для безопасного хеширования паролей:
password_hash()— создаёт криптографически стойкий хеш с автоматической генерацией соли;password_verify()— проверяет соответствие пароля и хеша без риска тайминг-атак.
Алгоритм PASSWORD_ARGON2ID рекомендуется как современный стандарт.
$hash = password_hash($password, PASSWORD_ARGON2ID);
if (password_verify($inputPassword, $hash)) {
// Пароль верен
}
Никогда не храните пароли в открытом виде или используйте устаревшие алгоритмы (md5, sha1).
Экранирование вывода
Для предотвращения XSS при выводе пользовательских данных в HTML применяется функция htmlspecialchars():
echo htmlspecialchars($userInput, ENT_QUOTES | ENT_HTML5, 'UTF-8');
Флаг ENT_QUOTES обеспечивает экранирование одинарных и двойных кавычек, что критично для атрибутов тегов.
Конфигурация сервера и окружения
Чувствительные файлы (.env, composer.json, vendor/) не должны быть доступны через веб-сервер. Рекомендуется:
- Добавить их в
.htaccess(Apache) илиnginx.conf(Nginx) с правилом запрета доступа; - Отключить
display_errorsв production; - Включить
log_errorsи направить логи в защищённую директорию; - Использовать
.envчерез библиотекуvlucas/phpdotenv, исключив его из Git.
Пример .htaccess:
<FilesMatch "\.(env|json|lock|xml)$">
Require all denied
</FilesMatch>
Options -Indexes
Ruby (Ruby on Rails)
Встроенная защита от XSS и CSRF
Ruby on Rails по умолчанию применяет автоматическое экранирование переменных в шаблонах ERB. Любая строка, вставленная через <%= %>, проходит через html_escape.
Защита от CSRF реализована через middleware ActionController::RequestForgeryProtection. При каждом POST-запросе проверяется наличие токена, сгенерированного в форме:
<%= form_with model: @post do |f| %>
<%= f.text_field :title %>
<%= f.submit %>
<% end %>
Этот хелпер автоматически вставляет скрытое поле с CSRF-токеном.
Strong Parameters
Strong Parameters — механизм фильтрации входных данных в контроллерах. Он предотвращает массовое присваивание недопустимых атрибутов (mass assignment vulnerability).
def user_params
params.require(:user).permit(:name, :email)
end
Только разрешённые поля (name, email) могут быть использованы при создании или обновлении модели.
Управление зависимостями
Зависимости управляются через Gemfile. Для анализа уязвимостей используется:
bundle audit— проверяет gem’ы на наличие CVE;snyk test— интеграция с облачным сканером.
Рекомендуется регулярно обновлять зависимости и использовать Gemfile.lock для воспроизводимости сборок.
Go
Безопасность на уровне стандартной библиотеки
Go не предоставляет встроенных фреймворков безопасности, но стандартная библиотека net/http позволяет реализовать защиту через middleware.
Пример middleware для CORS и заголовков:
func securityMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("Content-Security-Policy", "default-src 'self'")
if r.TLS != nil {
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
}
next.ServeHTTP(w, r)
})
}
Параметризованные запросы к базе данных
Пакет database/sql поддерживает параметризованные запросы:
var name string
err := db.QueryRow("SELECT name FROM users WHERE id = ?", userID).Scan(&name)
Это предотвращает SQL Injection независимо от используемого драйвера (PostgreSQL, MySQL и др.).
Криптография
Стандартный пакет crypto/* предоставляет реализации:
crypto/rand— для генерации криптографически стойких случайных значений;crypto/sha256,crypto/hmac— для хеширования и подписей;golang.org/x/crypto/argon2— для хеширования паролей.
Пример генерации токена:
token := make([]byte, 32)
_, err := rand.Read(token)
if err != nil {
// обработка ошибки
}
encoded := base64.URLEncoding.EncodeToString(token)
Rust
Безопасность памяти на этапе компиляции
Rust гарантирует отсутствие типичных уязвимостей, связанных с управлением памятью:
- Переполнение буфера;
- Использование после освобождения (use-after-free);
- Гонки данных (data races).
Эти свойства обеспечиваются системой владения (ownership) и заимствования (borrowing), проверяемой на этапе компиляции.
Безопасные крейты
При выборе зависимостей из crates.io следует отдавать предпочтение:
- Популярным и хорошо поддерживаемым библиотекам;
- Тем, которые не используют
unsafeблоки; - Прошедшим аудит сообщества.
Инструменты анализа:
cargo audit— проверяет зависимости на наличие CVE;cargo deny— настраивает политики лицензирования и безопасности.
Веб-фреймворки
Фреймворки вроде Actix Web и Axum позволяют легко внедрять middleware для:
- Валидации входных данных;
- Установки безопасных заголовков;
- Rate limiting через Redis.
Пример установки CSP в Axum:
use axum::{
response::{IntoResponse, Response},
middleware::{self, Next},
http::Request,
};
async fn security_headers<B>(req: Request<B>, next: Next<B>) -> Response {
let mut res = next.run(req).await.into_response();
res.headers_mut().insert(
axum::http::header::CONTENT_SECURITY_POLICY,
"default-src 'self'".parse().unwrap(),
);
res
}