Гид по технологиям

Безопасность Express.js: руководство по защите серверных приложений

7 min read Безопасность Обновлено 04 Jan 2026
Безопасность Express.js — руководство по защите
Безопасность Express.js — руководство по защите

Замок поверх фона с кодом

Введение

Express.js — лёгкий и быстрый фреймворк для Node.js. Он отлично подходит для создания API и серверной логики, но по умолчанию не обеспечивает всех уровней безопасности. Пропуски в конфигурации, отсутствие валидации данных и неверные заголовки HTTP делают приложение уязвимым.

Это руководство показывает практические меры защиты: от простых и быстрых (установить Helmet, отключить лишние заголовки) до более системных (валидация, CORS, rate limiting, управление секретами и процессы приёма/рейлбек).

Важно: безопасность — это процесс. Обновляйте зависимости, тестируйте и мониторьте продакшен.

Установка и демонстрационный сервер Express.js

Ниже — минимальные шаги для локального демо-проекта. Эти команды выполняют в терминале.

mkdir express-project
cd express-project

Создайте package.json по умолчанию:

npm init -y

Установите Express:

npm install express

Создайте файл server.js и вставьте базовый сервер:

const express = require("express")
const app = express()
const PORT = process.env.PORT || 5000

app.get("/", (req, res) => {
    res.json("Hello, World!")
})

app.listen(PORT, () => {
    console.log(`Starting server on http://localhost:${PORT}`)
})

Запустите сервер:

node server.js

Теперь у вас есть простое API, на котором можно отрабатывать советы из этого руководства.

1. HTTP‑заголовки и Helmet

Человек за столом печатает код на ноутбуке

Helmet — это пакет с набором middleware для установки безопасных HTTP‑заголовков. Он закрывает множество типичных путей атаки, если их правильно настроить.

Почему это важно

Express по умолчанию не выставляет набор защитных заголовков и оставляет полезную, но опасную подсказку X-Powered-By. Удаление этой подсказки и добавление других заголовков сокращает доступную для злоумышленника информацию и уменьшает поверхность атаки.

Просмотр заголовков без Helmet

При запросе к корневому эндпоинту вы можете увидеть заголовки с помощью Postman или инструментов браузера. Часто встречается заголовок X-Powered-By, который стоит удалить в продакшене.

Результат ответа HTTP с заголовками в клиенте Postman

Удаление заголовка X-Powered-By:

app.disable('x-powered-by')

Тестирование конфигурации заголовков

Чтобы получить внешний взгляд на заголовки, воспользуйтесь сервисом Security Headers (securityheaders.com). Для локального сервера можно использовать ngrok, чтобы открыть временный публичный URL.

  1. Скачайте и запустите ngrok.
ngrok http 5000

Информация ngrok в терминале

  1. Скопируйте forwarding URL в поле Security Headers и нажмите Scan.

Поле ввода forwarding URL в Security Headers

Если не использовать Helmet, отчёт часто показывает низкий рейтинг (например, F) из‑за отсутствующих заголовков.

Отчёт Security Headers с низкой оценкой

Интеграция Helmet

Установите пакет:

npm install helmet

Импорт и подключение:

const helmet = require("helmet")
app.use(helmet())

После этого повторный скан часто показывает заметное улучшение.

Отчёт Security Headers с высокой оценкой

Что ещё настроить (примеры)

  • Content Security Policy (CSP) — ограничьте источники скриптов, стилей и изображений.
  • Strict-Transport-Security (HSTS) — принуждайте HTTPS.
  • Referrer-Policy — контролируйте передачу реферера.
  • X-Content-Type-Options: nosniff

Пример кастомной конфигурации Helmet с CSP:

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "https://trusted.cdn.example.com"],
      imgSrc: ["'self'", "data:"]
    }
  },
  hsts: { maxAge: 63072000, includeSubDomains: true },
}))

Совет: при разработке CSP может блокировать сторонние ресурсы. Настройте политики постепенно и проверяйте в тестовой среде.

2. Валидация и санитизация входных данных с помощью Joi

Joi позволяет объявлять схемы данных и валидировать входящие запросы. Это снижает риск инъекций, XSS и ошибок формата.

Установка и базовый пример:

npm install joi
const Joi = require('joi');

const schema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(5).max(16).required()
});

app.post('/register', express.json(), (req, res) => {
  const { error, value } = schema.validate(req.body);
  if (error) {
    return res.status(400).json({ error: error.details[0].message });
  }
  // продолжить обработку безопасных данных
  res.status(201).json({ ok: true });
});

