description: Изучите ключевые практики безопасности для Express-приложений в production: TLS, валидация ввода, безопасные cookie и защита от уязвимостей.¶
Лучшие практики production: безопасность¶
Термин "production" обозначает этап жизненного цикла ПО, когда приложение или API уже доступно конечным пользователям. В отличие от этого, на этапе "development" код активно пишется и тестируется, а приложение обычно недоступно извне. Соответствующие окружения называются production и development.
Окружения development и production обычно настроены по-разному и имеют сильно отличающиеся требования. То, что допустимо в development, может быть неприемлемо в production. Например, подробные логи ошибок полезны для отладки, но в production могут стать угрозой безопасности. В development можно меньше думать о масштабируемости, надежности и производительности, а в production это критично.
Если вы считаете, что нашли уязвимость в Express, см. Security Policies and Procedures.
Практики безопасности для Express-приложений в production включают:
- Лучшие практики production: безопасность
Не используйте устаревшие или уязвимые версии Express¶
Express 2.x и 3.x больше не поддерживаются. Проблемы безопасности и производительности в этих версиях не исправляются. Не используйте их. Если вы еще не перешли на версию 4+, следуйте migration guide или рассмотрите Commercial Support Options.
Также убедитесь, что не используете уязвимые версии Express из Security updates. Если используете — обновитесь до стабильной версии, предпочтительно последней.
Используйте TLS¶
Если приложение работает с чувствительными данными или передает их, используйте Transport Layer Security (TLS) для защиты соединения и данных. Эта технология шифрует данные перед отправкой от клиента к серверу и защищает от ряда распространенных атак. Хотя Ajax- и POST-запросы могут казаться «скрытыми» в браузере, сетевой трафик подвержен packet sniffing и man-in-the-middle attacks.
Возможно, вам знакомо шифрование Secure Socket Layer (SSL). TLS is simply the next progression of SSL. Иными словами, если вы использовали SSL, стоит перейти на TLS. Обычно для терминации TLS рекомендуют Nginx. Для настройки TLS на Nginx (и других серверах) см. Recommended Server Configurations (Mozilla Wiki).
Удобный способ получить бесплатный TLS-сертификат — Let's Encrypt, открытый автоматизированный центр сертификации (CA) от Internet Security Research Group (ISRG).
Не доверяйте пользовательскому вводу¶
Для веб-приложений одно из ключевых требований безопасности — корректная валидация и обработка пользовательского ввода. Формы ввода бывают разными, и здесь мы не покрываем все случаи. В конечном итоге ответственность за проверку и безопасную обработку вводимых данных лежит на вас.
Предотвращайте open redirects¶
Пример потенциально опасного ввода — open redirect, когда приложение принимает URL от пользователя (часто в query, например ?url=https://example.com) и через res.redirect устанавливает заголовок location, возвращая статус 3xx.
Приложение должно проверять, допустим ли редирект на переданный URL, чтобы не отправлять пользователей на вредоносные ссылки (например, фишинговые сайты).
Вот пример проверки URL перед использованием res.redirect или res.location:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Используйте Helmet¶
Helmet помогает защитить приложение от ряда известных веб-уязвимостей за счет корректной настройки HTTP-заголовков.
Helmet — это middleware, который выставляет security-related HTTP response headers. По умолчанию он задает:
Content-Security-Policy: строгий allow-list действий на странице, снижающий множество атакCross-Origin-Opener-Policy: помогает изолировать страницу на уровне процессаCross-Origin-Resource-Policy: блокирует cross-origin загрузку ваших ресурсовOrigin-Agent-Cluster: делает изоляцию процессов origin-basedReferrer-Policy: управляет заголовкомRefererStrict-Transport-Security: указывает браузерам предпочитать HTTPSX-Content-Type-Options: предотвращает MIME sniffingX-DNS-Prefetch-Control: управляет DNS prefetchingX-Download-Options: принудительно сохраняет загрузки (только Internet Explorer)X-Frame-Options: устаревший заголовок для смягчения ClickjackingX-Permitted-Cross-Domain-Policies: контролирует cross-domain поведение продуктов Adobe, например AcrobatX-Powered-By: информация о веб-сервере; удаляется, так как может помогать простым атакамX-XSS-Protection: устаревший заголовок для смягчения XSS attacks, который может ухудшать безопасность, поэтому Helmet его отключает
Каждый заголовок можно настроить или отключить. Подробнее — в документации Helmet.
Установите Helmet как обычный модуль:
1 | |
Затем подключите его в коде:
1 2 3 4 5 6 | |
Снижайте fingerprinting¶
Дополнительным уровнем защиты является снижение возможности определить ПО, используемое сервером — так называемый "fingerprinting". Сам по себе fingerprinting не всегда уязвимость, но уменьшение его точности улучшает общий профиль безопасности. ПО сервера часто определяется по особенностям ответов на запросы, например по HTTP-заголовкам.
По умолчанию Express отправляет заголовок X-Powered-By, который можно отключить через app.disable():
1 | |
Отключение заголовка X-Powered-By не мешает опытному атакующему определить, что приложение работает на Express. Это может отпугнуть только простые атаки — существуют и другие способы определить стек.
Express также отправляет собственные форматированные сообщения "404 Not Found" и ошибки форматтера. Это можно изменить, добавив свой not found handler и написав свой error handler:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Используйте cookie безопасно¶
Чтобы cookie не открывали путь к атакам, не используйте имя session cookie по умолчанию и задавайте безопасные параметры cookie.
Есть два основных middleware-модуля для cookie-сессий:
- express-session, который заменяет встроенный в Express 3.x middleware
express.session. - cookie-session, который заменяет встроенный в Express 3.x middleware
express.cookieSession.
Ключевое различие между ними — способ хранения данных сессии. Middleware express-session хранит данные сессии на сервере; в cookie сохраняется только session ID, а не сами данные. По умолчанию используется in-memory storage, который не предназначен для production. В production нужен масштабируемый session-store; см. список compatible session stores.
В отличие от этого, middleware cookie-session использует cookie-backed storage: сериализует в cookie всю сессию, а не только ключ. Используйте его, только если данные сессии небольшие и легко кодируются примитивами (а не объектами). Хотя браузеры обычно поддерживают как минимум 4096 байт на cookie, чтобы не выйти за лимит, ориентируйтесь на 4093 байта на домен. Также помните: данные cookie видны клиенту, поэтому если нужна большая защищенность/скрытность, express-session обычно лучше.
Не используйте имя session cookie по умолчанию¶
Использование стандартного имени session cookie может упростить атаки. Проблема похожа на X-Powered-By: потенциальный атакующий может использовать это для fingerprinting сервера и выбора целевых атак.
Чтобы избежать этого, используйте нейтральные имена cookie; например, с middleware express-session:
1 2 3 4 5 6 7 8 | |
Настройте параметры безопасности cookie¶
Для усиления безопасности задайте следующие опции cookie:
secure— гарантирует, что браузер отправляет cookie только по HTTPS.httpOnly— гарантирует, что cookie отправляется только по HTTP(S), а не доступен клиентскому JavaScript, что помогает защититься от XSS.domain— задает домен cookie; сравнивается с доменом сервера, к которому идет запрос.path— задает путь cookie; сравнивается с путем запроса.expires— задает дату истечения для persistent cookie.
Ниже пример с middleware cookie-session:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Предотвращайте brute-force атаки на авторизацию¶
Убедитесь, что endpoints входа защищены, чтобы лучше защищать приватные данные.
Простой и эффективный подход — блокировать попытки авторизации по двум метрикам:
- Число последовательных неудачных попыток для одной пары «имя пользователя + IP-адрес».
- Число неудачных попыток с одного IP-адреса за длительный период. Например, блокируйте IP, если за день он совершил 100 неудачных попыток.
Пакет rate-limiter-flexible дает инструменты для быстрой реализации этой техники. Пример есть в документации: login-endpoint protection
Следите за безопасностью зависимостей¶
Использовать npm для управления зависимостями удобно и эффективно. Но пакеты могут содержать критические уязвимости, которые затронут и ваше приложение. Безопасность приложения определяется «самым слабым звеном» в зависимостях.
Начиная с npm@6, npm автоматически проверяет каждый запрос на установку. Также можно использовать npm audit для анализа дерева зависимостей.
1 | |
Если нужна более строгая безопасность, рассмотрите Snyk.
Snyk предлагает и CLI-инструмент, и интеграцию с GitHub, которая проверяет приложение по базе уязвимостей open source от Snyk на наличие известных проблем в зависимостях. Установите CLI так:
1 2 | |
Используйте эту команду для проверки приложения на уязвимости:
1 | |
Избегайте других известных уязвимостей¶
Следите за advisory в Node Security Project и Snyk, которые могут затрагивать Express и другие используемые модули. В целом это отличные источники знаний и инструментов по безопасности Node.
Наконец, Express-приложения, как и любые веб-приложения, могут быть уязвимы к различным веб-атакам. Изучите известные web vulnerabilities и принимайте меры защиты.
Дополнительные рекомендации¶
Ниже — дополнительные рекомендации из Node.js Security Checklist. За подробностями обращайтесь к оригинальной статье:
- Всегда фильтруйте и санитизируйте пользовательский ввод для защиты от XSS и command injection.
- Защищайтесь от SQL injection с помощью параметризованных запросов или prepared statements.
- Используйте open-source инструмент sqlmap для поиска SQL injection уязвимостей.
- Используйте nmap и sslyze для проверки SSL-конфигурации (шифры, ключи, renegotiation) и валидности сертификата.
- Используйте safe-regex, чтобы убедиться, что ваши регулярные выражения не подвержены regular expression denial of service.