Рекомендации по использованию в проме:

  • Включите express.json({ limit: ‘10kb’ }) чтобы ограничить размер тела запроса.
  • Проверяйте типы и диапазоны. Не полагайтесь только на фронтенд.
  • Для сложных схем разбивайте валидацию на отдельные middleware.
  • Именуйте ошибки так, чтобы не раскрывать внутренние детали приложения.

Альтернативы: express-validator, Yup — существуют и другие библиотеки. Выбор зависит от предпочтений и совместимости.

3. Управление CORS

CORS определяет, какие домены могут обращаться к API. Неправильная конфигурация разрешит нежелательный доступ.

Установка и пример:

npm install cors
const cors = require('cors');

const whitelist = ['https://app.example.com', 'https://admin.example.com'];
const corsOptions = {
  origin: function(origin, callback){
    if (!origin) return callback(null, true); // allow server-to-server or same-origin
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true
};

app.use(cors(corsOptions));

Рекомендации

  • В продакшене указывайте конкретные origin, а не app.use(cors()) без аргументов.
  • Включайте credentials только если нужны cookies/авторизация по сессии.
  • Обрабатывайте preflight запросы (OPTIONS) для сложных запросов.

Дополнительные меры безопасности

Ниже — комплекс мер, которые стоит применить параллельно с Helmet, Joi и CORS.

  • Ограничение частоты запросов (rate limiting). Пример: express-rate-limit.
  • Защита от brute-force при логине: задержки, капчи, блокировки по IP/учётной записи.
  • Безопасные cookie: HttpOnly, Secure, SameSite=strict/ Lax в зависимости от сценария.
  • HTTPS/TLS: всегда шифруйте трафик. Используйте HSTS.
  • Ограничение размера тела запроса: express.json({ limit: ‘10kb’ }).
  • Проверка зависимостей: npm audit, Snyk, Dependabot.
  • Управление секретами: не храните секреты в репозитории, используйте vault или секреты CI/CD.
  • Логи и мониторинг: централизованный сбор логов, оповещения по аномалиям.
  • Защита от утечек: минимизация данных в ответах, удаление подробных стектрейсов в проде.

Пример минимальной подборки middleware:

const rateLimit = require('express-rate-limit');
app.use(express.json({ limit: '10kb' }));
app.disable('x-powered-by');
app.use(helmet());
app.use(cors(corsOptions));
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 }));

Методология «Secure-by-Default» — мини‑руководство

  1. Проектирование: определите данные и требования конфиденциальности.
  2. Разработка: применяйте валидацию, ограничения и защищённые заголовки.
  3. Тестирование: автоматические тесты, SAST/DAST, сканирование зависимостей.
  4. Деплой: проверка конфигурации TLS, секретов и доступов.
  5. Эксплуатация: мониторинг, инцидент-менеджмент и обновления.

Ролевые чеклисты

Разработчик:

  • Включить express.json({ limit })
  • Валидировать все входные данные
  • Не раскрывать внутренние ошибки в ответах
  • Использовать helmet и отключить x-powered-by

DevOps / Инженер релиза:

  • Настроить TLS и HSTS
  • Хранить секреты в защищённом хранилище
  • Обновлять Node.js и пакеты по SLA
  • Настроить CI/CD с проверками безопасности

Инженер безопасности:

  • Проводить регулярные сканирования зависимостей
  • Тестировать CSP и заголовки
  • Анализ логов и настройка оповещений

Продуктовый менеджер:

  • Оценить, какие персональные данные обрабатываются
  • Утвердить сроки хранения и политику доступа
  • Обеспечить выделение ресурсов на безопасность

SOP для развёртывания безопасного сервера (короткая версия)

  1. Локальная подготовка: установить зависимости, прогнать тесты, выполнить lint.
  2. Проверка безопасности: npm audit, линтеры безопасности, статический анализ.
  3. Настройка окружения: секреты, переменные, TLS сертификаты.
  4. Деплой на staging: включить мониторинг и журналирование.
  5. Проверка в staging: функциональные тесты, securityheaders.com скан, автоматические тесты.
  6. Выпуск в production: по каналу CI/CD, с откатом в 1 клик и пошаговым мониторингом.
  7. Пост‑деплой: наблюдение, сбор метрик и быстрый откат при проблемах.

Критерии приёмки

  • Все критические заголовки установлены (CSP, HSTS, X-Content-Type-Options и т.д.).
  • API валидирует входные данные и возвращает 400 при неправильном формате.
  • CORS разрешает только утверждённые origin.
  • Максимальный размер тела запросов ограничен.
  • Логи настроены и отправляются в централизованную систему.

Тесты и примеры приёмки

Тест‑кейс 1 — Заголовки

  • Запросить корневой эндпоинт.
  • Ожидается наличие заголовков Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options.

Тест‑кейс 2 — Валидация

  • Послать POST /register с некорректной почтой.
  • Ожидаемый код 400 и понятное сообщение об ошибке.

Тест‑кейс 3 — CORS

  • Сделать запрос с origin запрещённого домена.
  • Ожидается ошибка CORS и отсутствие ответа с данными.

Тест‑кейс 4 — Rate limiting

  • Отправить 200 запросов за короткое время.
  • Ожидается 429 после достижения лимита.

Решения, когда стандартные методы не подходят

  • Если приложение должно быть публичным и принимать запросы со множества доменов, управляйте доступом через API‑ключи и авторизацию вместо широкого разрешения CORS.
  • Если CSP ломает сторонние виджеты (аналитика, виджеты оплаты), применяйте политикy по эндпоинтам, а не глобально.
  • Для внутреннего API используйте mTLS или VPN вместо экспонирования через публичный интернет.

Модель принятия решения (Mermaid)

flowchart TD
  A[Нужна защита API?] -->|Да| B{Тип клиента}
  B --> C[Браузер]
  B --> D[Серверное приложение]
  C --> E[Включить CORS с whitelist]
  C --> F[Добавить CSP и Helmet]
  D --> G[Ограничить IP / mTLS]
  D --> H[Использовать статические ключи / JWT]
  E --> I[Добавить валидацию Joi]
  F --> I
  G --> I
  H --> I
  I --> J[Мониторинг и rate limit]

Безопасность данных и соответствие требованиям (GDPR и приватность)

Если вы храните или обрабатываете персональные данные граждан ЕС, учтите:

  • Правовая база обработки (согласие, контракт, законный интерес).
  • Минимизация: храните только необходимые поля.
  • Контроль прав доступа и шифрование данных в покое и в движении.
  • Политика хранения и удаления данных (retention).
  • Процесс уведомления об утечке и DPIA для высокорисковых обработок.

Важно согласовать хранение логов и метрик с политикой приватности. Анонимизируйте персональные данные в логах.

Безопасное конфигурирование сессий и cookie

  • Устанавливайте cookie-флаги: HttpOnly, Secure, SameSite.
  • Для JWT храните токены с кратким сроком жизни и механикой отката (revocation list) при необходимости.
  • Рассмотрите server-side сессии с хранилищем Redis + TTL и защитой от перебора.

Пример конфигурации cookie для express-session:

const session = require('express-session');
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { secure: true, httpOnly: true, sameSite: 'lax', maxAge: 24 * 60 * 60 * 1000 }
}));

Меры безопасности при деплое и эксплуатации

  • Используйте CI/CD с проверками безопасности.
  • Автоматизируйте обновление зависимостей и патчи.
  • Настройте алерты на аномальные паттерны запросов (spike, unusual endpoints).
  • Проводите периодические пентесты и DAST-сканы.

Краткий справочник команд и сниппетов

  • Установка основных пакетов:
npm install express helmet cors joi express-rate-limit express-session
  • Ограничение размера тела:
app.use(express.json({ limit: '10kb' }))
  • Отключение подсказок фреймворка:
app.disable('x-powered-by')

Совместимость и миграция

  • Проверяйте совместимость middleware с версией Node.js и Express. Тестируйте ручные сценарии при переходе на следующую LTS.
  • Для крупных апдейтов сначала мигрируйте на staging, выполните регрессию и нагрузочное тестирование.

Риски и смягчения

  • Уязвимости зависимостей: регулярно сканируйте и обновляйте.
  • Неправильная конфигурация CORS: используйте whitelist и логи для выявления проблем.
  • Пробелы в валидации: автоматические тесты и code review.

Заключение

Защита Express.js — сочетание правильной конфигурации, валидации данных, управления доступом и процессов. Начните с простого: добавьте helmet, отключите x-powered-by, валидируйте ввод, ограничьте CORS и примените rate limiting. Затем расширяйте набор мер: мониторинг, проверка зависимостей, безопасное хранение секретов и регулярные тесты.

Важно: безопасность — это непрерывная работа, а не одноразовая настройка.

Important: всегда проверяйте конфигурации в staging и имейте готовый план отката.

Краткое резюме

  • Используйте Helmet для заголовков.
  • Валидируйте входящие данные Joi или альтернативами.
  • Ограничивайте CORS и настройте rate limiting.
  • Обеспечьте шифрование, управление секретами и мониторинг.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство